Skip to content
Json Works

How to Decode and Inspect a JWT Safely

Updated

A JSON Web Token (JWT) is the long string that follows Bearer in an Authorization header. It looks like random characters, but it is just three pieces of Base64 text joined by dots, and two of them are readable JSON. Decoding one is the quickest way to debug “why am I getting 401?” problems.

Anatomy of a token

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxNyIsIm5hbWUiOiJBZGEiLCJleHAiOjE3NjAwMDAwMDB9.signature...

A JWT has three parts, separated by dots:

  1. Header. Says how the token is signed, for example {"alg":"HS256","typ":"JWT"}.
  2. Payload. The claims: facts about the user and the token, for example {"sub":"17","name":"Ada","exp":1760000000}.
  3. Signature. A cryptographic value the server uses to detect tampering.

The header and payload are Base64URL-encoded JSON. That is encoding, not encryption: anyone holding the token can read them.

Decode a token

  1. Copy the token. In Postman, it is in the Authorization tab or the Authorization header; in a browser, check the Network tab or the application’s storage.
  2. Paste it into the JWT Decoder.
  3. Read the header and payload as formatted JSON.

Decoding runs in your browser, which matters here: a live token is a credential. A decoder that uploads it to a server asks you to hand over access to the account.

Standard claims

Claim Name Meaning
iss Issuer Who created the token
sub Subject Who it is about, usually a user ID
aud Audience Who it is intended for
exp Expiration When it stops being valid (Unix seconds)
nbf Not before When it starts being valid
iat Issued at When it was created
jti JWT ID A unique identifier for the token

Applications add their own, such as roles, email, scope or tenant_id.

Time claims

exp, nbf and iat are Unix timestamps in seconds, so 1760000000 is a moment in October 2025. Two common mistakes: treating them as milliseconds (the result is a date in the year 55,000), and forgetting clock skew between servers. The decoder converts them to readable dates and tells you whether the token has expired.

Debugging checklist

When a request fails with 401 or 403, decode the token and check:

  • Expired? Compare exp to the current time. This is the most common cause.
  • Not yet valid? Check nbf and iat. A server clock that is slightly behind can reject a brand new token.
  • Right audience? aud must match the API you are calling.
  • Right issuer? iss must be the identity provider the API trusts. Staging tokens sent to production fail here.
  • Missing scope or role? A 403 usually means the token is valid but lacks a permission. Look at scope, scp or roles.
  • Right algorithm? The alg in the header must match what the server expects.

Decoding is not verifying

This is the most important point about JWTs. Reading a payload tells you what the token claims. It does not prove the token is genuine. Anyone can write a token with "role":"admin" and any signature at all. Only verifying the signature with the right key shows the token was issued by someone who holds that key and has not been altered.

Never trust claims from an unverified token in a security decision. A server must verify the signature, and also check exp, iss and aud, before acting on a token.

Verifying a signature

How you verify depends on the algorithm in the header.

HS256, HS384, HS512 use a shared secret (HMAC). Anyone who has the secret can both create and verify tokens. You can verify these in the decoder by entering the secret, and it stays in your browser. This is useful for local development and test tokens.

RS256, ES256 and similar use a public/private key pair. The provider signs with a private key and publishes a public key, usually at a JWKS URL such as https://issuer.example.com/.well-known/jwks.json. Verifying needs that public key, and is normally done in your server code with a library.

alg: none means “unsigned”. A server must never accept it. If you see it in a token meant for a real API, something is wrong.

Security notes

  • Do not put secrets in a JWT payload. It is readable by anyone who gets the token, including in logs and browser storage.
  • Treat tokens as passwords. Do not paste live production tokens into tools you do not trust, or into tickets and chat. Use short-lived tokens and revoke if one leaks.
  • Keep expiry short and use refresh tokens for longer sessions.
  • Verify on the server, always. Client-side decoding is for display only.

Tokens that are not JWTs

Not every bearer token is a JWT. Opaque tokens, such as random strings or GitHub personal access tokens, have no readable contents, and the decoder will report them as invalid. They can only be checked by the server that issued them.

Working with the payload

The payload is JSON, so everything else on this site applies. Paste it into the JSON Formatter to pretty-print it. Diff two tokens from different environments to find what differs. If the token arrives as part of a cURL command or a Postman collection, pull it from the Authorization header first.

More guides

All guides · FAQ