How to Decode a JWT (JSON Web Token)
You've got a long string of gibberish that starts with eyJ and you need to know what's inside it. That's a JSON Web Token (JWT) — and the good news is you can read it in about five seconds, because a JWT isn't encrypted. It's just encoded.
Paste it into our free JWT Decoder and you'll instantly see the header and payload as readable JSON. Everything happens in your browser — the token is decoded locally with JavaScript and never uploaded to a server. That matters more than you might think, because a live JWT is a credential: anyone who has it can act as the user it belongs to. Pasting production tokens into a random website that processes them server-side is quietly handing over a key. A client-side decoder removes that risk entirely.
This guide covers how to decode a JWT online or in code, what each part of the token means, how to read the claims (including those cryptic exp timestamps), and the one thing every developer eventually learns the hard way: decoding a JWT is not the same as verifying it.
What Is a JWT, Exactly?
A JSON Web Token (defined in RFC 7519) is a compact way to pass claims between two parties — most commonly, between an authentication server and an API. It's the backbone of modern login sessions, OAuth flows, and API authentication.
Every JWT is three Base64URL-encoded segments joined by dots:
header.payload.signature
- Header — metadata about the token itself: the signing algorithm (
alg, e.g. HS256 or RS256) and the token type (typ). - Payload — the actual claims: who the token is about, who issued it, when it expires, and any custom data (roles, email, permissions).
- Signature — a cryptographic signature over the first two parts, created with a secret key (HMAC) or private key (RSA/ECDSA). This is what makes the token tamper-evident.
The header and payload are only encoded, not encrypted — Base64URL is a reversible text encoding, not a cipher (our Base64 guide explains the difference in depth). That's why any decoder can read them without knowing any secret. The signature is the only part that requires a key — and it's for verification, not for hiding data.
How to Decode a JWT Online (Fastest Method)
- Open the free FileNaut JWT Decoder — no signup, nothing to install.
- Paste your token into the input box. It should be the full three-part string, dots included.
- Click Decode.
- Read the results: the Header panel shows the algorithm and type; the Payload panel shows every claim as formatted JSON.
- Need the JSON elsewhere? Click Copy JSON to grab the decoded output, then paste it into our JSON Formatter if you want to reformat, minify, or validate it.
The whole process runs locally in your browser tab. Close the tab and nothing persists anywhere.
If you get an "Invalid JWT token" error, check three things: the token has exactly three dot-separated parts (an opaque session ID or an encrypted JWE token won't decode this way), you copied the whole string with no truncation, and there's no surrounding whitespace or a Bearer prefix pasted in with it.
Decoding Is NOT Verifying (The #1 JWT Misconception)
This is the part that trips up almost everyone at first: anyone can decode any JWT. No secret required. If decoding felt like "unlocking" the token, it wasn't — you just reversed a public text encoding.
What you can't do without the key is verify the token — confirm the signature is valid and the contents haven't been tampered with. That's the entire security model:
- Decoding answers: "what does this token claim?" — anyone can do it.
- Verifying answers: "is this claim genuine and untampered?" — only someone with the secret key (HS256) or the issuer's public key (RS256) can do it.
Two practical consequences follow. First, never trust a decoded payload on the server without verifying the signature — an attacker can craft a token claiming to be anyone; the signature check is what catches it. Second, never put secrets in a JWT payload — passwords, API keys, personal data. The payload is readable by anyone who ever sees the token, including everything between your server and the user's browser.
How to Read the Payload: Standard Claims
Most JWTs use a handful of standard "registered claims" with three-letter names. Here's the decoder ring:
| Claim | Meaning | Example |
|---|---|---|
iss | Issuer — who created the token | https://auth.example.com |
sub | Subject — who the token is about (usually the user ID) | user_82631 |
aud | Audience — who the token is intended for | api.example.com |
exp | Expiration time (Unix timestamp, seconds) | 1753380000 |
nbf | Not before — token invalid until this time | 1753376400 |
iat | Issued at — when the token was created | 1753376400 |
jti | JWT ID — unique identifier for this token | a1b2c3d4 |
The time claims (exp, nbf, iat) are Unix timestamps in seconds. To turn 1753380000 into a human date, use our Unix timestamp guide — the short version: it's seconds since January 1, 1970 UTC. If the exp value is in the past, the token is expired and any properly built API will reject it, no matter how valid the signature is.
Anything else in the payload — email, role, permissions, name — is a custom claim the issuing application added. Same rules apply: readable by anyone, trustworthy only after signature verification.
How to Decode a JWT in Code
For automated workflows, decoding is a one-liner in most languages. Remember JWTs use Base64URL (with - and _), not standard Base64 (with + and /) — the libraries below handle that for you:
# JavaScript (browser or Node) — decode only, no verification
JSON.parse(atob(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')))
# Node.js with verification (the right way on a server)
const jwt = require('jsonwebtoken');
jwt.verify(token, secret); // throws if invalid or expired
# Python — decode only
import jwt
jwt.decode(token, options={"verify_signature": False})
# Python — with verification
jwt.decode(token, secret, algorithms=["HS256"])
# Command line
echo "$TOKEN" | cut -d. -f2 | tr '_-' '/+' | base64 -d 2>/dev/null | python3 -m json.tool
The pattern to internalize: the decode-only versions are for inspection and debugging. The verify versions are for trusting. On a server, always verify.
Tips for Working with JWTs
- Debugging a 401? Decode the token first. Nine times out of ten the answer is right there: an expired
exp, a wrongaud, or a missing role claim. - Check the
algheader when integrating. Your verification code must expect the same algorithm the issuer uses — and should explicitly whitelist it. Accepting whatever the header claims (includingnone) is a classic vulnerability. - Keep tokens short-lived. A JWT can't practically be revoked before expiry, so a leaked long-lived token stays dangerous. Short
expplus refresh tokens is the standard pattern. - Treat every JWT like a password. Don't commit them to repos, paste them into chat tools, or log them. For inspection, use a client-side decoder like ours so the token never leaves your machine.
- Don't confuse JWT with encryption. If you need the payload hidden, you need JWE (encrypted tokens) or transport-level protection — a signed JWT (JWS) hides nothing. For integrity checks on arbitrary data, a hash plays a similar tamper-evidence role.
FAQs
header.payload.signature structure; (2) it's truncated — JWTs are long and easy to cut off mid-copy; (3) it's a JWE (encrypted JWT), which has five parts and genuinely cannot be read without the decryption key. Check that your string has exactly two dots and starts with something like eyJ.
**Q3: Can someone read my JWT if they intercept it?**
Yes — the header and payload of a standard signed JWT are readable by anyone who obtains the token. That's why JWTs must only travel over HTTPS, and why you should never store sensitive data (passwords, card numbers, private details) in the payload. The signature prevents modification, not reading.
**Q4: Can I edit a JWT after decoding it?**
You can edit the decoded JSON, but you can't produce a valid token from it without the signing key. The moment you change one character of the payload, the existing signature no longer matches, and any server that verifies signatures will reject the token. This is by design — it's the entire point of signing.
**Q5: How do I check if a JWT is expired?**
Decode it and look at the exp claim — a Unix timestamp in seconds. Compare it to the current time (in seconds since Jan 1, 1970 UTC). If exp is smaller than now, the token is expired. Our timestamp conversion guide shows quick ways to convert it to a readable date.
**Q6: What's the difference between a JWT and a session cookie?**
A traditional session cookie is an opaque reference — the server looks up the session data in its own store. A JWT is self-contained — the data travels inside the token, verified by signature instead of a database lookup. JWTs scale well across services (no shared session store needed) but are harder to revoke; sessions are easy to revoke but require server-side state. Neither is universally better.
**Q7: How do I verify a JWT signature?**
You need the key: the shared secret for HMAC algorithms (HS256) or the issuer's public key for asymmetric ones (RS256/ES256). Then use a proper library — jsonwebtoken in Node, PyJWT in Python, golang-jwt in Go — and pass the expected algorithm explicitly. Browser-based decoders (ours included) intentionally don't verify signatures; verification belongs in your backend code where the key lives.Ready to try it?
Use the tool right now — free, no signup, no upload.