JWT Decoder
Paste a JSON Web Token and see its header and claims, with the expiry and issued-at timestamps converted into actual dates. It runs entirely in this tab, which matters more here than on any other tool on this site: a JWT is usually a live credential, and pasting one into a decoder that posts it to a server is handing someone your session.
Use this without the search next time. Prathom Workbench puts Prathom's tools in your toolbar.
Add to Chrome — freeWhat it does
- Header and payload decoded and pretty-printed
- exp, iat and nbf converted to UTC dates with time remaining
- Accepts a pasted Authorization header, Bearer prefix and all
- States plainly that the signature is not verified
How to use JWT Decoder
- 1
Paste the token
Three dot-separated segments. A pasted Authorization header works too — the Bearer prefix is stripped rather than treated as an error, because that is how most tokens arrive.
- 2
Read the header
The alg field tells you which signature algorithm the token claims to use. That claim is made by whoever created the token, which is the whole reason it needs checking rather than trusting.
- 3
Check the timestamps
exp, iat and nbf are seconds since 1970, not milliseconds. They are shown as UTC dates with the time remaining, which is normally the actual question when a request is being refused.
- 4
Copy the payload
The payload is copied as formatted JSON, ready to paste into a bug report or a test fixture.
How it works
A JWT is three base64url segments separated by dots. Decoding it is not cryptography — it is string manipulation, and that is the single most important thing to understand about the format.
The first two segments are base64url-encoded JSON. Base64url is not Base64:
it uses - and _ in place of + and /, and it strips the trailing =
padding. The browser's atob accepts neither variation, so each segment has to
have its alphabet translated back and its padding restored before it can be
decoded at all. This is the most common reason a hand-rolled decoder reports a
valid token as malformed.
The third segment is the signature. It is bytes, not text, so it is left encoded and shown as-is. There is nothing useful to display and nothing that can be checked without the key.
The timestamp claims — exp, iat, nbf — are what the specification calls a
NumericDate: seconds since 1970, not milliseconds. JavaScript's Date takes
milliseconds, so the value has to be multiplied by a thousand. Missing that
produces dates in January 1970, and it is common enough that a token appearing to
be issued during the Nixon administration is a recognizable symptom rather than a
mystery.
Decoding is not validating
The alg: none example above is worth sitting with.
That token is well-formed. Every decoder will read it and report that the subject
is admin. Its signature segment is empty, because it claims not to have one.
Around 2015 it emerged that many JWT libraries would read the alg field out of
the header and use it to decide how to verify — so a token claiming none was
verified by doing nothing, and passed. The attacker chose the verification
algorithm. It affected a long list of well-known libraries, and the fix in every
case was the same: the application must decide which algorithms are acceptable
before it looks at the token, and reject anything else.
The reason a decoder should say all this out loud is that the output looks authoritative. A neatly formatted payload with a green tick beside it invites you to believe the claims. Nothing shown here has been checked, and the tool that shows it to you cannot check it.
When you'd use this
Working out why an API is returning 401 — nine times in ten the answer is in
exp and takes five seconds to find.
Confirming which user or scope a token actually carries, when a request is returning the wrong data and you want to know whether the token or the authorization logic is at fault.
Checking what an identity provider is putting in its tokens during an integration, especially the claims that are not in the documentation.
What not to paste here
The signing key, for any reason. No tool that runs in a browser needs it, and anything asking for one should be closed.
Beyond that, use judgment about production tokens even here. This page does not transmit anything and you can verify that with your network tab — but a token pasted into a browser can end up in that browser's session restore, and the habit of pasting live credentials into web pages is worth not having.
Examples
A standard HS256 token
The iat value is 1,516,239,022 seconds since 1970, not milliseconds — a distinction that produces dates in 1970 when it is missed, and is a recurring source of tokens that appear to have been issued fifty years ago. There is no exp claim here, so this token never expires by itself.
A token signed with nothing at all
A perfectly well-formed JWT claiming to be the admin, with an empty signature. This decodes cleanly here because decoding is not validation — and the fact that it looks completely normal is exactly why libraries that honored the alg field produced one of the best-known authentication bypasses of the last decade.
Frequently asked questions
Does this verify the signature?
No, and it will not. Verification requires the signing key, and a key pasted into a web page is a key you have to rotate. Anything a decoder can show you without the key is unverified by definition, including every claim in the payload. Treat this as a viewer, and do the verification in your application with a library that checks the algorithm against an allow-list.
Is my token sent anywhere?
No. The decoding is three string operations and a JSON parse, all performed in this tab. You can verify it by opening your developer tools and pasting a token in — no request carries it. This is worth caring about: a JWT from a production system is a live credential, and several popular online decoders post the token to their server to do the work.
Why can anyone read my token's contents?
Because a JWT is signed, not encrypted. The signature proves the payload has not been altered; it does nothing to hide it. The header and payload are plain base64url, readable by anyone holding the token, which is why nothing secret should ever be put in one. If the contents genuinely need to be hidden, the encrypted variant is JWE, which has five segments rather than three.
My token will not decode. What is wrong with it?
Almost always one of three things. A copied Authorization header still carrying the Bearer prefix, which this tool strips for you. A token truncated by a log viewer or a terminal, which loses the end of the signature and often the payload. Or a five-segment JWE, which is encrypted and cannot be read without the key. Whitespace and line breaks in the middle of a pasted token are also common and are not tolerated by the format.
What is the difference between exp and nbf?
exp is when the token stops being valid and nbf is when it starts. Both are optional and both are seconds since 1970. nbf matters for tokens issued ahead of time, and it is a frequent cause of a token that looks completely valid being rejected — the receiving system's clock is a few seconds behind the issuer's, so the token is technically not yet born. Most libraries allow a small leeway for exactly this reason.