How to Decode a JWT Safely (Without Sending It to a Server)
Decode a JWT to read its header and payload in seconds — and learn why decoding is not verifying, when it's safe to paste a token online, and how to do it in the browser.
You have a long string that starts with eyJ..., three chunks separated by dots, and a bug to fix. You need to see what's inside the token — the user id, the expiry, the issuer — without standing up a backend or trusting a random website with a live credential. This is the everyday reality of debugging authentication, and decoding a JWT correctly (and safely) takes about ten seconds once you know what you're looking at.
What a JWT actually is
A JSON Web Token is not encrypted. That surprises people. It's three parts joined by dots:
| Feature | Contains | Encoded how | Secret needed to read? |
|---|---|---|---|
| Header | Algorithm + token type | Base64URL | No |
| Payload | Claims (user, exp, iss…) | Base64URL | No |
| Signature | Integrity proof | HMAC/RSA over header+payload | Yes (to verify) |
The header and payload are Base64URL — a URL-safe variant of Base64 with +/= swapped out. Anyone holding the token can decode those two parts. That's by design: the payload is meant to be read by the client. The signature is the only part that needs a secret, and only to prove the token wasn't tampered with — not to hide it.
Decode one in the browser
The safest way to inspect a token is a tool that runs entirely client-side, so the token never leaves your machine.
Decode the header and payload, or build and sign a test token — all in the browser, nothing uploaded.
- Split on the dots
Conceptually, a JWT is
header.payload.signature. The decoder does this for you, but it's worth knowing the structure so you can spot a malformed token (wrong number of segments) at a glance. - Base64URL-decode the first two parts
The header and payload are Base64URL. The tool converts them back to JSON. You'll immediately see the algorithm (
alg) in the header and the claims in the payload. - Read the standard claims
Look for
exp(expiry, a Unix timestamp),iat(issued-at),iss(issuer),sub(subject/user id), andaud(audience). An expiredexpis the single most common cause of "my valid token is being rejected." - Convert the timestamps
expandiatare seconds since 1970, not milliseconds. If you're eyeballing whether a token is expired, drop them into a Unix timestamp converter rather than doing the math in your head.
When is it safe to paste a token into a tool?
This is the question that actually matters, and the honest answer has nuance.
- Expired or test tokens: safe anywhere. There's nothing to steal.
- Live production tokens, into a client-side decoder: acceptable if you trust the tool not to exfiltrate it. A purely client-side tool (no network request fires when you decode) keeps the token on your machine.
- Live production tokens, into a server-side decoder: avoid it. If the decode happens on someone else's server, you've just handed a working credential — often valid for minutes or hours — to a third party.
The signature: why you can't fake a token
If the payload is readable by anyone, what stops an attacker from changing "role": "user" to "role": "admin" and re-encoding? The signature. It's computed over the header and payload using a secret (HMAC) or a private key (RSA/ECDSA). Change one character of the payload and the signature no longer matches — verification fails on the server.
That's also why the algorithm matters. A token signed with HS256 uses a shared secret; RS256 uses a public/private key pair. If you're generating test tokens, you'll want to match the algorithm your backend expects — the same tool that decodes can sign a fresh one for you.
Common things you'll find (and what they mean)
expin the past → the token is expired; the API is right to reject it. Refresh it.issdoesn't match your config → you're validating against the wrong issuer, or pointing at the wrong environment (staging token, prod verifier).audmismatch → the token was minted for a different service. Common in multi-service setups.- A huge payload → someone stuffed too many claims in. JWTs travel in headers on every request; keep them lean.
Where this fits
Decoding tokens is one slice of working with auth and encoded data. If you're moving between formats and encodings all day, these pair well:
Percent-encoding for query strings and redirect URLs — the other encoding you'll hit constantly in auth flows.
Decode the raw Base64URL segments by hand when you want to see exactly what the JWT tool is doing.
For the full set of token, hash, and credential utilities, browse the Security & Hash Tools hub.
Related reading
Recommended tools for this topic
Explore focused tools and use-case pages related to this article.