🔑 JWT Decoder
Decode and inspect JWT tokens instantly — view header, payload, and signature. Verify signatures with your secret. Free online JWT decoder — nothing sent to any server.
How to Use
Paste your JWT
Copy your JWT token (starting with eyJ) and paste it into the input field.
Click Decode
Press Decode to instantly split and decode all three parts: header, payload, and signature.
Inspect the token
Read the decoded JSON, check expiration dates, algorithm, and any custom claims in the payload.
Frequently Asked Questions
Complete Guide: JWT Decoder
What Is a JWT and Why It Matters
A JSON Web Token (JWT), standardized in RFC 7519, is a compact, URL-safe token format that encodes claims — assertions about an entity (typically a user) and additional metadata. JWTs are the dominant authentication mechanism in single-page applications, mobile APIs, and microservices because they're stateless: the server doesn't need a session store to validate a request. The token itself carries the user's identity and permissions.
A JWT has three Base64url-encoded parts separated by dots: header.payload.signature. The header specifies the algorithm (alg) and token type. The payload contains claims — registered claims like iss (issuer), sub (subject), exp (expiration time), iat (issued at) — plus any custom claims your application needs. The signature is a cryptographic signature over the header and payload that proves the token hasn't been tampered with.
Critical distinction: decoding is not verification. Anyone can decode a JWT's header and payload — they're just Base64url-encoded, not encrypted. The signature verification (using the server's secret key for HS256 or the public key for RS256) is what proves authenticity. This tool decodes (reads the claims) without verifying. Never trust claims from a decoded JWT in a production application without verifying the signature server-side.
How to Use the JWT Decoder
- Paste your JWT (the long eyJ… string) into the input field.
- Click Decode to split and decode all three parts.
- Read the Header — check the algorithm (
alg). HS256 uses a shared secret; RS256 uses a public/private key pair. - Read the Payload — check
exp(Unix timestamp — is the token expired?),iss(issuer — does it match your auth server?), and any custom claims. - The Signature section shows the signature bytes — it cannot be verified without the secret key, but this tool shows you its encoding.
Code Examples
// Decode a JWT without a library (client-side, no verification)
function decodeJwt(token) {
const [header, payload] = token.split('.');
const decode = (b64url) => JSON.parse(
atob(b64url.replace(/-/g, '+').replace(/_/g, '/').padEnd(
b64url.length + (4 - b64url.length % 4) % 4, '='
))
);
return { header: decode(header), payload: decode(payload) };
}
// Node.js: verify and decode with the 'jose' library (recommended)
import { jwtVerify } from 'jose';
const secret = new TextEncoder().encode('your-256-bit-secret');
const { payload } = await jwtVerify(token, secret, {
issuer: 'https://auth.example.com',
audience: 'https://api.example.com',
});
// Check expiration in the payload
const isExpired = (decodedPayload) =>
Date.now() >= decodedPayload.exp * 1000;
// Python: PyJWT
import jwt
decoded = jwt.decode(token, 'secret', algorithms=['HS256'],
options={'verify_exp': True})
Common Mistakes to Avoid
- Storing JWTs in localStorage — Accessible to any JavaScript on the page, including injected XSS scripts. Use
httpOnlycookies (inaccessible to JS) for tokens with sensitive permissions. Use localStorage only for non-sensitive, short-lived tokens. - The "alg: none" attack — Some older JWT libraries accept a token with
"alg": "none"and no signature. Always explicitly specify allowed algorithms server-side and rejectnone. - Algorithm confusion attacks — If your server accepts both HS256 (symmetric) and RS256 (asymmetric), an attacker might craft a token signed with the public key as if it were the HS256 secret. Always lock down the allowed algorithm list.
- Long-lived access tokens — An access token should expire in 15 minutes to an hour. Use refresh tokens (longer-lived, stored securely, rotated on use) to obtain new access tokens.
- Putting sensitive data in the payload — The payload is only Base64url-encoded, not encrypted. Any party with the token can read the payload. Don't include PII, passwords, or secrets.
- Not validating
issandaudclaims — Always verify that the token was issued by your auth server (iss) and intended for your API (aud).
Comparison with Alternatives
Opaque tokens (random strings stored in a server-side session store like Redis) are more secure than JWTs because they can be instantly revoked and contain no readable claims. The tradeoff is a database lookup on every request. Paseto (Platform-Agnostic Security Tokens) was designed to fix JWT's algorithm confusion and "alg: none" vulnerabilities — a safer choice for new systems where you control both client and server. Session cookies with server-side sessions remain the gold standard for traditional web apps — simpler to revoke, no XSS token theft risk if using httpOnly; Secure; SameSite=Strict.
JWTs use Base64url encoding internally — understand how it works with the Base64 Encoder. Token headers and payloads contain JSON — validate their structure with the JSON Formatter.
Pro Tips
- JWT expiry in your timezone: The
expclaim is a Unix timestamp (seconds since 1970-01-01 UTC). Convert withnew Date(payload.exp * 1000)to see the human-readable expiry time. - Rotate refresh tokens on use: Each time a refresh token is used to get a new access token, issue a new refresh token and invalidate the old one. This detects token theft: if the old token is used after rotation, both tokens are invalidated.
- JWK Sets for RS256: Instead of hard-coding a public key, point your verifier at a JWKS endpoint (
/.well-known/jwks.json). Key rotation then happens without redeploying your service. - Keep JWTs small: Every authenticated request sends the full JWT in the header. Overfilling the payload (50+ claims) adds bandwidth and slows header parsing. Keep it to essential claims only.