JWT Decoder
100% private — runs on your device, never uploaded. Works offline once loaded.
Paste a JSON Web Token (JWT) to decode its header and payload as readable JSON. Decoding happens locally — we do not verify signatures or send tokens anywhere.
What's actually inside a JWT
A JSON Web Token is three Base64URL-encoded segments joined by dots: a header, a payload, and a signature — for example eyJhbGc...eyJzdWI...SflKxw.... The header typically names the signing algorithm (like HS256 or RS256) and token type; the payload holds the actual claims, such as a user ID (sub), expiry time (exp), issued-at time (iat), and any custom fields an application adds, like roles or tenant IDs. This tool splits the token on its dots, Base64URL-decodes the first two segments, and pretty-prints them as readable JSON.
Because Base64URL encoding is reversible with no secret key required, anyone can read the header and payload of a JWT just by decoding it — encoding is not encryption. That's a deliberate design choice in the JWT spec: the signature exists to prove the token wasn't tampered with, not to hide its contents.
Why developers decode tokens by hand
Pasting a token here is usually a debugging move: checking why an API call returns 401 Unauthorized, confirming an exp timestamp actually reflects the session length you configured, verifying that an OAuth provider is including the scopes or roles your backend expects, or inspecting a token a teammate sent in a bug report without writing a throwaway script. It's also handy when integrating a new auth provider and you want to see the exact shape of the claims before writing code against them.
What this tool deliberately does not do
This decoder does not verify the signature, so it will happily show you the contents of an expired, revoked, or even forged token — decoding tells you what a token claims, not whether those claims are trustworthy. Signature verification requires the issuer's secret or public key, which this tool never asks for or has access to; that check belongs in your server-side auth library, not a browser paste box.
Reading timestamps and common claim names
JWT timestamp claims like exp, iat, and nbf are stored as Unix epoch seconds, not milliseconds, which trips people up when comparing them against Date.now() in JavaScript. If you see a payload with no exp field at all, that token technically never expires by its own claims — expiry enforcement, if any, is happening elsewhere in the issuing system.
Frequently asked questions
Is my token sent anywhere?
No — decoding happens entirely on your device.
Does this verify the signature?
No — this tool only decodes the payload for inspection.
Is my token sent to a server anywhere?
No — the header and payload are decoded entirely in your browser using JavaScript's built-in Base64 decoding, so the raw token never leaves your device or gets logged anywhere.
Why can I read the payload without a secret key?
Because JWTs are Base64URL-encoded, not encrypted — the signature protects against tampering, but the header and payload are always human-readable to anyone who has the token string.
Why does the payload show exp as a number instead of a date?
JWT timestamp claims are stored as Unix epoch seconds; the tool won't automatically convert that to a calendar date, so you may need to multiply by 1000 and pass it to a Date object if you're checking it in code.
What if the token is malformed or won't decode?
A valid JWT needs exactly three dot-separated Base64URL segments; if you're pasting a truncated token, an opaque session cookie, or a non-JWT API key, decoding will fail because there's nothing structured to parse.
Can I use this to check if my token has expired?
You can view the exp claim and compare it manually against the current time, but the tool won't flag expiry for you automatically since that requires trusting the token's claims rather than a verified signature.
Advertisement