Decode and Inspect JWT Tokens Safely
See exactly what's inside a JSON Web Token: issuer, expiry, scopes, and claims. Decode locally and spot expired or suspicious tokens before trusting them.
A JSON Web Token (JWT) is the string your browser sends to prove who you are after you log in — and it is readable by anyone who holds it. That’s not a leak in the design; it’s the design. The real risk isn’t reading a token, it’s where you read it. Pasting a live token into a random decoder site hands your session to a server you don’t control. The JWT Decoder never uploads anything — it decodes the header, payload, and claims entirely in your browser, and it tells you so up front: the security note under the input reads “Decoded locally in your browser. Signature is not verified.”
TL;DR
A JWT is not a sealed envelope. It is three Base64URL parts with a signature on the end, and the first two are plain text in disguise.
- A JWT is three parts —
header.payload.signature, each separated by a dot. The first two are Base64URL-encoded JSON. - Anyone who has the token can read it — the header and payload decode in milliseconds, no key required.
- The signature proves integrity, not confidentiality — it lets the server confirm the token wasn’t tampered with. It does not hide the contents.
Decode locally, read what the token says, and never treat the payload as a safe place for secrets.
Anatomy of a JWT
Every JWT has exactly three Base64URL segments, joined by dots:
<header>.<payload>.<signature>
Take the tool’s own sample token (load it with the Sample button) and look at the first two segments. They look like noise, but each is just Base64URL-encoded JSON. Decoded, they read:
- Header —
{"alg":"HS256","typ":"JWT","kid":"example-demo"}. This declares the algorithm, the token type, and the key id. It tells the server how to verify, not anything secret. - Payload —
{"iss":"example-app","sub":"demo-user","name":"홍길동","scope":"read write","iat":1704067200,"nbf":1704067200,"exp":4102444800}. These are the claims: statements about the token — who issued it, who it’s for, what it allows, and when it expires. - Signature —
demo-signature. In a real token this is a cryptographic value the server computes over the header and payload using a secret or private key. The tool’s sample ships a placeholder on purpose.
The header and payload are the readable parts. The signature is the one piece you cannot read back to its input — and it exists to prove the other two weren’t changed in transit, not to keep them private. (For the encoding half of this story, see Base64 encoding vs encryption — a JWT is a worked example of “Base64 is not a secret.”)
Standard claims decoded
The payload is a bag of claims — key/value pairs agreed on by convention. The registered ones you’ll meet almost every time:
iss(issuer) — who issued the token, usually a URL or identifier.sub(subject) — who the token is about, typically a user or account id.aud(audience) — who the token is intended for. A token minted for the billing service should be rejected by the profile service.exp(expiration) — the moment the token stops being valid, as a Unix timestamp. This is the single most important claim to check.iat(issued at) — when the token was created.nbf(not before) — the earliest moment the token is valid. Combined withiat, it lets issuers mint tokens slightly ahead of time.
exp matters because tokens are bearer credentials: whoever presents a valid one gets in. Short, expiring tokens limit the blast radius if one is stolen. A token with exp far in the future is a long-lived key; a token with no exp at all is effectively permanent. Always read the expiry before you trust what a token claims.
Step-by-step: decode a token
The JWT Decoder runs entirely in your browser — the token never leaves your device. The workflow:
- Paste the token. Drop a full
header.payload.signaturestring into the JWT token input box. Hit Sample to load the built-in demo token instead of pasting your own. - Decode. Click Decode. The right-hand panel fills with the parsed result. (If you edit the input afterward, the status line reads “Input changed. Decode again to refresh the result.” so you never read a stale parse.)
- Read the Diagnostics panel. At the top it lists Algorithm, Type, and Key ID pulled from the header, plus the byte size of each segment. This is where malformed or empty-signature tokens surface — a warning here reads “Token is expired.”, “Token is not valid yet.”, or “Signature segment is empty. Decode does not verify signatures.”
- Check the Claims timeline. The table lays out the time-based claims —
exp,iat,nbf— each with its raw seconds, the ISO UTC reading, and a Status of Active, Past, or Future. Anexprow marked Past is an expired token; anbfrow marked Future means it’s not valid yet. - Read the Header and Payload panels. Each is pretty-printed JSON with a Copy button. This is the full, decoded content of the token — issuer, subject, scopes, the lot.
- Copy what you need. Use Copy on a single panel, or Copy all for a text summary of header, payload, and signature together. Use Reset to clear everything.
The whole thing is a read operation. The tool never calls out, never verifies the signature against an issuer, and never stores the token — refresh the page and it’s gone.
The critical misconception
Because a JWT is used for authentication, people assume its contents are secret. They are not. The header and payload are Base64URL-encoded, which is encoding, not encryption — reversible by anyone in one step, no key. (This is the same trap as treating Base64 as security; see Base64 encoding vs encryption.)
That has one iron rule: never put a secret in a JWT payload. No passwords, no API keys, no credit card numbers, no credentials of any kind. If it’s in the payload, assume it is public — because the moment that token leaves the server, anyone along the path can read it. The signature guarantees the token wasn’t altered; it guarantees nothing about who can see it.
When you decode a token and the payload reads fine, that means the format is honest — not that the contents are private. Design accordingly: put only what the client needs in the payload, keep the real secrets server-side, and let short exp values do the protecting.
Related checks
Decoding is the first question. A few neighbors answer the rest:
- Verify the Base64 parts. Each segment is Base64URL — confirm it round-trips with the Base64 tool. This is also how you prove a JWT’s contents aren’t hidden: paste a segment in, decode it, and the JSON comes straight back.
- Check the timestamps.
exp,iat, andnbfare Unix seconds. Turn one into a human date with the Timestamp Converter to see exactly when a token expires or became valid. - Integrity via hash. A JWT’s signature proves it wasn’t tampered with. For the same job on a file or arbitrary string, compare hashes with the Hash & Checksum Generator — a matching digest means “unchanged,” with no key exchanged.
FAQ
Is decoding a JWT safe?
Yes — decoding a JWT is just Base64URL-decoding two JSON segments. It reveals what the token already says in plaintext to anyone holding it; it doesn’t weaken, expose, or invalidate the token. What’s unsafe is where you decode it: pasting a live token into an unknown website can leak your session. Decode in your browser with the JWT Decoder and the token never leaves your device.
Can the tool read my token?
No. The JWT Decoder runs entirely client-side. The token is parsed in your browser’s memory; nothing is uploaded, logged, or stored on a server. The security note under the input states this directly: “Decoded locally in your browser.” Refresh the page and the input is cleared.
What does “expired” mean here?
It means the token’s exp claim — its expiration timestamp — is in the past, so a verifying server should reject it. In the tool, an expired token shows exp as Past in the Claims timeline and raises a “Token is expired.” warning in the Diagnostics panel. “Expired” is about validity, not readability: the token still decodes fine, it just shouldn’t be trusted.
Where is the token validated?
Not in this tool. The JWT Decoder decodes — it reads header and payload and shows the claim timeline. It does not verify the signature against an issuer’s key, so it can’t tell you a token is authentic, only what it claims. Real validation (checking the signature, exp, aud, and issuer) happens on the server that issued or trusts the token. That’s why the security note is explicit: “Signature is not verified.”

Start with this tool
Get started