jwt decoder
Decoded in this tab. Never paste a signing key anywhere.
Decoded in this tab. Anyone holding a token can read it the same way, which is the reason not to put anything private in one.
The short answer
A JWT is three base64url sections separated by dots, and the first two are plain JSON that anyone holding the token can read. Decoding is not verification: checking that a token is genuine needs the signing key, which is precisely the thing you should never paste into a web page.
Reads the header and payload of a JSON Web Token and spells out its dates. It cannot tell you whether a token is genuine, and no page that runs in a browser should try.
The formula
split on dots → base64url-decode the first two → parse as JSON
Worked examples
- Section one
- the header, naming the algorithm
- Section two
- the payload, the claims themselves
- Section three
- the signature, which this cannot check
Reference table
| Claim | Means | Worth checking |
|---|---|---|
| exp | Expires at | Yes, and it is a common bug |
| iat | Issued at | For debugging clock skew |
| nbf | Not valid before | Rare, and confusing when set |
| sub | Subject, usually a user id | Yes |
| aud | Audience the token is for | Yes, if you accept several |
How to use it
- 01Paste the tokenAll three sections. Decoding happens as you type, in the page.
- 02Read the payloadThe claims, formatted, with iat, nbf and exp turned into readable dates.
Also searched for
Searches that land here include jwt decoder, decode jwt, jwt debugger, read jwt token and jwt payload.
What a JWT is made of
Three sections, two of them readable
Header, payload, signature, joined with dots and each encoded as base64url. The header names the algorithm. The payload holds the claims. The signature is computed over the first two with a secret, which is what makes tampering detectable. Only the third part needs a key, and only to check it.
The claims worth looking at
exp is when the token stops being valid, and an exp that has passed is the single most common cause of a mysterious 401. iat is when it was issued, useful for spotting a client caching a token far longer than intended. sub is who it is about. aud is who it is for, and skipping that check is how a token minted for one service gets accepted by another.
The alg field is not a suggestion
A verifier must decide which algorithms it accepts before reading the token, not after. Trusting the header's own alg field is how the "alg: none" attack worked: the token said it needed no signature, and libraries believed it. Any library written since 2015 refuses that, and it is still worth knowing why.
Questions people ask
Why does it not verify the signature?
Because verifying needs the signing key, and a page asking you to paste your signing key into it would be giving you terrible advice. Verification belongs on the server that holds the secret. Decoding is a separate, harmless job: the payload is readable by anyone holding the token anyway.
Is a JWT encrypted?
No. The header and payload are base64url, which is an encoding and not encryption — this page decodes them with no key at all, and so can anyone else. The signature stops a token being altered; it does not stop it being read. Never put anything private in a JWT payload.
How is the expiry worked out?
The exp claim is a Unix timestamp in seconds, and it is compared against your own clock. If a token looks expired when the server thinks it is fine, or the reverse, clock skew between the two machines is the usual culprit, which is why most libraries allow a small tolerance.