How to Decode JWT Tokens: Complete Guide for Developers
What is JWT Decoding and Why Do You Need It?
JWT (JSON Web Token) decoding is the process of extracting the payload data from a JWT without verifying its signature. This is useful when you need to quickly inspect token contents during development, debugging authentication issues, or understanding what data your API is receiving.
Who this guide is for:
- Developers debugging authentication flows
- Backend engineers inspecting API tokens
- Frontend developers working with JWT-based auth
- Anyone needing to quickly view JWT contents
Understanding JWT Structure
A JWT consists of three parts separated by dots (.):
header.payload.signature
- Header: Contains token type and signing algorithm
- Payload: Contains the claims (user data)
- Signature: Verifies the token hasn't been tampered with
Step-by-Step: How to Decode a JWT
Method 1: Using DevConverter (Fastest)
- Copy your JWT token
- Go to DevConverter JWT Decoder
- Paste your token
- View the decoded header and payload instantly
Method 2: Using JavaScript/Node.js
function decodeJWT(token) {
const parts = token.split(".")
if (parts.length !== 3) {
throw new Error("Invalid JWT format")
}
const header = JSON.parse(atob(parts[0]))
const payload = JSON.parse(atob(parts[1]))
return { header, payload }
}
// Example usage
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
const decoded = decodeJWT(token)
console.log(decoded.payload)Method 3: Using Python
import base64
import json
def decode_jwt(token):
parts = token.split('.')
if len(parts) != 3:
raise ValueError('Invalid JWT format')
# Add padding if needed
payload = parts[1]
payload += '=' * (4 - len(payload) % 4)
decoded = base64.urlsafe_b64decode(payload)
return json.loads(decoded)
# Example usage
token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
payload = decode_jwt(token)
print(payload)Common Mistakes to Avoid
1. Confusing Decoding with Verification
Mistake: Thinking decoded = verified
// ❌ WRONG - This doesn't verify the signature!
const decoded = decodeJWT(token)
if (decoded.payload.role === "admin") {
grantAccess() // SECURITY RISK!
}Correct approach:
// ✅ CORRECT - Always verify before trusting
const verified = jwt.verify(token, secretKey)
if (verified.role === "admin") {
grantAccess()
}2. Forgetting Base64 Padding
JWT uses base64url encoding which may need padding. Always add padding when decoding manually.
3. Exposing Sensitive Data in JWTs
Don't store:
- Passwords
- Credit card numbers
- Social security numbers
- Private keys
Do store:
- User ID
- Username
- Roles/permissions
- Expiration time
4. Not Checking Token Expiration
// ✅ Always check exp claim
const decoded = decodeJWT(token)
if (decoded.payload.exp < Date.now() / 1000) {
throw new Error("Token expired")
}Best Practices for Working with JWTs
1. Use HTTPS Only
Always transmit JWTs over HTTPS to prevent interception.
2. Set Short Expiration Times
// Good: 15 minutes for access tokens
const token = jwt.sign(payload, secret, { expiresIn: "15m" })3. Store Tokens Securely
- Frontend: Use httpOnly cookies (not localStorage)
- Backend: Never log tokens in production
4. Validate All Claims
const decoded = decodeJWT(token)
// Check issuer
if (decoded.payload.iss !== "your-auth-server.com") {
throw new Error("Invalid issuer")
}
// Check audience
if (decoded.payload.aud !== "your-app.com") {
throw new Error("Invalid audience")
}FAQ
Can I decode a JWT without the secret key?
Yes! Decoding only requires base64 decoding. The secret key is only needed for verification (checking if the token is valid and hasn't been tampered with).
Is it safe to decode JWTs in the browser?
Yes, decoding is safe because JWTs are not encrypted—they're just encoded. However, never trust decoded data without verification on the server.
What's the difference between decoding and verifying a JWT?
- Decoding: Extracting the payload (no security check)
- Verifying: Checking the signature to ensure the token is valid and unmodified
How do I decode a JWT in the command line?
# Using jq and base64
echo 'eyJhbGc...' | cut -d'.' -f2 | base64 -d | jqWhy does my decoded JWT look garbled?
Make sure you're:
- Using base64url decoding (not regular base64)
- Adding proper padding (=) if needed
- Decoding the payload part (second segment)
Can expired JWTs still be decoded?
Yes! Expiration only affects verification, not decoding. You can decode expired tokens to inspect their contents.
What should I do if my JWT has 4 or 5 parts?
Standard JWTs have 3 parts. If yours has more, it might be:
- A JWE (JSON Web Encryption) token
- A malformed token
- A custom token format
How can I decode JWTs in production safely?
Use established libraries:
- Node.js:
jsonwebtoken,jose - Python:
PyJWT - Java:
java-jwt - Go:
golang-jwt
Never roll your own JWT implementation in production.
What information is in the JWT header?
Typically:
alg: Signing algorithm (HS256, RS256, etc.)typ: Token type (usually "JWT")kid: Key ID (for key rotation)
How do I handle JWT decoding errors?
try {
const decoded = decodeJWT(token)
console.log(decoded)
} catch (error) {
if (error.message.includes("Invalid JWT format")) {
// Handle malformed token
} else {
// Handle other errors
}
}Quick Summary
- JWT decoding extracts payload data without verification
- Use DevConverter's JWT Decoder for instant, secure decoding
- Never trust decoded data without server-side verification
- Always check expiration and validate claims
- Use HTTPS and store tokens securely
Ready to decode your JWT? Try DevConverter's free JWT Decoder tool →
No installation, no sign-up, completely private—your tokens never leave your browser.