DevKitHub

API & Security

JWT Decoder — Read a JSON Web Token

Paste a JSON Web Token to read its header and claims. Expiry, not-before and issued-at are converted to real dates. The token is never sent anywhere.

1 line
alg HS256typ JWT
4 lines
5 lines

Signature — not verified

Segment 3
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

This decodes the token; it does not verify the signature. A JWT payload is Base64url, not encryption — anyone holding the token can read it. Treat any token you paste anywhere as compromised.

This tool runs entirely in your browser. Your input is never uploaded, stored or logged.

How it works

A JWT is three Base64url segments joined by dots: header, payload, signature. Decoding the first two is nothing more than a Base64url decode followed by a JSON parse — no key is involved at any point. That is worth sitting with, because it is the property people most often get wrong about tokens: a JWT payload is encoded, not encrypted. Anyone who holds the token can read every claim in it, including this page, including any proxy it passed through, and including whoever finds it in a log file.

What this tool does not do is verify the signature, and that omission is deliberate rather than unfinished. Verification requires the issuer's HMAC secret or public key, and a web page that asks you to paste your signing secret is asking for the credential that mints tokens for your entire system. So there is no "valid" badge anywhere on this page. The status shown is derived purely from the token's own exp and nbf claims measured against your clock, which is arithmetic on data the token already gave away.

The registered time claims — iat, nbf and exp — are defined by RFC 7519 as NumericDate: a count of seconds since 1 January 1970. JavaScript's Date.now() returns milliseconds, so a token built by hand is very often a thousand times off, which puts its expiry somewhere in the year 56000 and means it effectively never expires. Any claim here whose magnitude looks like milliseconds is flagged rather than silently rendered as a far-future date.

Common problems

Every example below is run against this tool in our test suite, so what it says here is what the tool actually does.

A JWT has three dot-separated segments; this has 5.

a.b.c.d.e
Why:
Five segments is a JWE, not a JWS. JWE tokens are encrypted, and the content cannot be read without the decryption key.
Fix:
Nothing can decode a JWE in a browser. You need the key and a JWE library on the server that owns it.

The header segment is not valid Base64url.

!!!.eyJhIjoxfQ.sig
Why:
Usually a truncated copy, or a token that was URL-encoded somewhere in transit so its dots or dashes were rewritten.
Fix:
Re-copy the whole token. If it came from a URL, percent-decode it first.

The payload segment decoded, but it is not JSON.

eyJhbGciOiJIUzI1NiJ9.aGVsbG8.sig
Why:
The middle segment contained something other than a JSON object — often an opaque session id from a system that only looks like it uses JWTs.
Fix:
Check what actually issued the token. Not every dot-separated string is a JWT.

The payload decoded to an array, but a JWT payload must be a JSON object.

eyJhbGciOiJIUzI1NiJ9.WzFd.sig
Why:
RFC 7519 requires the claims set to be a JSON object. An array is valid JSON but cannot carry named claims.
Fix:
The token is malformed. Fix whatever built it.

Frequently asked questions

Does this verify the signature?
No, and it never will. Verifying needs the issuer's secret or public key, and you should not paste a signing secret into a web page. This tool decodes the token and reads its time claims; it makes no statement about who issued it.
Is it safe to paste a real token here?
Decoding happens entirely in your browser and nothing is uploaded or logged. That said, a JWT is a live credential: if you have pasted one into any online tool, the safe assumption is that it is compromised, and you should let it expire or revoke it.
Why does my token say it expires in the year 56000?
The exp claim is in seconds, but Date.now() returns milliseconds. Dividing by 1000 fixes it. This tool flags a time claim whose magnitude looks like milliseconds instead of rendering the absurd date without comment.
What does alg "none" mean?
It means the token is unsigned. It was allowed by the original specification and is the root of a well-known family of authentication bypasses: an attacker strips the signature, sets alg to none, and a server that trusts the header accepts a token anyone can forge. Servers must pin the expected algorithm rather than read it from the token.

Read more about this

Last updated