How to decode a JSON Web Token?
Decoding a JWT takes a single paste — there is nothing to configure:
- Copy the token from your browser dev tools, an API response, or your application logs. You can paste it with or without the leading 'Bearer ' prefix.
- Paste it into the input box. The token is decoded automatically as you type — no button to press.
- The header (algorithm and token type) and the payload (the claims) appear side by side as formatted, highlighted JSON.
- The signature part is shown separately, exactly as it appears in the token. It stays base64url-encoded because signatures are binary data, not text.
How to check if a token is expired?
The tool reads the registered time claims for you:
- The status line under the output tells you whether the token is valid, expired, or not yet active, and how long is left.
- The 'Registered Claims' panel converts 'exp', 'iat' and 'nbf' from Unix timestamps into readable UTC dates with a relative time.
- Tokens without an 'exp' claim are reported as having no expiry — a red flag for production tokens.
Reading the decoded output
Each section maps to a part of the token:
- Header — usually contains 'alg' (HS256, RS256, ES256...) and 'typ'. Optionally 'kid' tells the server which key to verify with.
- Payload — your claims: standard ones like iss, sub, aud, exp, nbf, iat, jti plus any custom application claims.
- Signature — produced by signing 'header.payload' with a secret key (HMAC) or private key (RSA/ECDSA). It is not encrypted and not readable as text.
What is a JSON Web Token?
A JSON Web Token (JWT, RFC 7519) is a compact, URL-safe way to represent claims securely between two parties. A JWT is a string made of three base64url-encoded parts separated by dots. The first part is the header, which describes how the token is signed. The second is the payload, a JSON object holding the claims — statements about the user, the issuer, expiry, and permissions. The third is the signature, computed over the first two parts with a secret or private key. A key property: JWTs are signed, not encrypted. Anyone holding the token can read the header and payload with no key at all, which is exactly why decoders like this one work. The signature only guarantees integrity and authenticity — that the content came from the issuer and has not been altered. This means you should never put sensitive data such as passwords, credit card numbers, national IDs, or internal secrets inside a JWT payload, because every recipient and every proxy that touches the token can read it.
Registered claims and what they mean
The JWT specification defines a set of optional but conventional claims that servers and libraries understand automatically. 'iss' (issuer) identifies the party that created the token, typically your auth server URL. 'sub' (subject) identifies the principal the token is about — usually a user ID. 'aud' (audience) states who the token is intended for, and a compliant API must reject a token whose audience does not match it. 'exp' (expiration time) is a Unix timestamp after which the token must be rejected. 'nbf' (not before) is the earliest moment the token may be accepted, useful for tokens issued slightly ahead of time. 'iat' (issued at) records when the token was created and lets you enforce maximum session ages. 'jti' (JWT ID) is a unique identifier used to prevent replay attacks by blacklisting a token once it has been used. All time claims are expressed as NumericDate values — seconds since the Unix epoch, UTC — not milliseconds, which is a very common implementation mistake, since JavaScript's Date.now() returns milliseconds.
JWT vs opaque session tokens
Traditional session authentication stores a random opaque session ID in a cookie and keeps the session state in a database or Redis. Every request requires a lookup. A JWT takes the opposite approach: all necessary state travels inside the token, so any service holding the verification key can validate a request without a database round trip. This statelessness is what makes JWTs popular for microservices, mobile apps, and cross-domain APIs. The trade-off is revocation. Because a JWT is self-contained and valid until it expires, you cannot invalidate it centrally without extra machinery such as short lifetimes plus refresh tokens, a jti blacklist, or rotating signing keys. The practical pattern is a short-lived access token (5–15 minutes) sent in the Authorization header and a long-lived refresh token stored in an HttpOnly, Secure, SameSite cookie. Decoding a token client-side helps you debug exactly those lifetimes when authentication mysteriously starts failing.
Common JWT mistakes to avoid
The 'alg: none' attack: an early generation of JWT libraries accepted unsigned tokens when the header declared 'alg: none', letting an attacker forge any payload. Always whitelist the algorithms you accept on the server instead of trusting the header. Confusing decoding with verification: this tool decodes — it proves nothing about authenticity. Never treat a decoded payload as trusted on the server; only a signature check performed with your key does that. Mixing up signing algorithms: HS256 uses one shared secret for both signing and verifying, so if an API that normally expects RS256 public keys accepts HS256, an attacker can sign tokens using the public key as an HMAC secret. Clock skew: tokens rejected as 'not yet valid' are often simply issued by a server a few seconds ahead, so allow 30–60 seconds of leeway. Oversized payloads: JWTs are sent with every request, so keep claims minimal — a large payload bloats every API call. And finally, storing tokens in localStorage: any XSS on the page can read it, so prefer HttpOnly cookies where the architecture allows.
Frequently Asked Questions (FAQs)
Is it safe to paste my JWT into this decoder?
Yes — decoding happens entirely in your browser with JavaScript and your token is never sent to any server, logged, or stored. That said, treat any real production token as a secret: a JWT is a bearer credential and anyone who holds it can use it until it expires. If you decode a live token on a shared or compromised machine, consider it exposed. For demos, use the Sample Token button instead of a real one.
Does this tool verify the JWT signature?
No. This is a decoder, not a verifier. Decoding only base64url-decodes the header and payload, which requires no key at all. Verifying a signature requires the issuer's secret (HS256) or public key (RS256/ES256), and it proves the token was not tampered with. A successfully decoded token tells you nothing about authenticity — always verify server-side before trusting any claim.
Why can I read the payload if the token is supposed to be secure?
Because JWTs are signed, not encrypted. The signature guarantees integrity and authenticity, but the content is deliberately readable by anyone. JWE (JSON Web Encryption, RFC 7516) is the encrypted counterpart, producing a five-part token that cannot be read without a key. If your payload contains data that must stay confidential, use JWE or keep that data server-side and reference it by ID.
What does 'This token has no expiry claim (exp)' mean?
It means the payload has no 'exp' property, so the token never expires on its own and stays valid until the signing key is rotated or the server decides to reject it. Some libraries accept such tokens indefinitely. For production systems this is a security concern — it makes revocation impossible. Best practice is to always include a short 'exp' on access tokens and to refresh them with a dedicated refresh token.
Why does the time look wrong when I decode exp or iat?
JWT time claims are NumericDate values measured in seconds since the Unix epoch in UTC, while JavaScript and many languages report milliseconds. A claim of 1757836800 is 2026-09-14T08:00:00Z. If you compare it directly against Date.now() without multiplying by 1000, every token will look expired. This tool converts both to a readable UTC date and a relative description such as 'expires in 42 minutes' to remove that ambiguity.
Which algorithms and token formats are supported?
All of them, because decoding is algorithm-independent. Whether the token is HS256, HS384, HS512, RS256, PS512, ES256, EdDSA or anything else, the header and payload are always base64url-encoded JSON. The tool also handles tokens with a 'Bearer ' prefix, extra whitespace, and missing base64url padding. Only the signature, which is binary, is shown as-is rather than interpreted.
Can I use this offline?
Yes. Once the page has loaded, the decoder works without a network connection because every operation uses built-in browser APIs (atob, TextDecoder and JSON.parse). You can also save it to your bookmarks and use it on a machine with no internet access at all.