If you've ever worked with a REST API that uses authentication, you've almost certainly dealt with a JWT — JSON Web Token. They're compact, self-contained, and widely used for transmitting user identity and permissions between systems.
But when one of these tokens shows up in a bug report, an auth failure log, or a Postman response, you need to quickly answer: What's in this token? Is it expired? What claims does it carry?
This guide explains what JWTs are, how to read them, and how to decode them safely — without pasting tokens into an untrusted third-party site.
What Is a JWT?
A JSON Web Token is a Base64url-encoded string with three parts separated by dots:
- Header (pink) — algorithm and token type
- Payload (green) — the claims (user ID, roles, expiry, etc.)
- Signature (blue) — cryptographic proof the token hasn't been tampered with
Each part is Base64url-encoded — not encrypted. That means the header and payload are readable by anyone who has the token. Only the signature requires the secret key to validate.
The Three Parts Decoded
1. Header
Decoding the header gives you the algorithm used to sign the token and the token type:
"alg": "HS256",
"typ": "JWT"
}
Common algorithms: HS256 (HMAC-SHA256, shared secret), RS256 (RSA, public/private key), ES256 (ECDSA). RS256 and ES256 are preferred in production as they don't require sharing the secret.
2. Payload (Claims)
This is the important part. The payload contains claims — statements about the user and the token itself. Here are the standard registered claims:
| Claim | Full Name | Description |
|---|---|---|
| sub | Subject | Who the token is about — usually a user ID |
| iss | Issuer | Who issued the token (e.g. your auth server URL) |
| aud | Audience | Who the token is intended for — must match your API |
| exp | Expiration | Unix timestamp — token is invalid after this time |
| iat | Issued At | Unix timestamp when the token was created |
| nbf | Not Before | Token is invalid before this timestamp |
| jti | JWT ID | Unique identifier — used to prevent replay attacks |
In addition to these standard claims, tokens often carry custom claims like name, email, role, scope, or any application-specific data your auth server puts in.
3. Signature
The signature is computed as:
base64urlEncode(header) + "." + base64urlEncode(payload),
secret
)
You cannot verify the signature client-side without the secret key or public certificate. Decoding only reads the header and payload — it does not validate authenticity. Always verify signatures on your backend.
How to Decode a JWT — Step by Step
eyJ (that's the Base64url-encoded {").sub, iss, exp, etc.) is explained inline.Why Not Paste Tokens Into Random Sites?
JWTs often contain real user data — names, email addresses, user IDs, permission roles. Some decode tools send the token to their server for processing. If the token is still valid, a malicious server could:
- Log the token and replay it against your API
- Extract user PII from the payload
- Use it to impersonate the token subject if your API doesn't validate the signature
The WebToolsz JWT Decoder decodes tokens using only atob() and JSON.parse() — both built into your browser. No network request is made with your token.
Decoding a JWT Manually
If you prefer the command line or want to understand the mechanics:
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0In0.abc"
# Header
echo $TOKEN | cut -d'.' -f1 | base64 -d 2>/dev/null | python3 -m json.tool
# Payload
echo $TOKEN | cut -d'.' -f2 | base64 -d 2>/dev/null | python3 -m json.tool
Note: Base64url encoding uses - and _ instead of + and /. You may need to pad with = characters if base64 -d complains.
Common JWT Debugging Scenarios
Token rejected with 401 Unauthorized
Check: Is exp in the past? Is aud correct for your API? Is the token from the right iss? All three are common sources of rejections even when the token is structurally valid.
User sees stale permissions after a role change
JWTs are stateless — the server can't invalidate them once issued. If a user's role changes, they'll keep their old permissions until the token expires. Short expiry times (15–60 minutes) combined with refresh tokens is the standard solution.
Missing claims on the frontend
Decode the token and check whether the claim is present in the payload. If it's missing, the issue is in token generation (your auth server isn't including it), not in your frontend code reading it.
Token works in Postman but not in the browser
Check if the aud claim matches what your API expects. Postman may not validate audience — your browser app might. Also verify the token isn't being double-encoded (e.g. URL-encoding the dots).
Decode Your JWT Now — Free & Private
Paste any token to instantly inspect header, payload, claims and expiry. Runs in your browser — zero data upload.
Open JWT DecoderFrequently Asked Questions
Is it safe to paste my JWT token in an online decoder?
Yes — if the tool runs entirely in your browser. WebToolsz JWT Decoder uses only built-in browser APIs (atob, JSON.parse). Your token is never sent to any server, never logged, and never stored. You can safely paste tokens containing user IDs, roles, and claims.
Can a JWT decoder verify the signature?
No. Signature verification requires the secret key (for HS256) or the public key (for RS256/ES256). These should never be exposed in a browser. Use a backend library like jsonwebtoken (Node.js), PyJWT (Python), or java-jwt (Java) to verify signatures securely.
What is the exp claim in a JWT?
exp is the expiration time, expressed as a Unix timestamp (seconds since Jan 1, 1970 UTC). If the current time is past exp, the token is expired and must be rejected by your server. Always validate exp on the server — never trust a client-side check alone.
What algorithms do JWT tokens use?
The most common are HS256 (HMAC-SHA256, shared secret), RS256 (RSA with SHA-256, public/private key), and ES256 (ECDSA). RS256 and ES256 are preferred for production because they allow signature verification without distributing the signing secret.
Last updated: March 2026 | Back to Blog | Privacy Policy