Read a JWT — and separately, check one
Decode a token to see what it claims, or verify its signature against a key you supply. Those are different operations and the difference matters more than almost anything else on this page.
Anyone holding a token can decode it — there is no key involved and nothing is proven. Everything shown below is what the token claims, written by whoever produced it. To find out whether those claims are genuine, switch to Verify and supply the key.
Header
Payload
Processed locally in your browserNothing you enter here is uploaded, logged or sent to any server.
Why you choose the algorithm and the token does not
A JWT carries its own algorithm in its header, and a verifier that reads it and does as it says can be attacked in two well-documented ways.
The “none” algorithm. Set alg to none and a naive library skips verification altogether, accepting a token anybody could have written. This tool refuses such a token outright, whatever algorithm you selected.
Algorithm confusion. A service that expects RS256 — RSA, verified with a public key — can be handed a token declaring HS256. A library that picks the algorithm from the header will then verify an HMAC using the RSA public key as the shared secret. That key is published, so anybody can produce a token that passes. This has been found in real libraries repeatedly.
The defence is exactly what this page does: you state the algorithm, and the token's header is compared against it. A mismatch fails, names both values, and explains what it prevented. There is no code path here that takes the algorithm from the token.
What a valid signature still does not tell you
That the token has not expired, that its audience is you, that its issuer is one you trust, or that its subject is allowed to do what they are asking. All four are separate decisions and an application has to make every one of them.
A signature check answers a narrow question: was this token produced by whoever holds that key, and has it been altered since. This page reports expiry and not-before alongside the signature result rather than folding them together, because they are different facts and an expired token with a perfectly valid signature is a common and confusing thing to encounter.
Nothing in a token is rendered as markup
A JWT payload is entirely under the control of whoever handed it to you, so every value shown on this page is inserted as text and escaped. A decoder that renders claim values as HTML turns a token into a way of running script in your browser, which is a fine irony for a security tool and has happened to more than one of them.
What this tool does not claim
No tool on this site is described as unbreakable, military grade, or completely secure, because none of those phrases means anything a person could check. What is written down instead is which standard is used, which library implements it, and what the tool has been tested against.
Everything here runs in your browser using its built-in Web Crypto implementation. Nothing is uploaded, and there is no server that could receive it. That is a real and checkable property — open your browser's network tab and use the tool.
What the parts are
Three Base64url segments separated by full stops. The header says which algorithm signed it. The payload holds the claims. The signature covers the first two, joined by their dot — which is why changing a single character of either invalidates it.
None of it is encrypted. Base64url is an encoding, not a cipher, and anybody who can see the token can read every claim in it. Do not put anything in a JWT that you would mind the holder reading, because they can.
Common confusions
"Bearer" is not part of the token. An Authorization: Bearer eyJ… header contains the scheme and then the token. Pasting the whole line gives you a token with a space in it that will not decode.
Segments have no padding. JWT uses Base64url without the = characters. A decoder that insists on padding will refuse perfectly ordinary tokens.
Times are seconds, not milliseconds. exp, nbf and iat are Unix timestamps in seconds. Passing a JavaScript millisecond timestamp produces an expiry somewhere in the year 55000, which this page will show you plainly.
Related
The encoding converter for Base64url generally, HMAC for the HS-family signatures on their own, or the key inspector for the key you are verifying against.
Questions people actually ask
Does decoding a token prove anything?
No. Decoding is unwrapping Base64url — no key is involved and anyone holding the token can do it. Everything a decoder shows is what the token claims, written by whoever produced it. Only a signature check against a key you supply turns a claim into evidence.
Why do I have to choose the algorithm?
Because reading it from the token is how JWT verification is usually broken. Set alg to "none" and a naive library skips verification entirely. Declare HS256 to a service expecting RS256 and a library that trusts the header will verify an HMAC using the RSA public key as the secret — and that key is published, so anyone can forge tokens. Here you state the algorithm and a mismatch fails loudly.
Is the payload encrypted?
No. Base64url is an encoding, not a cipher — anyone who can see the token can read every claim in it. Do not put anything in a JWT you would mind the holder reading, because they can and will.
The signature is valid but the token does not work.
A valid signature answers one narrow question: was this issued by whoever holds that key, and has it changed since. It does not check expiry, audience, issuer trust or authorisation. This page reports expiry and not-before alongside the signature result rather than folding them together, because an expired token with a perfectly good signature is a common and confusing thing to meet.
It will not decode and I am sure it is a token.
Three usual causes. The "Bearer " prefix from an Authorization header is not part of the token. A copied token sometimes picks up a line break in the middle. And a token from a log may have been truncated — the signature segment is the one that usually goes.
Is my token sent anywhere?
No. Everything happens in your browser and nothing is transmitted. Every value from the token is inserted as escaped text rather than markup, because a payload is entirely under the control of whoever gave you the token.