JWT Decoder Guide: Header, Payload and Expiry
Paste a token and you can read its header and payload in a second. Keep the distinction straight, though: decoding tells you what the token claims, not whether it is genuine. Only signature verification on the server answers that.
When you actually need to read a JWT
Your API returns 401 and you need to know whether the token expired, the audience does not match, or the signature check failed. Reading exp, aud and iss settles that faster than any log. When integrating someone else's single sign-on, decoding the claims is often the only documentation you get.
The other common case is a permissions bug: which claim holds the role, is it nested under user.roles, did a gateway rename it. None of that is a signature problem, and reading the payload locates it immediately.
The three parts, and the time fields
A JWT is header.payload.signature, dot-separated. The first two segments are Base64URL-encoded JSON and the third is the signature. Base64URL, not Base64: it swaps + for -, / for _, and drops trailing padding, which is why some tokens fail in a plain Base64 decoder.
exp, iat and nbf are NumericDate values — seconds since 1970-01-01 UTC, not milliseconds and not local time. Ten digits is correct. If you see thirteen, someone stored milliseconds, and reading that as seconds puts the expiry tens of thousands of years out.
- exp is an upper bound, so allow 30–60 seconds of clock skew when checking it
- The payload is only Base64URL — anyone holding the token can read it, so keep personal data and secrets out
- Two segments, or an empty third one, means this is not a complete JWS
Limit: no signature check means no verification
A decoder cannot tell you whether the token was altered. That is exactly where the attacks live: alg set to none, RS256 swapped for HS256 with the public key reused as an HMAC secret, and jku, x5u or kid headers that make a server fetch a key the attacker controls.
Verify on the server with a maintained library, and pin an explicit algorithm allowlist instead of trusting the alg header. On the client, reading exp is enough to decide when to refresh. Any authorization decision belongs on the verified side.
FAQ
Is it safe to decode a JWT in the browser?
This tool decodes entirely in your browser; the token never leaves the page. Still treat a production token like a password: paste it only when you have to, and avoid sites you cannot inspect that send the value to a server.
Why does it say this is not a valid JWT?
Three usual causes: the last segment was cut off when copying, a Bearer prefix is still attached, or the value is a JWE with five segments rather than a JWS. Base64URL also drops padding, which trips up some decoders.
Can this tell me whether a token was tampered with?
No. Decoding skips the signature, so an edited payload re-encoded in Base64URL renders just fine. The only way to know is to verify the signature with the key on the server and check exp, aud and iss.
Related tool:JWT Decoder