JWT Decoder – Decode and Inspect JWT Tokens Online
Decode any JSON Web Token instantly. Inspect header algorithm, all payload claims with descriptions, expiry status, and signature info. No secret key required. Runs entirely in your browser.
Decoding a JWT is base64url plus JSON.parse. Verifying one is a different problem entirely
A JSON Web Token is three base64url segments joined by dots: header, payload, and signature. Reading the first two segments requires no cryptography at all, just a correct base64url decoder and a JSON parse. This tool does exactly that, then adds expiry analysis and plain English descriptions for the standard claims defined in RFC 7519.
The token you paste is decoded entirely in your browser using atob and JSON.parse. There is no network call anywhere in the script, so the token, and anything sensitive it might contain, is never transmitted anywhere.
Base64url is not quite base64
JWT segments use base64url encoding, a variant defined in RFC 4648 section 5 specifically to be safe inside URLs. It replaces the two characters standard base64 uses that are not URL-safe, plus with hyphen and slash with underscore, and it drops the trailing = padding entirely. The browser’s built-in atob function only understands standard base64, so every decode has to reverse both changes first.
alg: "none" header. Anything other than two or three parts is rejected outright as malformed.
atob expects the string length to be a multiple of four. The decoder checks the remainder when dividing the length by four and appends one or two = characters to correct it.
atob alone returns a byte string, not proper Unicode text, so the result is passed through decodeURIComponent(escape(...)) to correctly reconstruct multi-byte UTF-8 characters like accented names or emoji before JSON.parse runs.
Expiry, issued-at, and not-before are checked against your local clock
The three standard time claims, exp, iat, and nbf, are Unix timestamps measured in seconds. The tool compares exp against Math.floor(Date.now() / 1000) to render a valid or expired badge, and computes a relative time string like “expires in 42 minutes” or “expired 3 days ago” by stepping through second, minute, hour, and day thresholds.
| Claim | Meaning per RFC 7519 |
|---|---|
| iss | Issuer, the principal that issued the token |
| sub | Subject, the entity the token is about |
| aud | Audience, the intended recipients |
| exp | Expiration time, a Unix timestamp after which the token must be rejected |
| nbf | Not before, a Unix timestamp before which the token must not be accepted |
| iat | Issued at, when the token was created |
| jti | JWT ID, a unique identifier that can be used to prevent replay |
The tool also recognizes about twenty nonstandard but widely used OpenID Connect claims such as email, given_name, roles, and scope, attaching a short description to each so you do not have to look up what a claim means while debugging an authentication flow.
Two things the tool flags automatically
Algorithm in the header
The alg field, typically HS256, RS256, or ES256, is pulled straight from the header and displayed as a badge, since it tells you immediately what kind of key would be needed to verify the token.
Missing exp claim
If a token has no exp claim at all, the tool shows a distinct “no expiry” badge rather than treating it as valid or invalid, since a token without an expiration is a legitimate but notable configuration worth flagging on its own.
Token specifications and libraries
- RFC 7519, JSON Web Token is the specification defining the token structure and the standard claim names this tool decodes.
- RFC 4648 section 5 defines base64url encoding, the URL-safe variant used in every JWT segment.
- RFC 7515, JSON Web Signature defines how the signature segment is actually computed and verified server side.
- OpenID Connect Core, standard claims is the source for the extended claim glossary this tool includes.
- jwt.io is the widely used reference decoder from Auth0, useful for cross-checking output on a tricky token.
Debugging jobs this handles
Debugging why an API call returns a 401 by checking whether the access token has actually expired, inspecting what claims an identity provider is actually putting into a token during OAuth integration work, confirming a token’s audience and issuer match what your service expects, and reading a session token pulled from browser storage during a support investigation.
Questions About the JWT Decoder
No, and that is intentional. JWT signature verification requires the secret key (for HS256/HS384/HS512) or the public key (for RS256/ES256 and other asymmetric algorithms). This tool decodes the header and payload — which are Base64url-encoded, not encrypted — so you can inspect the claims. To verify a token, use your server-side library: jsonwebtoken in Node.js, PyJWT in Python, or java-jwt in Java.
The decoding runs entirely in your browser — your token is never sent to a server. That said, production JWTs containing active user sessions should be treated as sensitive credentials. For real tokens with live expiry, be cautious about pasting them anywhere. Use the “Load Example” button if you just want to explore the tool without using a real token.
The decoder reads the algorithm from the header (alg claim) and displays it, but the algorithm does not affect decoding of the header and payload — only signature verification depends on it. The tool works with any JWT regardless of algorithm: HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, and so on. It also handles “none” algorithm (unsigned) tokens.
RFC 7519 defines registered claims: sub (subject, usually the user ID), iss (issuer, usually your auth server URL), aud (audience, the intended recipient), exp (expiration time), iat (issued at), nbf (not before), and jti (a unique ID for the token). Beyond these, OIDC adds claims like email, name, given_name, picture, and locale. Custom claims like roles, scope, and permissions are application-specific and vary by implementation.
The exp claim is a Unix timestamp (seconds since January 1, 1970 UTC). If the server that issued the token has a clock skew relative to your local machine, or the token has a very short TTL (common in test environments), the token may appear expired even if it was just issued. Also check that you are reading the right token — many auth flows issue both an access token (short-lived) and a refresh token (long-lived) and these are easy to mix up.
A traditional session cookie contains only an opaque session ID — the server looks up the session data in a database on each request. A JWT is self-contained: all claims are embedded in the token itself, so the server only needs the key to verify the signature, with no database lookup required. JWTs are stateless and scale well horizontally, but cannot be invalidated before they expire without extra infrastructure (a blocklist). Session cookies are stateful but trivially revocable.
No. A JWE (JSON Web Encryption) token has five parts separated by dots and the payload is actually encrypted, not just encoded. Decoding it requires the private key or shared symmetric key used for encryption. This tool only handles standard JWTs (JWS — JSON Web Signature), which have three parts and an encoded (not encrypted) payload. If you paste a five-part token, the tool will report a format error.
As this tool demonstrates, decoding a JWT payload requires no key at all — it is just Base64url encoding, which anyone can reverse. The signature only proves the token was issued by a specific party and has not been tampered with; it does not hide the payload content. Passwords, personal identification numbers, full credit card numbers, and other highly sensitive data should never appear in a JWT payload because any party who receives the token can read the claims. Store such data server-side and reference it by a safe identifier.
From the blog
Deep dives on the things these tools touch
Minification, UUID collisions, diffing API responses, and the other questions that come up around this toolset.