Decode JWT
Decode JWT tokens instantly to inspect headers, payloads, and claims for authentication debugging. View decoded JSON without signature verification—perfect for troubleshooting "unauthorized" errors, expired tokens, and permission issues in OAuth/OpenID flows.
Why Use Decode JWT
JWT (JSON Web Token) decoding reveals the header and payload claims hidden inside Base64URL-encoded tokens. When authentication fails with cryptic "401 Unauthorized" or "403 Forbidden" errors, decoding the JWT shows exactly why: expired `exp` timestamp, wrong `aud` audience, missing `scope` claims, or incorrect `iss` issuer. This tool decodes JWTs locally in your browser without sending tokens to any server—essential for debugging production auth issues while maintaining security.
- Instant decoding: Paste JWT and see header + payload JSON immediately
- Claim inspection: View exp, iat, nbf, aud, iss, sub, scope, and custom claims
- Expiration checking: Automatically flags expired tokens with timestamp conversion
- Algorithm visibility: See which signing algorithm (HS256, RS256, ES256) was used
- Browser-safe: Zero server uploads—tokens never leave your device
Choose the Right Variant
- This page: JWT decoding for authentication debugging and claim inspection
- JWT Token Decoder: Alternative decoder interface with validation
- JWT Parser: Structured parsing with field-by-field breakdown
- JWT Decode Online: General JWT decoding tool
Step-by-Step Tutorial
- Copy JWT token from browser DevTools Network tab, API response, or localStorage
- Example JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE4MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c - Paste into decoder input field
- Decoded header shows:
{"alg":"HS256","typ":"JWT"} - Decoded payload shows:
{"sub":"1234567890","name":"John Doe","iat":1516239022,"exp":1816239022} - Check if exp (expiration) is in the future—if past, token is expired
- Verify aud, iss, and scope match your API's requirements
Real-World Use Case
A frontend developer's API calls suddenly return "401 Unauthorized" after working fine yesterday. The user can log in but every authenticated request fails. They open DevTools Network tab, copy the Authorization header JWT, and paste it into the decoder. The payload shows {"exp":1704067200,"aud":"api.old-domain.com","sub":"user123"}. The exp timestamp is from yesterday (token expired), and the aud audience is the old domain before migration. They discover the OAuth login flow is still configured with the old domain and 24-hour expiration. After updating to the new domain and extending token lifetime to 7 days, users stop getting logged out. Total debugging time: 5 minutes instead of hours examining server logs and auth middleware code.
Best Practices
- Decode JWTs before verifying signatures to see why validation might fail
- Check exp, nbf (not before), and iat (issued at) timestamps against current UTC time
- Verify aud (audience) matches your API's expected audience string
- Confirm iss (issuer) matches your auth provider (e.g., "https://accounts.google.com")
- Inspect scope or roles claims to debug permission denied errors
- Never paste production JWTs containing PII into shared tools—use local decoder only
- Remember: decoding is not verification—signature validation still required for security
Performance & Limits
- Decoding speed: Instant (< 5ms) for typical JWTs
- Token size: Handles JWTs up to 100 KB (very large tokens with many claims)
- Browser support: Works in all modern browsers with Base64 support
- Offline capability: Fully functional offline after page loads
- No rate limits: Decode unlimited tokens locally
Common Mistakes to Avoid
- Thinking decode = verify: Decoding shows claims but doesn't validate signatures—always verify tokens server-side
- Ignoring exp timestamps: Convert Unix timestamps to human dates to check expiration
- Pasting incomplete tokens: JWTs have 3 parts (header.payload.signature) separated by dots
- Confusing aud and iss: aud is who should accept the token, iss is who created it
- Sharing decoded sensitive claims: JWTs often contain PII, emails, or permissions—redact before sharing screenshots
- Using untrusted decoders: Never paste production tokens into random online tools—use local decoders only
Privacy and Data Handling
All JWT decoding happens locally in your browser using JavaScript's atob() function. Your tokens never leave your device and are never uploaded to any server. The decoder simply reverses Base64URL encoding to reveal JSON—no network requests are made. However, decoded JWTs may contain sensitive information: user IDs, emails, roles, permissions, or custom claims. Always use this tool in private browsing mode when decoding production tokens. Never paste tokens containing real user data into shared screenshots or documentation. For security audits with sensitive tokens, use offline tools or browser-based decoders like this one exclusively.
Frequently Asked Questions
What is the difference between decoding and verifying a JWT?
Decoding simply reverses Base64URL encoding to reveal the JSON header and payload without cryptographic validation. Verification checks the signature using the secret key or public key to ensure the token hasn't been tampered with and was issued by a trusted authority. Decoding is useful for debugging what's inside a token when authentication fails, but verification is mandatory for security before trusting token claims. An attacker can create a JWT with fake claims, which will decode perfectly but fail signature verification. Always decode for inspection during development, but verify signatures in production code before granting access. The workflow: decode to debug claims → fix issues → verify signature server-side before trusting the token.
Why do JWT timestamps use large integers instead of dates?
JWT timestamps (exp, iat, nbf) follow the NumericDate format defined in RFC 7519, which uses Unix timestamps—seconds since January 1, 1970 UTC. For example, 1704067200 represents midnight on January 1, 2024 UTC. This format is language-agnostic and avoids timezone confusion: all JWT implementations can compare timestamps as simple integer math without parsing complex date strings. To convert to human-readable dates, use online epoch converters or JavaScript: new Date(1704067200 * 1000).toISOString(). When debugging, check if exp is greater than the current Unix timestamp—if exp < Date.now()/1000, the token is expired. Many JWT decoders automatically convert timestamps to readable dates for convenience.
What should I check first when JWT authentication fails?
Start by decoding the JWT and checking exp (expiration), nbf (not before), and aud (audience) claims. Most auth failures are caused by: (1) Expired tokens where current time > exp timestamp, (2) Tokens used before nbf timestamp (future-dated tokens), (3) Wrong aud audience (token for api-dev.example.com used on api-prod.example.com), (4) Incorrect iss issuer (token from wrong auth provider), (5) Missing required scope or role claims for the endpoint. After confirming these registered claims, verify the algorithm in the header matches your server's expected algorithm (e.g., RS256). If all claims look correct, the issue is likely signature verification failure—check that keys match between issuer and validator. This triage workflow solves 90% of JWT auth issues in under 5 minutes.
Can I edit JWT claims after decoding?
You can edit the decoded JSON payload, re-encode it to Base64URL, and create a new JWT, but the signature will be invalid because you don't have the secret/private key to re-sign it. This is the security design of JWTs—tampering is detectable. Editing claims is useful for learning or testing: modify the exp timestamp to create an expired token for testing error handling, or change scope claims to test permission logic. However, production systems will reject these edited tokens during signature verification. If you need to modify claims legitimately, generate a new JWT from the auth provider with updated claims. Some debugging scenarios: decode → edit exp to simulate expiration → use modified token to test error messages → confirm app handles expired tokens correctly.