Developer JWT decoder
Decode a JSON Web Token to read its header and claims, with expiry checked and timestamps rendered as dates, all in your browser.
Decoding is not verification. A JWT payload is only Base64-encoded, not encrypted, so anyone holding the token can read it. This tool deliberately does not check the signature, because doing so would need your secret key. Never paste a production token you would not also be comfortable printing.
Ready. Runs locally on your device.

Your files stay on your device. The tool works directly in your browser, using your device to process your files. Nothing is sent to our servers, and we never receive, store, or see your files or figures.
Cite
Cite this page
Reembun. (2026, July 28). JWT decoder. https://reembun.com/jwt-decoder
How to use it
Paste the token
It is split and decoded in this tab. That matters more here than on most tools, because a token is a live credential.
Read the header and payload
Both are shown as formatted JSON, with the signing algorithm and the standard claim names spelled out.
Check the timestamps
Issued at, not before and expiry are converted from epoch seconds into readable dates, and an expired token is flagged.
Remember what decoding is not
Decoding is not verification. Only your server, holding the secret or the public key, can tell you the signature is genuine.
Structure of a token
A JWT is three Base64URL-encoded segments separated by dots:
header.payload.signature
Header declares the signing algorithm and token type. Payload carries the claims. Signature is computed over the first two segments using a secret or private key.
Only the signature is cryptographic. The header and payload are merely encoded, and anyone holding the token can read them, including whoever it was issued to.
Registered claims
The names defined by RFC 7519, which most libraries understand without configuration:
| Claim | Meaning |
|---|---|
iss | Issuer: who created the token |
sub | Subject: who the token is about, usually a user ID |
aud | Audience: who the token is intended for |
exp | Expiry time, as a Unix timestamp in seconds |
nbf | Not valid before, as a Unix timestamp |
iat | Issued at, as a Unix timestamp |
jti | Token ID, for revocation lists |
The three time claims are in seconds, not milliseconds. Passing a JavaScript Date.now() value straight into exp produces a token that expires roughly 50,000 years from now, which is a real and recurring bug.
Signed is not encrypted
This is the most consequential thing to understand about JWTs, and the source of a steady stream of incidents.
A signed JWT (JWS) guarantees that the payload has not been altered and came from someone holding the key. It does not hide the payload. Email addresses, internal user IDs, role names and permission lists placed in a JWT are all readable by the client and by anyone who intercepts the token.
If a claim must stay confidential, either keep it server-side and reference it by an opaque ID, or use JWE, which actually encrypts. In practice, keeping it server-side is almost always the better answer.
Common vulnerabilities
alg: none. An attacker sets the algorithm to none, strips the signature, and forges any payload. Mitigation: pin the expected algorithm in your verifier rather than trusting the header.
Algorithm confusion. A token signed with HMAC using the server’s public RSA key as the HMAC secret, on a verifier that picks its method from the header. Mitigation is the same: never let the token choose how it is verified.
No expiry. A token without exp is valid forever. Set short lifetimes and use refresh tokens.
Storing tokens in localStorage. Readable by any script on the page, so a single XSS becomes full account takeover. HttpOnly cookies with SameSite are the safer default for browser sessions.
When not to use a JWT
JWTs are attractive because they are stateless, and that is also their main drawback: a token cannot be revoked before it expires without reintroducing server-side state. For ordinary web sessions, a random opaque session ID in a secure cookie with server-side storage is simpler, revocable immediately, and leaks nothing.
JWTs earn their place for short-lived access tokens across service boundaries, where avoiding a lookup on every request genuinely matters.
Common questions
Is it safe to paste a token into a website?
Only if the decoding happens locally, which it does here. There is no request carrying your token anywhere, and you can confirm that in your browser's network panel. Many JWT debuggers are server-side, which means the token has been transmitted and possibly logged. Even so, treat any browser tab as a place secrets can leak through extensions or screen sharing, and prefer a test token where you can.
Why does this not verify the signature?
Verification requires the secret or public key that signed the token. Asking you to paste a signing secret into a web page would be far more dangerous than decoding a token, so this tool deliberately does not offer it. Verify signatures in your own code or with a local CLI.
Is a JWT encrypted?
No. The header and payload are Base64URL-encoded, which is reversible by anyone. A signed JWT guarantees integrity and authenticity, not confidentiality. Never put anything in a JWT payload that the token holder should not be able to read.
What does an algorithm of "none" mean?
An unsigned token. Accepting one is a well-known vulnerability: an attacker can craft any payload, set the algorithm to none, and a verifier that honours the header will trust it. Always pin the expected algorithm server-side rather than reading it from the token.
Last reviewed
