JWT decoder
Decode a JWT header/payload and check its expiry.
Header
Payload
The signature cannot be verified without the secret key, so this only decodes. Do not paste sensitive tokens (everything runs in your browser).
An API keeps returning 401 and the only clue you have is a long token in three dot-separated parts. Pasting it here shows what the token actually claims — who issued it, who it is for, and whether it expired an hour ago — which usually answers the question faster than adding another log line.
How it works
What the three parts are
A JWT looks like xxxxx.yyyyy.zzzzz: header, payload and signature, each Base64URL-encoded and joined by dots. Paste the whole thing and the tool splits it, decodes the first two parts and prints them as formatted JSON. The header names the signing algorithm (alg) and token type; the payload holds the claims.
The claims worth checking first
| Claim | Meaning |
|---|---|
exp | Expiry time, as a Unix timestamp in seconds |
iat | When the token was issued |
nbf | Not valid before this time |
iss | Issuer — who created the token |
sub | Subject — usually the user the token represents |
aud | Audience — the service the token is meant for |
The expiry is evaluated for you, so an expired token is obvious without converting the number by hand. A token that looks valid but is rejected is often failing on aud or iss instead, or on a clock difference of a few seconds between the two servers.
Decoding is not verifying
The signature cannot be checked without the secret or public key, so this tool decodes only. Anyone holding a token can read its payload the same way — a JWT is signed, not encrypted, so never put anything confidential in the claims. Equally, never trust a decoded payload in your own code without verifying the signature server-side; the readable part can be edited by anyone. Everything here runs in your browser, but treat a live production token as a credential and avoid pasting one into any web page.
Terms explained
- JWT
- JSON Web Token: a compact, signed token carrying JSON claims, used to pass identity and permissions between services.
- Claim
- A key-value pair inside the payload, such as `sub` or `exp`. Registered claims have standard meanings; you can add your own.
- Base64URL
- A Base64 variant using `-` and `_` in place of `+` and `/`, so the token is safe inside URLs and headers.
- Signature
- The third segment, produced with a secret or private key, that proves the token has not been altered. Verifying it needs that key.
- exp
- The expiry claim, a Unix timestamp in seconds. A token past this moment should be rejected.
- alg
- The header field naming the signing algorithm, such as HS256 or RS256.
Frequently asked questions
Does this verify the token's signature?
No. Verification needs the shared secret or the issuer's public key, which this page does not have. It decodes the header and payload and checks the expiry only.
Is a JWT encrypted?
No, only signed. The payload is Base64URL-encoded, which anyone can reverse — as this page demonstrates. Keep personal or confidential data out of the claims.
My token has not expired but the API still rejects it.
Look past `exp`. A mismatched `aud` or `iss`, a missing scope, a token signed with a rotated key, or clock drift between servers all produce the same 401. Comparing `iat` with the current time will reveal a clock problem.
Why does decoding fail?
Usually the token is truncated or has picked up whitespace or a line break when copied. A valid JWT has exactly two dots and no spaces; check that the whole third segment came along.
Is it safe to paste a production token here?
Decoding happens locally in your browser and nothing is uploaded, but a live token is a credential — anyone who sees your screen or clipboard history sees it too. Prefer an expired or test token when you can.
Tell us what went wrong and we'll fix it fast. (Leave an email if you'd like a reply.)