JWT Decoder
- Paste a JWT (the whole eyJhbGciOi... string) into the input box.
- The header and payload are decoded and displayed as JSON automatically.
- Check the Claims summary panel for exp / iat / iss / aud / sub with human-readable dates.
- To verify the signature, enter the shared secret (HS256/HS512) or PEM public key (RS256) and click Verify.
Help
FAQ
Is a JWT encrypted?ShowHide
Does decoding a JWT validate it?ShowHide
What is the difference between HS256 and RS256?ShowHide
Can a JWT be revoked or invalidated before exp?ShowHide
Where should I store JWTs in the browser?ShowHide
Why does my token have exp but still gets rejected?ShowHide
How to use this JWT decoder
- Paste a JWT (the whole eyJhbGciOi... string) into the input box.
- The header and payload are decoded and displayed as JSON automatically.
- Check the Claims summary panel for exp / iat / iss / aud / sub with human-readable dates.
- To verify the signature, enter the shared secret (HS256/HS512) or PEM public key (RS256) and click Verify.
Privacy Notice
Full guide
What is a JWT?
A JSON Web Token (JWT) is an open standard (RFC 7519) for representing claims between two parties as a compact, URL-safe string. It is the most common way to carry identity and authorization state in stateless APIs: the server issues a signed token, and every subsequent request presents it instead of a session cookie lookup.
A JWT is not encryption. It is a carrier for JSON claims with an integrity mechanism. The JWT standard actually defines two distinct things people constantly conflate:
- JWS (JSON Web Signature) - signed but readable by anyone. This is what 99% of "JWTs" in the wild are, and what this tool decodes.
- JWE (JSON Web Encryption) - actually encrypted. You can tell one apart instantly: a JWE has five dot-separated parts (
header.encryptedKey.iv.ciphertext.tag), a JWS has three (header.payload.signature).
Anatomy: header.payload.signature
A JWT is three Base64URL-encoded segments joined by dots:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUiLCJpYXQiOjE3MDAwMDAwMDAsImV4cCI6MTcwMDA4NjQwMH0
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Decoding the first two segments gives the JSON you see in the tool output:
Header - metadata about the token:
{ "alg": "HS256", "typ": "JWT" }
Payload - the claims. Note there is nothing secret here; anyone with the token can read it with two lines of JavaScript, exactly like this tool does.
Signature - the proof. For HS256 it is HMAC-SHA256(base64url(header) + "." + base64url(payload), secret). Change a single character of the payload and the signature no longer matches.
The encoding is Base64URL, not standard Base64: + becomes -, / becomes _, and padding = is dropped. That is what makes the token safe to put in URLs, HTTP headers, and query strings without encoding surprises.
Signature algorithms: HS vs RS vs ES
The alg header decides how the signature is produced and who can verify it.
| Algorithm | Type | Key model | Typical use |
|---|---|---|---|
| HS256 / HS384 / HS512 | HMAC + SHA-2 | One shared secret signs and verifies | Monolith, single service issuing and verifying |
| RS256 / RS384 / RS512 | RSA PKCS#1 v1.5 | Private key signs, public key verifies | Microservices, third-party verifiers, OIDC |
| ES256 / ES384 | ECDSA (P-256/P-384) | Same asymmetric model, smaller keys and signatures | Modern APIs, mobile, constrained environments |
| PS256 | RSA-PSS | Asymmetric, probabilistic padding | Required by some government / FAPI profiles |
none | No signature | — | Should be rejected. Historically the source of the alg=none attack |
The rule of thumb: if the party verifying the token should not be able to create tokens, you need an asymmetric algorithm. With HS256, every service that can validate a token can also forge one - a compromised microservice becomes a token mint.
This tool verifies HS256/HS512 with a shared secret and RS256 with a PEM public key, using the browser's Web Crypto API.
Registered claims you should actually use
The payload can hold anything, but RFC 7519 reserves these keys:
| Claim | Meaning | Notes |
|---|---|---|
iss | Issuer | Who created the token, e.g. https://auth.example.com |
sub | Subject | Who the token is about - usually the user ID |
aud | Audience | Who the token is for. APIs must reject tokens whose aud does not match them |
exp | Expiration | Unix seconds. Verification libraries enforce this - plain decoding never will |
nbf | Not Before | Token is invalid earlier than this timestamp |
iat | Issued At | When the token was created |
jti | JWT ID | Unique ID, used for one-time tokens or denylist entries |
The tool's Claims panel renders exp, iat, and nbf as human-readable dates so you can spot a stale or not-yet-valid token at a glance.
Security pitfalls that still bite teams in 2026
1. Trusting a decoded token. Decoding is not validation. Attackers craft beautiful payloads all day; only the signature check proves authenticity, and only your own exp/aud/iss checks prove fitness for your API.
2. The algorithm-confusion attack. Classic CVE bait: a server accepts tokens and verifies whatever alg the header claims. Attacker takes an RS256 token, changes the header to HS256, signs with the public key (which the server happily treats as the HMAC secret). Always pin the expected algorithm server-side, like this tool does with algorithms: [alg].
3. Weak HMAC secrets. HS256 with a dictionary-word secret falls to offline brute force in minutes, because an attacker with one valid token can test candidate secrets without touching your server. Use at least 256 bits of randomness (openssl rand -base64 32).
4. Putting sensitive data in the payload. It is Base64, not encryption. PII, internal IDs, and permission details in the payload leak to every place the token travels - including browser dev tools, logs, and proxies.
5. Long-lived tokens with no revocation. A stolen JWT is valid until exp. Best practice: short access tokens (5-15 minutes) plus refresh tokens stored server-side, and a jti denylist if you need instant revocation.
6. Storage in localStorage. Any XSS on your origin reads every token in localStorage. HttpOnly cookies keep tokens out of JavaScript's reach entirely; pair with SameSite and CSRF tokens.
JWT vs opaque session tokens
| JWT | Opaque session ID + store | |
|---|---|---|
| Verification | Local crypto, no DB hit | Server-side lookup every request |
| Revocation | Hard (denylist / short exp) | Trivial (delete the row) |
| Size | Larger (hundreds of bytes +) | Tiny |
| Cross-service | Excellent - any service with the public key | Requires shared session store or gateway |
Use JWTs where many independent services must verify identity without a round trip; use server sessions when revocation and simplicity matter more.
How this tool processes your token
Everything runs in your browser: the segments are split and Base64URL-decoded with the standard alphabet translation, JSON is parsed and rendered, and signature verification calls Web Crypto (crypto.subtle) directly. No network request carries your token or secret - which is also why it is safe to debug real credentials from staging here.