What a JWT contains
A JWT (JSON Web Token, RFC 7519) is three base64url-encoded parts separated by dots: a header that says how the token is signed, a payload of claims about the user or client, and a signature. The header and payload are encoded, not encrypted, so anyone holding the token can read them. This tool does exactly that, and pretty-prints the JSON.
Times in a JWT (exp, iat, nbf) are NumericDates: seconds since 1 January 1970, UTC. The tool shows each as a date in your time zone and relative to now, and tells you whether the token has expired.
How to use the JWT Decoder
- Paste a token, or press Sample. A
Bearerprefix, quotes and line breaks are removed automatically. - Read the header and payload, pretty-printed.
- Check the times: when the token was issued, and whether it has expired.
- Look up a claim in the claims table, or copy the header or payload as JSON.
Examples
An access token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzEwNDIiLCJuYW1lIjoiQWRhIExvdmVsYWNlIiwic2NvcGUiOiJvcmRlcnM6cmVhZCBvcmRlcnM6d3JpdGUiLCJpYXQiOjE3NjcyMjU2MDAsImV4cCI6MTc2NzIyOTIwMH0.ZTQv-yowazock7ytfMs4-olE6W8qmbhUpz8ioswvBP8{
"sub": "user_1042",
"name": "Ada Lovelace",
"scope": "orders:read orders:write",
"iat": 1767225600,
"exp": 1767229200
}iat is 1 January 2026, 00:00 UTC and exp an hour later, so the token was valid for one hour. The header shows it is signed with HS256.
Times in milliseconds by mistake
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzEwNDIiLCJpYXQiOjE3NjcyMjU2MDAwMDAsImV4cCI6MTc2NzIyOTIwMDAwMH0.bhEk_pCCaD3_cq7JGX0MZ4xgT5kcX6ikRxTWR2RD0bQ{
"sub": "user_1042",
"iat": 1767225600000,
"exp": 1767229200000
}Date.now() returns milliseconds, but JWT times are seconds. This token appears to expire in the year 57,970; the tool warns about it. Use Math.floor(Date.now() / 1000).
An unsigned token
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJ1c2VyXzEwNDIiLCJyb2xlIjoiYWRtaW4ifQ.{
"sub": "user_1042",
"role": "admin"
}The header says "alg": "none" and the signature is empty, so anyone could have made this token. Servers must reject unsigned tokens.
Decoding is not verification
Anyone can create a token with any payload. A token is only trustworthy after a server has checked its signature with the issuer's key: a shared secret for HS256, or a public key for RS256 and ES256. This tool doesn't verify signatures, and an application must never trust a decoded token that it hasn't verified.
Treat tokens like passwords: anyone who has one can use it until it expires. That's why this tool runs entirely in your browser, and why you shouldn't paste live tokens into tools that send them to a server.
Common claims
- iss (issuer) and aud (audience): who created the token and who it is for. A server should reject tokens meant for another audience.
- sub (subject): who the token is about, usually a user ID.
- exp, nbf and iat: when the token expires, when it becomes valid and when it was issued.
- scope or scp, roles, groups: what the token allows. Names vary by provider.
Limitations
- Signatures aren't verified; that needs the issuer's secret or public key.
- Encrypted tokens (JWE, five parts) can't be read without the recipient's key; the tool says so.
- Times are compared with your device's clock, without the few minutes of leeway many servers allow.
Frequently asked questions
Is my token sent to a server?
No. The token is decoded entirely in your browser; it is never uploaded, stored or logged. Once the page has loaded, it even works offline.
Can anyone read a JWT?
Yes. The header and payload are only base64url-encoded, so anyone with the token can read them. Don't put secrets in a JWT's payload; use an encrypted token (JWE) if the contents must be private.
Why does it say my token is valid when my API rejects it?
This tool only checks the times. An API also checks the signature, the issuer and the audience, and may allow less clock skew. Also check that the token is for the right environment.
What does exp mean?
exp is the expiration time: seconds since 1 January 1970 (UTC) after which the token must be rejected. In JavaScript, compare it with Date.now() / 1000, not Date.now().
Does it verify the signature?
No. Verifying needs the key the token was signed with, and a decoded token can't tell you whether it's genuine. Verify tokens in your server code with a maintained JWT library.