Developer Encoding

JWT decoder

The signature is shown but never verified, that needs the signing key, which this page does not have and should not ask for.

Processed in your browser · nothing is uploaded

Local · never verified, never uploaded

Splits a JWT into its three parts and decodes the header and payload, showing the expiry in readable form when the token carries one. The signature is displayed but not verified.

How to use the jwt decoder

1 Paste the token. The header, payload and signature appear immediately, each on its own block.
2 Read the payload for the claims the token actually carries: who it is for, what it grants, when it was issued.
3 If the token has an exp claim, an EXPIRES line appears underneath with the date and whether it has passed.
4 Copy the decoded payload, or save it as a file.

Not verifying is the only defensible position for a browser tool: verification needs the signing key, and pasting a production signing key into a web page is precisely the mistake nobody should make. Which leads to the point that matters about JWTs generally. A decoded payload proves nothing. Anyone can craft a token with any claims in it, only the signature makes it trustworthy, and only your server holds what is needed to check that. The classic attack is a token whose header says alg: none with an empty third part: it decodes perfectly here, and a server that trusts the header rather than its own configuration will accept it. Two related habits follow. Never put anything confidential in a payload, because it is plain Base64URL and readable by anyone holding the token. And treat a token you have seen in a URL, a log line or a screenshot as compromised, this page included.

The payload is re-serialised as formatted JSON on the way to the screen, which makes it readable and costs two things. Duplicate keys collapse to the last one, so a payload carrying a twice shows a single a. And any number beyond about 9 quadrillion loses precision, because JSON numbers are read as doubles: a sub of 12345678901234567890 comes back as 12345678901234567000. If your identifiers are large integers, compare them against the raw token rather than against what is displayed here.

The sample token this page opens with is the one everybody uses, and it makes a useful point by omission: it carries iat but no exp, so no expiry line appears at all. A missing EXPIRES row means the token has no expiry claim, not that it is fresh. When a row is there, the time is written in UTC as an ISO 8601 string and the expired or valid flag is judged against your own device clock, so a badly set clock will misjudge a token near its boundary. The spec anticipates that and lets a server allow a few minutes of leeway either way.

What people use it for

  • Checking whether an access token has already expired
  • Seeing which claims a login actually issued
  • Finding which user or scope a token from a log belonged to
  • Confirming which algorithm and key id a token names
  • Checking that nothing confidential ended up in a payload

Questions

No, deliberately. Verification needs the signing key, which should never be pasted into a web page.

RFC 7519, JSON Web TokenRFC 7515, JSON Web Signature
Was this tool any good?
Internal signal only · I use it to find the tools worth rebuilding