JWT (JSON Web Tokens) are everywhere in modern web development — auth tokens, API keys, OAuth flows. But when something goes wrong, you need to quickly inspect what's inside.
This post covers how JWT decoding works and shows a few ways to do it.
JWT Structure
A JWT has three Base64URL-encoded parts separated by dots:
<header>.<payload>.<signature>
Example:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiJ1c2VyXzEyMyIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImV4cCI6MTcxNjIzOTAyMn0
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Method 1: Browser Console (Quick Debug)
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
const [header, payload] = token.split('.');
console.log(JSON.parse(atob(payload.replace(/-/g, '+').replace(/_/g, '/'))));
// {sub: "user_123", email: "user@example.com", exp: 1716239022}
Method 2: Online Tool
Paste your token at aiforeverthing.com/jwt-decoder.html — it decodes client-side in your browser (nothing sent to a server), shows expiry status, and highlights all standard claims.
Method 3: CLI with jq
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
echo $TOKEN | cut -d. -f2 | base64 -d 2>/dev/null | jq .
Method 4: Node.js
function decodeJWT(token) {
const base64Decode = str => Buffer.from(
str.replace(/-/g, '+').replace(/_/g, '/'), 'base64'
).toString('utf8');
const [headerB64, payloadB64] = token.split('.');
return {
header: JSON.parse(base64Decode(headerB64)),
payload: JSON.parse(base64Decode(payloadB64)),
};
}
const { header, payload } = decodeJWT(token);
console.log('Algorithm:', header.alg);
console.log('User ID:', payload.sub);
console.log('Expires:', new Date(payload.exp * 1000));
Method 5: REST API
curl -X POST https://api.aiforeverthing.com/api/jwt/decode \
-H "Content-Type: application/json" \
-d '{"token": "YOUR_JWT_HERE"}'
Returns:
{
"success": true,
"data": {
"header": { "alg": "HS256", "typ": "JWT" },
"payload": { "sub": "user_123", "exp": 1716239022 },
"signature": "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}
}
Common JWT Claims Reference
| Claim | Name | Description |
|---|---|---|
iss |
Issuer | Who issued the token |
sub |
Subject | User/entity identifier |
aud |
Audience | Intended recipient |
exp |
Expiration | Unix timestamp when it expires |
iat |
Issued At | When it was created |
nbf |
Not Before | Not valid before this time |
jti |
JWT ID | Unique token identifier |
Security Note
Decoding ≠ Verifying. Anyone can decode a JWT payload — it's just Base64. The signature verification (checking the JWT hasn't been tampered with) requires the secret key and should only happen server-side.
Never trust decoded payload data without server-side signature verification.
For quick debugging, the JWT Decoder at DevKits is 100% client-side and works safely with real tokens.
Top comments (0)