How to Decode a JWT Token Online
Last updated:
A JWT has 3 dot-separated base64url-encoded parts: header, payload, and signature. Decoding the payload requires no library — split on ., replace -→+ and _→/, then call atob() and JSON.parse() in 4 lines. Decoding is not verification — anyone with the token can read the payload; the 256-byte RS256 signature only proves the token was not tampered with. The 5 standard payload claims to check when debugging a 401 are sub, exp (Unix seconds), iat, aud, and iss. This guide covers 5 signing algorithms (HS256, RS256, ES256, EdDSA, none), decode patterns in the browser and Node.js, expiry checking, and when to verify instead of decode.
What is a JWT?
A JSON Web Token (JWT) is a compact, URL-safe string used to represent claims between two parties. In practice, you'll encounter them as authentication tokens: your app logs in, the server returns a JWT, and you send that token in the Authorization header on every subsequent request.
A JWT looks like this:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzEyMyIsIm5hbWUiOiJBbGljZSIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTcwNTMxMjIwMCwiZXhwIjoxNzA1Mzk4NjAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cThree base64url-encoded parts, separated by dots. They are not encrypted — they are signed. Anyone can decode and read the contents. The signature only proves the token hasn't been tampered with.
The three parts of a JWT
Part 1: Header
The first segment contains metadata about the token itself — specifically, which signing algorithm was used.
// Encoded:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
// Decoded:
{
"alg": "HS256",
"typ": "JWT"
}Common values for alg: HS256 (HMAC-SHA256, symmetric),RS256 (RSA-SHA256, asymmetric), ES256 (ECDSA). If you're integrating with an OAuth provider, you'll often see RS256.
Part 2: Payload
The payload contains the actual claims — data the token is asserting. There are registered claim names with well-known meanings, plus custom claims your app defines.
// Encoded:
eyJzdWIiOiJ1c2VyXzEyMyIsIm5hbWUiOiJBbGljZSIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTcwNTMxMjIwMCwiZXhwIjoxNzA1Mzk4NjAwfQ
// Decoded:
{
"sub": "user_123",
"name": "Alice",
"role": "admin",
"iat": 1705312200,
"exp": 1705398600
}Standard registered claims:
sub— subject: the user or entity the token refers toiat— issued at: Unix timestamp when the token was createdexp— expiration: Unix timestamp after which the token is invalidiss— issuer: who created the tokenaud— audience: who the token is intended forjti— JWT ID: a unique identifier for the token (used to prevent replay)
Part 3: Signature
The signature is computed by hashing the encoded header + encoded payload with a secret key (for HS256) or a private key (for RS256/ES256). The server validates the signature on every request to confirm the token is authentic and unmodified.
Decoding a JWT does not verify the signature — that requires the secret or public key. Decoding only unpacks the base64url encoding to reveal the JSON contents.
JWT signing algorithms compared
The alg claim in the JWT header names the signing algorithm. Five algorithms cover almost all production tokens; the choice between them is a tradeoff of key type, signature size, and rotation cost.
alg | Family | Key type | Signature size | Best for |
|---|---|---|---|---|
HS256 | HMAC + SHA-256 | Shared secret | 32 bytes | Same-service tokens, internal APIs |
RS256 | RSA + SHA-256 | RSA keypair (2048-bit) | 256 bytes | Third-party verification (JWKS) |
ES256 | ECDSA + SHA-256 (P-256) | EC keypair | 64 bytes | Mobile, low bandwidth |
EdDSA | Ed25519 | EC keypair | 64 bytes | Fastest verification, modern stacks |
none | — | None | 0 bytes | Never in production — reject server-side |
When to decode a JWT
Debugging authentication errors
Getting a 401 on an authenticated request? Decode the token and check:
- Is
expin the past? The token expired. - Is
audset to the wrong service? The token is for a different API. - Is
subwhat you expect? You might be using a token from the wrong user. - Is the role or permission claim missing? Your auth middleware might not have included it.
Checking expiry
The exp claim is a Unix timestamp (seconds since epoch). To convert it manually:
// exp: 1705398600
new Date(1705398600 * 1000).toISOString()
// → "2024-01-16T10:30:00.000Z"A good JWT decoder shows this as a human-readable date automatically, saving you the conversion.
Inspecting claims from OAuth providers
When integrating Google, Auth0, Okta, or another OAuth provider, the ID token or access token contains claims your app needs (email, name, roles, scopes). Decoding lets you verify the provider is sending exactly what you expect before writing the code to consume it.
Security: never paste production tokens into untrusted tools
This is important. A JWT issued in production is a valid credential. Pasting it into a random online tool means:
- The tool's server might log it
- The payload (including user data) is now on someone else's system
- If the token hasn't expired, it can be replayed
For production tokens, either decode them locally in your browser's DevTools console —atob(token.split('.')[1]) — or use a tool that explicitly processes everything client-side with no server uploads.
Jsonic's JWT decoder runs entirely in your browser. Nothing is sent to any server. That makes it safe to use for inspecting tokens during development and staging — though for sensitive production tokens, local decoding is always the right default.
Decoding a JWT manually
You can decode a JWT in any browser console without a tool:
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzEyMyJ9.signature'
const [header, payload] = token.split('.')
JSON.parse(atob(header)) // → { alg: 'HS256', typ: 'JWT' }
JSON.parse(atob(payload)) // → { sub: 'user_123' }Note: atob expects standard base64, but JWTs use base64url (uses -and _ instead of + and /). For most tokens this doesn't matter, but strictly you should replace those characters first:
function decodeJwtPart(part) {
const base64 = part.replace(/-/g, '+').replace(/_/g, '/')
return JSON.parse(atob(base64))
}Decode a JWT now
Paste any JWT token into Jsonic's JWT Decoder to instantly see the header, payload, and expiry time formatted as human-readable JSON and dates. No server. No uploads.
Open JWT DecoderFrequently asked questions
How do I decode a JWT token without a library?
Split on dots, base64url-decode the first two parts, and parse as JSON:JSON.parse(atob(token.split('.')[1].replace(/-/g,'+').replace(/_/g,'/'))). The third part (signature) is binary, not JSON.
What is the difference between decoding and verifying a JWT?
Decoding unpacks the base64url encoding to read the payload — anyone can do this. Verifying checks the signature using the secret or public key to confirm the token is authentic and unmodified. Never trust claims without server-side verification.
What are the three parts of a JWT?
Header (algorithm and token type), Payload (claims: sub, exp, iat, custom fields), and Signature (computed by the server). All three are base64url-encoded and separated by dots.
Is the JWT payload encrypted or just encoded?
Just encoded — anyone with the token can read the payload. JWTs are signed (to detect tampering) but not encrypted by default. Never put sensitive data like passwords in a JWT payload.
How do I check if a JWT has expired?
Read the exp claim and compare to Date.now() / 1000:Date.now() / 1000 {'>'} payload.exp means expired. Always validate expiry server-side during signature verification for security.
What is the exp claim in a JWT?
The exp (expiration time) claim is a Unix timestamp in seconds after which the token must be rejected. Common lifetimes are 1 hour for access tokens and 7–30 days for refresh tokens. Related claims: iat (issued at) and nbf (not before).
Further reading and primary sources
- RFC 7519 — JSON Web Token (JWT) — IETF JWT specification
- RFC 7515 — JSON Web Signature (JWS) — Signature mechanism used by signed JWTs
- RFC 4648 — Base64url Encoding — URL-safe Base64 used in JWT segments
- OWASP — JWT Cheat Sheet — Security guidance for JWT consumers
Recommended reading
- Designing Data-Intensive Applications (2nd Edition) — Martin Kleppmann & Chris RiccominiThe modern classic on data systems — encoding formats, schemas, replication, and stream processing.
- API Design Patterns — JJ GeewaxBattle-tested patterns for designing consistent, scalable JSON APIs — from a Google API architect.
As an Amazon Associate, Jsonic earns from qualifying purchases.