🔑 JWT Decoder
Paste a JSON Web Token to see its decoded header and payload, plus whether it has expired. Decoding happens entirely in your browser — the token is never sent to any server, and this tool cannot verify a signature (that needs the signing secret).
How the three parts are read
A JWT is three Base64URL strings joined by dots. This page splits on the dots,
swaps - back to + and _ back to
/, pads to a multiple of four, then decodes the first two parts and
runs JSON.parse on each:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 -> {"alg":"HS256","typ":"JWT"}
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6... -> {"sub":"1234567890","name":"John Doe"}
<signature> -> never touched
An exp, iat or nbf claim is read as Unix
seconds and shown in local time and UTC - iat 1516239022 is
2018-01-18T01:30:22Z. The Expired or Valid badge is only a comparison of
exp against your computer's clock.
What decoding does not tell you
- Decoding is not verifying. The signature is never checked here. Only a server holding the signing key can say whether the claims were tampered with.
- Never put secrets in the payload. Passwords and internal IDs are readable by everyone the token passes through.
- Anything but three dot-separated parts is rejected before decoding, which usually means a truncated paste.
Frequently asked questions
Can this tool tell me if a JWT is genuine?
No. It reads the header and payload and compares the expiry to your clock, but never checks the signature, so a token whose payload was edited by hand decodes and displays exactly like a real one.
Why can anyone read my JWT payload?
Base64URL is an encoding, not a cipher, and the standard JWS format leaves the payload in the clear by design. If the contents must stay private, use an encrypted token (JWE) or an opaque reference token.
My token says expired but the server still accepts it. Why?
The badge compares exp with the clock on your own machine. If that clock is off, or the server allows a few seconds of leeway for skew, the two verdicts disagree near the boundary.