How to Decode
a JWT Token
Read the header, payload and expiry of any JSON Web Token — in your browser, in one step, without your secret key leaving your machine.
How to decode a JWT token is the question that shows up every time an auth flow breaks, an API returns 401 for no obvious reason, or a teammate pastes an eyJ... string into Slack and asks what's in it. This guide walks through the safe way to do it — entirely in your browser, without your secret key, and without handing a production token to a third-party server.
The 10-second version
Open the JWT Decoder. Paste the token. Read the header, payload and expiry. Nothing leaves your browser.
What a JWT Actually Is (in 30 seconds)
A JSON Web Token is three Base64URL-encoded strings joined with dots:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NSIsImV4cCI6MTc2MDAwMDAwMH0.abc123signature
The three parts are:
- Header — which algorithm signed the token (
HS256,RS256, etc.). - Payload — the claims: who the user is, when the token expires, what roles they have.
- Signature — a cryptographic proof the token wasn't tampered with.
Decoding means reversing the Base64URL on the first two parts and parsing them as JSON. It's not encryption — anyone holding the token can read its contents. The signature is the only part that requires the secret key, and that's only needed for verification, not decoding. This distinction matters because a lot of developers assume they need to be careful with JWTs the way they'd be careful with passwords, but JWTs are "readable credentials" — the data is meant to be inspectable, the signature is what makes it trustworthy.
Step 1 — Open the JWT Decoder
Navigate to /tools/jwt. The decoder is a single-page browser app with no server component. The Base64URL decoding logic runs on your machine the moment you paste the token.
This matters because the alternative — pasting into a server-hosted debugger — transmits your production token to someone else's backend. The hidden dangers of JWT debuggers covers exactly what happens when you do that: the token gets logged, the user ID and email inside it are now in a third party's systems, and if you're under SOC 2 or GDPR you've just created a reportable event.
Step 2 — Paste the Full Token
Drop the token into the input field. Make sure you include all three parts — both dots and the signature. A common mistake is copying only the payload or truncating the signature; decoders can still read the header and payload in that case, but you won't be able to copy the full token back out for testing.
Where tokens usually live:
- Authorization header.
Authorization: Bearer eyJ...— strip theBearerprefix before pasting. - Browser storage. DevTools → Application → Local Storage (or Cookies). Common keys:
access_token,id_token,jwt. - Network tab. Any authenticated API response — click a request, look at the request headers.
- Identity provider dashboards. Auth0, Cognito, Clerk, Supabase all expose a "sample token" in their consoles.
Step 3 — Read the Header and Payload
The decoder splits the token into three panels. The header tells you which algorithm signed it:
{
"alg": "HS256",
"typ": "JWT"
}
The payload is where the actual claims live:
{
"sub": "user_12345",
"email": "alex@example.com",
"roles": ["admin", "billing"],
"tenant_id": "acme_corp",
"iat": 1728000000,
"exp": 1728003600
}
Standard claims you'll see across almost every JWT:
sub— subject. Usually the user ID.iat— issued at. Unix timestamp of creation.exp— expires at. Unix timestamp of expiry.iss— issuer. Which service minted the token.aud— audience. Which service the token is intended for.
Everything else is application-specific. email, roles, tenant_id, org_id, permissions, scope — all conventions, all readable.
Step 4 — Check the Expiry
The decoder converts the exp claim into a human-readable date. This is the single most useful thing a decoder does because roughly 80% of "my JWT isn't working" debugging sessions end here: the token expired, or there's a clock-skew issue between the service that issued it and the service validating it.
If you're chasing an expiry-related bug specifically, the JWT token expired — how to fix it guide covers the full diagnostic flow — clock drift, refresh-token patterns, silent reauth and the common middleware misconfigurations that cause tokens to reject early.
Decoding vs Verifying — They're Not the Same Thing
This trips people up constantly, so it's worth being explicit:
| Operation | Needs secret? | Answers |
|---|---|---|
| Decode | No | What's inside the token? |
| Verify | Yes | Was this token issued by us and untampered? |
Your API server verifies on every request. You as a developer almost always just need to decode. Decoding is the 99% case for debugging, which is why a client-side decoder that never asks for the secret is both safer and more convenient than a full verifier — see how to decode a JWT without sending it to a server for the mechanics of doing this in your own code.
Common JWT Debugging Scenarios
"My API returns 401 but the token looks fine"
Decode it and check three things in order: exp (is it expired?), aud (does it match the service you're calling?), and iss (is it from the right issuer?). Most 401s resolve at one of those three claims.
"The user has the wrong permissions"
Decode and read roles or scope. If the token says ["user"] and the app expected ["admin"], the bug is upstream — the identity provider issued the token before the role change propagated.
"The token looks weird and I want to confirm it's a JWT at all"
If it decodes into valid JSON for both header and payload, it's a JWT. If the header is empty or the payload is gibberish, you've got either a bad copy-paste or a different token format (opaque access tokens, PASETO, etc.) that a JWT decoder can't read.
"Is this jwt.io safe to use?"
Short answer: jwt.io's decoder runs client-side, but the ecosystem around it has historically been more mixed than users assume. If you want a longer read, is jwt.io safe? covers what the tool actually does with your token versus what developers assume it does.
What the Decoder Will Not Do
- Verify the signature. That requires the secret key. Decoding just reads the payload.
- Decrypt JWE tokens. JWEs are encrypted (not just signed) — you need the decryption key, which the decoder doesn't want.
- Fetch a JWKS to look up the public key. Anything that requires a network call is intentionally out of scope. A client-side decoder that doesn't make network calls is the only defensible posture for production tokens.
Ready to Decode a Token?
Open the JWT Decoder
Paste the token. Read the payload. Your token never leaves your browser.
Launch the Tool →Related Reading
- Is jwt.io safe? — what the original JWT debugger actually does with your token.
- The hidden dangers of JWT debuggers — why most online debuggers are a data-exfiltration path.
- How to decode a JWT without sending it to a server — the code-level mechanics of decoding in your own app.
- JWT token expired — how to fix it — full diagnostic flow for clock skew, refresh tokens and silent reauth.