How to decode a JWT
A JWT is three base64url strings joined by dots: header, payload and signature. To decode it, split on the dots and base64url-decode the first two parts; each one is a JSON object. Decoding needs no key, because a signed JWT is not encrypted. It also proves nothing: only verifying the signature with the secret or the issuer's public key, and checking exp, nbf, iss and aud, tells you the token is genuine and still valid.

What is inside a JWT?
Take the public sample token used in the JWT documentation:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 .eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ .SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
The first part decodes to {"alg":"HS256","typ":"JWT"}: the token is signed with HMAC-SHA256. The second decodes to {"sub":"1234567890","name":"John Doe","iat":1516239022}. The third is the signature, raw bytes encoded in base64url, which only makes sense to someone holding the key.
What are the common claims?
| Claim | Meaning | Example |
|---|---|---|
| sub | Subject: who the token is about, usually a user id | "1234567890" |
| iss | Issuer: who created the token | "https://auth.example.com" |
| aud | Audience: which API should accept it | "api.example.com" |
| iat | Issued at, Unix seconds | 1516239022 = 2018-01-18 01:30:22 UTC |
| nbf | Not valid before, Unix seconds | - |
| exp | Expires at, Unix seconds | - |
| scope / roles | Permissions (names vary by provider) | "read:orders" |
How can you decode a JWT?
- In the browser: paste the token into the JWT decoder. It shows header and payload as JSON, converts iat, nbf and exp to dates and says whether the token has expired. Nothing is uploaded.
- In a terminal: take the middle part, convert base64url to base64 (replace - with + and _ with /, add = padding) and run
base64 -d, then pipe tojq. - In code: most JWT libraries have a decode function that skips verification, for debugging only. In production call the verify function with the key and the expected algorithm, issuer and audience.
Example: debugging a 401 Unauthorized
An API call that worked yesterday now returns 401. Decode the token from the Authorization header and check, in order:
- exp: is it in the past? Most access tokens live 5 to 60 minutes, so an expired token is the most common cause. Refresh it.
- aud: does it name the API you are calling? A token issued for one API is often rejected by another.
- iss: does it come from the expected tenant or environment? Staging tokens fail on production.
- scope or roles: is the permission for this endpoint there?
- Clock skew: if iat or nbf is a few seconds in the future, the server clock and the issuer clock disagree.
If all of these look right, the signature is the likely problem, for example a rotated signing key, and only the server logs can tell you more.
Which security mistakes should you avoid?
- Trusting a decoded payload. Anyone can create a token with "role": "admin". Only a verified signature makes the claims trustworthy.
- Accepting alg "none" or letting the token choose the algorithm. Fix the expected algorithm on the server side.
- Putting secrets in the payload. A signed JWT is readable by anyone who has it. Use an encrypted token (JWE) or keep sensitive data on the server.
- Pasting live tokens into online tools that send them to a server. A valid access token is a password until it expires.
FAQ
Do I need the secret to decode a JWT?
No. Header and payload are only base64url-encoded. The secret or public key is needed to verify the signature, not to read the content.
Why does my JWT have five parts?
That is an encrypted token (JWE). Its payload can only be read with the decryption key.
How do I know if a JWT is expired?
Compare its exp claim, in Unix seconds, with the current time. The JWT decoder on this site shows exp as a date and marks expired tokens.
Is base64url the same as base64?
Almost: base64url uses - and _ instead of + and /, and usually drops the = padding, so it is safe in URLs and headers.
Last updated: November 2026. Facts about third-party tools come from their public repositories and documentation. Check licenses before commercial use.