About the JWT Decoder
This free JWT decoder reads a JSON Web Token and shows its header and payload as formatted JSON, with the issued and expiry times converted into readable dates.
Decoding happens in your browser — your token is never uploaded. That is not a minor point: a JWT is usually a live credential, and pasting one into a website that sends it somewhere hands over whatever access it carries.
This tool decodes a token. It does not verify the signature — see below for why that distinction matters.
The three parts of a token
A JWT is three chunks of Base64url separated by dots:
xxxxx.yyyyy.zzzzz
Header — which algorithm signed the token and what type it is. Usually two fields: alg and typ.
Payload — the claims. Who the token is about, who issued it, when it expires, and whatever else the application put in: user ID, email, roles, permissions, tenant.
Signature — a cryptographic check over the first two parts, made with a secret or a private key. It proves the token has not been altered since it was issued.
The essential thing to understand: the first two parts are not encrypted. They are merely encoded, and anyone can read them. Paste a token into this page and its contents appear instantly. Base64url is a way of making data safe to put in a URL or header, not a way of hiding it.
What that means for what you put in a token
Since the payload is public to anyone holding the token, the rule follows directly: never put anything secret in a JWT.
Things that do not belong in a payload: passwords, API keys, credit card details, national identity numbers, medical information, anything covered by privacy regulation. All of it is readable by the user, by anything that logs the request, and by anyone who obtains the token.
Things that do belong: a user ID, a role, an expiry, an issuer, an audience — identifiers and claims that are meant to be seen by the system receiving them.
The signature protects integrity, not confidentiality. It guarantees nobody changed the token. It does nothing to stop them reading it.
Decoding is not verifying
This is the distinction that causes real security bugs, so it is worth being precise.
Decoding unpacks the Base64url and shows you the JSON. It needs no key, anybody can do it, and it proves nothing whatsoever about whether the token is genuine.
Verifying recomputes the signature using the secret or public key and checks that it matches. Only this tells you the token was really issued by who it claims and has not been tampered with.
A token can decode perfectly and be a complete forgery. Anyone can craft a JWT that says "role": "admin" and it will display beautifully here — because displaying it is all that is happening.
This tool deliberately does not verify, and that is the safe choice: verification requires the signing secret, and pasting your signing secret into a web page would be far more dangerous than pasting a token. Verification belongs on your server, with your key, using a proper library.
The historical version of this mistake is the alg: none attack. Early JWT libraries honoured a header claiming no algorithm was used and accepted the token unverified. An attacker could edit the payload, set alg to none, and walk in. Modern libraries reject it, but it is why you should always pin the expected algorithm rather than trusting the header to tell you.
Reading the standard claims
Most of the short field names in a payload are registered claims with fixed meanings:
- exp — expiry time. After this, the token should be rejected.
- iat — issued at. When it was created.
- nbf — not before. The token is invalid until this time.
- sub — subject. Usually the user ID.
- iss — issuer. Who created the token.
- aud — audience. Which service it is meant for.
- jti — token ID, used for revocation lists.
exp, iat and nbf are Unix timestamps — seconds since 1 January 1970 — which is why they look like a meaningless ten-digit number. This tool converts them to readable dates, which is usually the fastest way to answer the question that brought you here: *has this token expired?*
How to use it
- Paste your JWT (the xxxxx.yyyyy.zzzzz string)
- Read the decoded header and payload below
- Copy either part if you need it
Good to know
- Treat a token like a password. If it is still valid, whoever holds it can act as that user. Do not paste live tokens into tools that upload them, and do not post them in a ticket or a chat.
- JWTs are hard to revoke. They are valid until they expire, so a stolen token works until then unless you maintain a blocklist. This is why short expiry times matter.
- Bearer is not part of the token. Strip that prefix from an Authorization header before decoding.
- Base64url is not standard Base64. It uses - and _ instead of + and / and usually drops the = padding, which is why a JWT chunk may fail in a plain Base64 decoder.
- Clock skew causes confusing failures. A token can look valid to you and be rejected by a server whose clock differs by a minute or two.
- A JWT is not a session. It carries its claims with it, so changes to a user's role do not take effect until the token expires.
Common questions
Is a JWT encrypted?
No. The header and payload are Base64url-encoded, which makes them safe to put in a URL or an HTTP header but does nothing to hide them. Anyone holding the token can read every claim inside it, as this page demonstrates. The signature protects the token from being modified, not from being read.
Does this tool verify the signature?
No, and deliberately so. Verifying requires the signing secret or public key, and pasting your signing secret into a web page would be considerably more dangerous than pasting a token. Verification belongs on your server using a proper library. This tool decodes and shows you the contents, which is what you need when debugging.
Is it safe to paste my token here?
Here, yes — the decoding happens entirely in your browser and nothing is transmitted, so you can disconnect from the internet and it still works. Be careful with tools generally, though. A live JWT is a working credential, and a site that sends it to a server has just been handed whatever access it grants.
How do I tell if my token has expired?
Look at the exp claim, which is a Unix timestamp in seconds. This tool converts it to a readable date and tells you directly whether the moment has passed. If a token looks valid to you but a server rejects it, check for clock skew — a difference of a minute or two between machines is enough.
What do sub, iss, aud and iat mean?
They are registered claims with standard meanings: sub is the subject, normally the user ID; iss is the issuer that created the token; aud is the intended audience, meaning which service should accept it; iat is when it was issued. Together with exp and nbf they cover who, where and when.
Why does my JWT fail in a normal Base64 decoder?
Because a JWT uses Base64url, a variant that replaces + with - and / with _ and usually removes the = padding. Those substitutions exist so the value is safe inside a URL. Swapping the characters back makes it decode in a standard Base64 tool.
Can I edit a JWT payload?
You can change the text, but the result will be rejected by any correctly implemented server, because the signature no longer matches the modified content. That is precisely what the signature is for. Tokens are reissued by the service that signs them, not edited by hand.
Related tools
- Base64 Encode / Decode — the encoding the three chunks are written in
- JSON Formatter — tidy and inspect the decoded payload
- Hash Generator — the hash functions underneath the signature