Skip to content
Plaintools

JWT decoder

Paste a JWT. We base64url-decode the header and payload in this tab and format iat, exp, and nbf as dates. The signature is shown, not verified. Treat any token you paste as secret — this page does not send it anywhere, but your browser extensions still can.

The token is decoded in this tab. It is not sent anywhere.

Example

The jwt.io sample token

The classic HS256 example decodes to alg HS256, sub 1234567890, and an exp in 2018, so the expired flag is true.

Related: JSON to CSV converter, YAML to JSON converter, Text diff checker

FAQ

Do I need a secret to decode a JWT?
No. The header and payload are Base64URL-encoded JSON, not encrypted, so decoding needs no secret. A secret or public key is only for signature verification, which this tool does not do.
Does this verify the signature?
No. Verification needs the secret or public key and a chosen algorithm. This tool only decodes so you can read claims. A decoded token is not a valid token.
Is my token uploaded?
No. Decoding uses atob and JSON.parse in the page. There is no API route and no analytics beacon that includes the textarea. If you need a stronger guarantee, disconnect the network before you paste.
What does the expired flag mean?
If exp is a numeric claim, we compare exp * 1000 to Date.now() in your timezone. Missing exp means we cannot say. nbf in the future is called out separately; it is not the same as expired.
Why did decoding fail?
A JWT has three base64url segments. We fail on missing dots, invalid base64, or non-JSON header/payload. Encrypted JWEs (five segments) are not supported.
Can I edit claims and re-encode?
Not here. Re-encoding without the correct signature would mint a token that looks real and is not. Use your issuer if you need a new token.
How do I decode a JWT without this page?
Trim and split on “.”. Require exactly three nonempty segments (JWEs with five segments are unsupported). For header and payload: base64url (replace - with +, _ with /; pad with “=” to a multiple of 4); atob; UTF-8 JSON object. Show the third segment as the signature; do not verify it. If iat/exp/nbf is a number, display new Date(claim * 1000) as ISO plus locale. expired if exp * 1000 < Date.now(); notYetValid if nbf * 1000 is in the future. Missing exp/nbf is not treated as expired or not-yet-valid.