Decode a JWT
See the header, the claims and the expiry of a JSON Web Token. A token is a working credential, so nothing here is sent anywhere or stored, ever.
- Never stored
- No queue, no waiting
- No signup, no watermark
Your token is never stored or sent anywhere. That matters, because a JWT is usually a working credential. Switch off your Wi-Fi after the page has loaded and it still decodes.
The “Bearer ” prefix is fine — it is ignored.
How it works
Paste the token
With or without the "Bearer " prefix. It stays in this page; no request is made.
Read the three parts
Header, payload and signature, each decoded and formatted. Timestamps become real dates and you are told how long is left.
Check the warnings
Expired tokens, missing expiry, the "none" algorithm and other problems are called out with what they mean.
What is checked, and what is only read
Everything on this page except two date comparisons is transcription. The header and the payload are Base64URL-decoded and printed; the signature is copied out and never touched, because there is no key here and no cryptography runs at all. The two judgements the page does make are arithmetic against your own device's clock — the expiry claim compared with now, and the not-before claim compared with now. No allowance is made for clock skew, where a server checking the same token normally allows a minute or two. A laptop running five minutes fast will show you a live token as expired, and the token will be perfectly fine.
Two parsing details decide what you actually see. The time claims are read only when they arrive as JSON numbers: a token whose expiry was written as the string "1699999999" is treated as having no expiry at all, and gets the warning saying it never expires on its own — the opposite of the truth. And the payload is parsed with the browser's own JSON parser rather than the digit-preserving one behind our JSON tools, so a 64-bit numeric claim such as a snowflake user ID in the subject is displayed with its last digits rounded. Identifiers in a JWT are usually strings for exactly this reason; when one is not, read it out of the raw payload rather than off the claims table.
A token with five sections is refused as an encrypted JWE, and that judgement is made on the section count alone rather than by reading the header — right in practice, and worth knowing is a shortcut. Anything that is not three sections is refused outright, as is a payload that decodes to a JSON array or a bare string instead of an object. Warnings are raised for an algorithm of "none" and for the HS family, where the signing key is a shared secret rather than a public one. Tokens signed with RS, ES or PS raise nothing, so silence on this page is the absence of a known-bad shape, not approval.
When you want something else
Nothing here is stored, which is the only reason this page can reasonably exist — and it is still not the habit to build. A privacy claim cannot be checked by reading it: disconnect after the page has loaded and watch the decoder keep working, which is precisely what a tool with a server behind it cannot do. And if a token you pasted somewhere you cannot audit is still valid, rotate it rather than reason about it. Rotating is a minute's work. The alternative is a long argument with yourself about a credential that still opens the door. For reading a token on a machine instead of in a tab, the payload is one shell line: cut the second dot-separated field, base64 -d it, and pipe it through jq.
When the question is whether a token is genuine rather than what it says, this is the wrong page by construction, and so is every other online decoder. Verification belongs where the key already is — your language's own JWT library on your server, checked against the issuer's published JWKS. That is a few lines, it is the only answer that means anything, and any site offering to do it for you is asking for the one secret you should never give a website.
Frequently asked questions
Is my token sent anywhere?
No — and for this page that is the entire point rather than a feature. A JWT is usually a live credential: whoever holds it can act as you until it expires. Pasting one into an online decoder that posts it to a server hands over a working key, and no promise about not logging can undo that. This decoder is plain JavaScript in the page you are looking at. Nothing is stored, nothing is logged, no request is made. Once the page has loaded, turn off your Wi-Fi and it works exactly the same. That is the simplest way to confirm the privacy claim for yourself rather than taking our word for it.
Does this verify the signature?
No, and no online decoder honestly can without your signing key. Decoding and verifying are completely different operations. Decoding just un-Base64s the token — anyone can do it to any token, and it proves nothing at all about whether the token is genuine. Verifying means recomputing the signature with the secret or public key that signed it, and that key should never be pasted into a website. What you see here is what the token CLAIMS. Whether those claims are trustworthy is a question only your server, holding the key, can answer.
Can someone read a JWT I send them?
Yes — completely, and this catches people out. A JWT is signed, not encrypted. The header and payload are Base64, which is an encoding with no secret in it, so anyone who intercepts the token can read every claim inside it. The signature stops them CHANGING the token; it does nothing to stop them READING it. Never put anything confidential in a JWT payload: no passwords, no card numbers, no personal data you would not put on a postcard.
What does the "none" algorithm warning mean?
That the token says it is unsigned, and it is one of the most serious findings this page reports. `alg: none` is a documented authentication bypass: an attacker takes a real token, changes the payload to say they are an administrator, sets the algorithm to "none", removes the signature, and a library that trusts the header accepts it. Every serious JWT library now blocks this by default, but implementations that trust `alg` still exist. A token arriving with `alg: none` should be treated as an attack until proven otherwise.
How do I read the expiry?
It is done for you. `exp`, `iat` and `nbf` are Unix timestamps — seconds since 1970 — which are unreadable as raw numbers. Each is shown as a real date in your own timezone, with how long ago or how long from now, and an expired token is stated plainly rather than left for you to work out. A token with no `exp` at all is flagged too: a JWT that never expires cannot be revoked by expiry, and stays valid for as long as the signing key does.
My token has five parts, not three
Then it is a JWE — encrypted rather than merely signed — and its contents genuinely cannot be read without the decryption key. The page recognises the shape and tells you so instead of showing you nonsense. Five parts means the payload is real ciphertext; there is nothing to decode.
What are the standard claims?
The registered ones are: `iss` who issued it, `sub` who it is about (usually a user ID), `aud` who it is for, `exp` when it expires, `nbf` not valid before, `iat` when it was issued, and `jti` a unique ID for the token. Everything else is custom to whoever built the system. Each registered claim is labelled with its meaning in the output, so you do not need to remember which three-letter abbreviation is which.
Good to know: This decodes; it does not verify. A JWT's signature proves the token has not been altered, and checking it needs the issuer's secret or public key — which you should never paste into a web page. Treat everything shown here as claimed, not proven, and verify on your server.
Put this tool on your website
Free for any blog, class page or help article. Paste one snippet and your visitors can use it right on your page.