JWT Decoder

Works offlineNothing is uploadedFree, no sign-up

Decode a JWT into its header and claims, see exactly when it expires with a live countdown, and check an HMAC signature against a secret — everything stays in your browser, which is the only place a token should be pasted.

The three parts of a JWT

A JWT is three base64url segments joined by dots. The header names the signing algorithm; the payload carries the claims; the signature covers exactly the first two segments as transmitted — not the decoded JSON, which is why re-encoding a payload byte-for-byte matters and why this tool keeps the original segments when checking a signature.

PartContainsProtected by the signature?
Headeralgorithm, token type, key idyes
Payloadthe claims — who, for whom, until whenyes
SignatureHMAC or asymmetric signature of the first two parts—

Reading the time claims

exp, nbf and iat are Unix timestamps in seconds — a value like 1516239022 is a date in 2018, not 1970. The tool converts each to UTC and to relative time, and derives the status line from them: valid, expired, or not yet valid. The commonest debugging discovery here is clock skew — a token minted by a server whose clock runs a minute fast is "not valid yet" for everyone else.

Everything on this page runs locally; no token, secret or claim leaves your browser.

Frequently asked questions

Is it safe to paste a token here?

The page never sends anything anywhere — decoding and the HMAC check both run in your browser, and you can verify that by loading the page and going offline. That said, treat live production tokens like passwords everywhere: this tool being local is exactly why it exists, since pasting a token into a random online decoder hands a bearer credential to a stranger.

Why can I read the token without any key?

Because a JWT is signed, not encrypted. The header and payload are plain base64url — an encoding, not encryption — readable by anyone who holds the token. The signature only proves who issued it and that it was not altered. Anything confidential must never be put in a JWT payload; that is what encrypted tokens (JWE) are for.

What does the signature check actually prove?

For HS256/384/512, the signature is an HMAC of header.payload with a shared secret. If the check passes for your secret, the token was made by someone holding that secret and has not been modified. It proves nothing about expiry — an expired token still has a valid signature — which is why the tool shows both separately.

Why does it say the algorithm needs a public key?

RS256, ES256 and their siblings are asymmetric: the issuer signs with a private key and anyone can verify with the public key. Verifying those needs that key in the right format, which is a server-side job. The decoded contents shown above are complete and correct regardless — decoding never needs any key.

What is the alg "none" warning about?

The JWT spec technically allows an unsigned token with alg set to none. Early libraries would accept such tokens as verified — so an attacker could strip the signature, set alg to none, and edit the claims freely. Modern libraries refuse it, but the tool flags it because a none token in a real system is almost always either an attack artefact or a serious misconfiguration.

Why did my token stop working before its exp time?

exp is only the hard upper bound. Servers also reject tokens whose nbf is in the future, whose iss or aud does not match what they expect, that were revoked by jti, or whose clock skew allowance was exceeded. The claims table shows all of these — comparing iss and aud against what the server expects finds most "valid but rejected" cases.

Related tools