We use cookies and similar technologies to enhance your browsing experience, analyze site traffic, and personalize content and ads. By clicking "Accept", you consent to our use of cookies. Learn more in our Privacy Policy.
by Cosmovex
Paste a JWT token above to decode it
Decode JWT tokens to view header and payload claims, check expiry status, verify HS256 signatures. No signup required.
A JSON Web Token (JWT) is a compact, URL-safe string used to carry identity and authorization data between services. It looks like one long blob, but it's actually three Base64URL-encoded parts joined by dots: a header, a payload, and a signature. This tool splits the token apart and decodes the header and payload into readable JSON so you can see exactly what claims a token carries.
Paste a token and you immediately get the decoded header and payload, plus a plain-language breakdown of the standard claims like exp, iat, iss, and sub, including whether the token has expired. Everything runs in your browser, so the token you paste never leaves your machine and is never sent to a server. That matters here because access tokens are credentials, and pasting a live one into a remote site is a real risk.
A JWT is three parts separated by dots: header.payload.signature. The header and payload are JSON objects, each Base64URL-encoded; the signature is a cryptographic check over the first two parts.
This tool does the following:
exp, iat, and nbf from Unix epoch seconds into human-readable dates, and flags whether the token is currently expired or not yet valid.alg field (for example HS256 or RS256) and the key id kid if present.Decoding is not the same as verifying. This tool reads the contents but does not check the signature, because that requires the issuer's secret or public key. Treat the decoded payload as untrusted input until something with the key has verified it.
Take this token (line-wrapped here for readability; paste it as one line):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUgRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyNDI2MjJ9.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
The decoder splits it and shows:
// header
{ "alg": "HS256", "typ": "JWT" }
// payload
{
"sub": "1234567890",
"name": "Jane Doe",
"iat": 1516239022,
"exp": 1516242622
}
From this you can read it directly: the subject (sub) is user 1234567890, the token was issued (iat) and expires (exp) one hour later, and it's signed with HS256. The decoder converts those epoch numbers to dates and tells you the token expired long ago. Notice that name is sitting in plain readable JSON, which is the whole point of the next gotcha.
exp and aud before blaming the network.sub, roles, tenant id) actually made it in.kid and alg. When rotating keys or setting up JWKS verification, the header's kid tells you which public key the verifier needs.nbf (not before) is in the future relative to a server's clock, requests get rejected even though the token "looks" fine.exp and iat are seconds, not milliseconds. A common bug is comparing exp against Date.now() (which is milliseconds). Multiply exp by 1000 first.alg: none is a red flag. Some attacks strip the signature and set the algorithm to none. Production verifiers should reject it outright.- and _ instead of + and /, no = padding), which is why generic Base64 tools sometimes choke on the parts.The JWT spec defines a small set of registered claims with reserved meanings. You'll see these constantly:
iss (issuer) — who created and signed the token, often a URL.sub (subject) — who the token is about, typically a user id.aud (audience) — who the token is intended for; a verifier should reject tokens not meant for it.exp (expiration) — Unix time after which the token must be rejected.nbf (not before) — Unix time before which the token is not yet valid.iat (issued at) — Unix time the token was created.jti (JWT id) — a unique identifier, useful for revocation or replay protection.Everything else is a custom (private) claim: name, email, roles, tenant_id, and so on. The decoder shows registered and custom claims together, but only the registered ones carry spec-defined behavior that verifiers act on.
No. Decoding only reads the Base64URL-encoded header and payload. Verifying validity means checking the signature against the issuer's secret or public key and confirming claims like exp and aud, which requires the key this tool doesn't have.
No. A standard JWT (JWS) payload is Base64URL-encoded, not encrypted. Anyone with the token can read every claim, so never put secrets or sensitive personal data in it. If you need encryption, that's a separate format called JWE.
No. The decoding happens entirely in your browser. The token is never uploaded to a server, which is why it's safe to inspect a real, live token.
Check whether you're comparing exp (which is in Unix seconds) against a millisecond clock, or whether server and client clocks are out of sync. A small clock skew combined with a short lifetime can make a fresh token look expired.
iat is when the token was issued, nbf is the earliest time it's considered valid, and exp is when it stops being valid. All three are Unix timestamps in seconds. A token is only usable in the window between nbf and exp.
JWT uses Base64URL, which replaces + and / with - and _ and drops the = padding. Generic Base64 tools may fail or produce garbage. This decoder handles Base64URL correctly.
Yes. The header and payload are independent Base64URL JSON segments. If you only have one segment (the part before or between the dots), you can decode it on its own; the signature isn't needed to read either one.
kid is the key id. When an issuer uses multiple signing keys, kid tells a verifier which public key (usually from a JWKS endpoint) to use to check the signature. It's informational here and doesn't affect decoding.