Paste a JSON Web Token to decode its header and payload instantly. Inspect claims, expiry, and algorithm — all locally, so tokens never leave your browser.
SYSTEM ● ONLINE · LOCAL COMPUTE · ZERO UPLOAD
UNIT // JWT.DECODELIVE
—
Algorithm
0
Claims
—
Expiry
Quick Answer
How do you decode a JWT?
// Answer
A JSON Web Token has three Base64URL-encoded parts separated by dots: header.payload.signature. Decoding the first two parts reveals the algorithm and the claims (like user ID and expiry). This tool decodes them instantly. Note: decoding is not the same as verifying the signature.
Why use this tool
Inspect tokens safely
When debugging authentication, you often need to see what is inside a token — its claims, issued-at, and expiry. Pasting tokens into a remote decoder is risky because tokens are credentials. This tool decodes entirely in your browser, so the token never leaves your machine.
FAQ
Frequently asked questions
Header (algorithm and type), payload (claims), and signature (used to verify integrity). They are separated by dots.
No. Decoding only reads the header and payload. Verifying the signature requires the secret or public key and is a separate step.
Yes. Decoding happens entirely in your browser, and the token is never uploaded.
exp is the expiry time, in seconds since 1 January 1970 (UTC). From that moment on, the token must not be accepted.
This tool splits the token on its dots, Base64URL-decodes the first two parts, and prints them. It never looks at the third part. A token that decodes cleanly here can still be expired, forged, or signed with a key nobody recognises.
The distinction matters because the two operations answer different questions. Decoding answers what does this token claim. Verifying answers did the party holding the key actually issue this, and has it been altered since. Only the second one is a security check, and it needs a key that this page does not have and should not ask you for.
How that key works depends on the algorithm in the header. With the HMAC family (HS256, HS384, HS512) signing and verifying use the same shared secret, so anything able to verify a token is also able to mint new ones — which is exactly why that secret must never reach a browser. With the RSA and ECDSA families (RS256, ES256) verification needs only the public key, so it is technically possible in a browser. It still does not make the browser a place to decide who is allowed in. Anyone can edit your JavaScript. Nobody can edit your server.
Limits
What this tool is not for
It does not verify signatures. No key input, no verification, by design.
It does not tell you a token is authentic. The alg value in the readout is copied out of the token's own header, which is the one part an attacker controls freely.
The Expiry readout only reads exp. When it says "Valid" it means the exp timestamp has not passed. It is not a verdict on the token.
It does not check revocation. A perfectly signed, unexpired token may have been withdrawn server-side. There is no way to see that from the token.
It reads text, not cookies or headers. You have to paste the token yourself.
Worked example
Reading a token part by part
The field above arrives pre-filled with the standard demonstration token, so you can see the shape of the output before pasting anything of your own. Every JWT has the same three-segment layout:
Now the part worth practising. Now picture a payload such as {"sub":"user-0001","exp":1700000000} and read it as a reviewer rather than a developer. (The demonstration token has no exp, which is why its Expiry readout says No exp.) sub is the subject, the thing the token is about. exp is an expiry expressed in seconds since 1 January 1970, which is why the tool multiplies it by a thousand before turning it into a date — paste a value in milliseconds by mistake and you will see an expiry tens of thousands of years away. That wrong-looking date is a useful signal, not a bug.
The other registered claims defined by the JWT specification are worth knowing by name, because seeing which ones are missing is often the finding. iss is the issuer, aud the intended audience, nbf the not-before time, iat the issued-at time, and jti a unique identifier for the token. A token with no aud can be replayed against any service that trusts the same issuer. A token with no exp never expires on its own.
The mistake
Two ways people get this wrong
Treating the payload as secret. The payload is Base64URL, not ciphertext. Base64URL is a transport alphabet — the same idea as ordinary Base64 encoding, with - and _ swapped in so the result survives a URL. Anyone holding the token can read every claim in it, in a browser, in a second. Do not put anything in a JWT payload you would not print on a postcard: no internal notes, no roles you would rather users could not enumerate, and certainly no secondary credential. If a value genuinely must be confidential, it does not belong in the token at all; keep it server-side and reference it by an opaque id.
Trusting the alg header. The header is part of the token, so whoever sends the token chooses what it says. The specification even defines none, meaning "unsecured, no signature". A verifier that reads alg and does whatever it says can be handed a token claiming none, or one claiming HMAC when the server expected RSA. The fix is on the server: decide in advance which algorithm and which key you accept, and reject everything else. Never let the token pick.
Why local matters
A pasted token is a live credential
JWTs are very often used as bearer tokens. Holding one is the authorisation — no password needed, no second factor. So when you copy an access token out of your browser's network tab to find out why an endpoint keeps returning 403, and paste it into whichever decoder ranked first that day, you have handed a stranger's server a working key to your account for as long as that token lives. Nobody has to attack anything. You uploaded it.
Nothing you paste here is sent to a server. The script contains no fetch, no XMLHttpRequest and no analytics beacon; it reads the textarea, splits the string, and writes into two other textareas. Confirm it the hard way: open your network panel, paste a token, and watch that no request is made. Or switch the Wi-Fi off and use the page anyway.
The same reasoning runs through the rest of the set. Hashing uses the browser's own Web Crypto API, UUIDs come from crypto.getRandomValues rather than a remote generator, and JSON formatting never sees a server — which matters when the JSON is a customer record pulled from production. Full list on the developer tools page.