How-to guide

How to Decode a JWT

To decode a JWT, paste it into a JWT decoder. The token is three Base64url segments separated by dots: header, payload and signature. The decoder reads the first two and shows the claims, including exp and iat as readable dates. Decoding is not verification — anyone can read a JWT, so never trust its claims without checking the signature on your backend.

JWT Decoder

Read a JSON Web Token header, payload and expiry.

Open the tool

A JWT is not encrypted. It is signed. The header and payload are Base64url-encoded, which is an encoding, not a cipher, and anyone holding the token can read every claim inside it. That is by design, and it is the single most misunderstood thing about the format.

The signature is what makes a JWT trustworthy, and checking it requires the signing key. That is why a decoder in a web page can show you what a token says but can never tell you whether to believe it.

Step by step

  1. Paste the token

    Paste the whole thing, including both dots. If you copied it from an Authorization header, drop the leading "Bearer " prefix — that is part of the header, not the token.

  2. Read the header

    The header names the signing algorithm in alg and the token type in typ. A kid value, when present, identifies which key from a key set was used, which matters when a service rotates keys.

  3. Read the payload claims

    The payload holds the claims. The registered ones are iss (issuer), sub (subject), aud (audience), exp (expiry), nbf (not before), iat (issued at) and jti (token id). Everything else is application-specific.

  4. Check the expiry

    exp and iat are Unix timestamps in seconds, not milliseconds. The decoder renders them as dates and flags a token that has already expired, which is the most common cause of a 401 that "worked yesterday".

  5. Verify on the backend, not here

    Verification requires the secret or public key, and pasting a signing key into any web page is a bad habit. Check the signature in your own service, using a library that validates alg rather than trusting the header.

Example

The payload segment of a token, decoded. exp is a Unix timestamp in seconds.

Token payload segment

eyJzdWIiOiIxMjM0IiwibmFtZSI6IkFkYSIsImlhdCI6MTc1NDUyMTIwMH0

Decoded claims

{
  "sub": "1234",
  "name": "Ada",
  "iat": 1754521200
}

iat  →  7 Aug 2025, 00:00:00 UTC

Frequently asked questions

Does decoding verify the token?
No, and the distinction matters. Decoding reads the Base64url-encoded header and payload, which anyone can do. Verifying checks the signature against a key to prove the token was issued by who it claims and has not been altered.
Is it safe to paste a real token here?
Decoding happens entirely in your browser and the token is never transmitted. That said, a live token is a credential: treat it as you would a password, prefer expired or test tokens, and never paste your signing key anywhere.
Why does my token show as expired?
The exp claim is in the past. JWT timestamps are Unix seconds, not milliseconds — a common bug is issuing exp in milliseconds, which puts it tens of thousands of years in the future instead.
What does alg: none mean?
An unsigned token. Historically some libraries accepted it and trusted the payload, which was a serious vulnerability. Any verifier should reject none outright and check the algorithm against an expected value rather than reading it from the token.
Can I decode an encrypted JWE?
No. A JWE has five segments rather than three and its payload is genuinely encrypted, so decoding it requires the decryption key. This decoder handles signed JWS tokens, which is what almost all APIs issue.

Tools used in this guide

All tools →
All guides →

Last reviewed .