JWT Decoder
Paste a JWT below. Decoding happens entirely in your browser — nothing is transmitted.
What Is a JWT and Why Would You Ever Need to Decode One?
If you've spent time building or consuming REST APIs, you've almost certainly bumped into a string that starts with eyJ and goes on for a suspiciously long time. That's a JSON Web Token — a compact, self-contained way to represent claims between two parties. Understanding what's actually inside one is an everyday task for backend developers, security engineers, and anyone debugging authentication flows.
How Is a JWT Structured?
A JWT is three Base64URL-encoded chunks separated by dots: header.payload.signature. The header carries metadata — which signing algorithm was used (HS256, RS256, ES256, and so on) and the token type. The payload is where the interesting stuff lives: user identity, roles, permissions, expiry timestamps. The signature is a cryptographic proof that the first two parts haven't been tampered with — but you need the original secret or public key to verify it.
The encoding is Base64URL, not standard Base64. The difference is subtle — + becomes - and / becomes _, with no padding characters — but it matters when you're decoding manually.
What Claims Are Actually Useful to Inspect?
The IETF specification (RFC 7519) defines a set of "registered" claim names that have agreed-upon meanings. Among the most practically important:
- exp (Expiration Time) — a Unix timestamp. If the current time is past this, the token is expired and should be rejected by any compliant server.
- iat (Issued At) — when the token was minted. Useful for understanding token age and for replay-attack analysis.
- nbf (Not Before) — the token isn't valid until this time. Rarely used but worth checking if you're seeing unexpected authorization failures shortly after a token is created.
- sub (Subject) — typically a user ID or account identifier.
- iss (Issuer) — the authority that generated the token. In multi-tenant or federated systems, this tells you which identity provider signed it.
- aud (Audience) — which service or resource the token is meant for. A token issued for your mobile API should be rejected by your admin panel if audiences are validated properly.
Beyond these registered claims, applications commonly add their own: roles, scopes, organization IDs, plan tiers, feature flags. These "private" or "public" claims are just regular JSON keys — there's no enforcement on their names or structure.
Can You Decode a JWT Without the Secret Key?
Yes, absolutely. The header and payload are only encoded, not encrypted. Anyone who holds the token string can read its contents. This is by design — the information is meant to be readable, just not forgeable. The signature is what prevents someone from modifying the payload and crafting a fake token.
This is an important distinction that trips up newcomers: a JWT is not a privacy mechanism. If you need the payload to be confidential, you'd use a JWE (JSON Web Encryption) instead. Plain JWTs only guarantee integrity and authenticity, not secrecy. So if your payload contains sensitive personal data, that's a design problem regardless of how strong the signing algorithm is.
What's the Difference Between HS256 and RS256?
The algorithm in the header determines how the signature works. HS256 (HMAC-SHA256) uses a shared secret — both the token issuer and every service that validates tokens need to know the same secret key. It's simple but requires secure key distribution.
RS256 (RSA-SHA256) uses a private/public key pair. The issuer signs with the private key; validators only need the public key. This is far more suitable for distributed systems because you can publish your public key openly (via a JWKS endpoint, typically at /.well-known/jwks.json) and any service can verify tokens without knowing the signing secret. ES256 works similarly but uses elliptic curve cryptography — smaller keys, faster operations.
When inspecting a JWT, the algorithm field matters because it tells you what kind of key you'd need to actually verify the signature. For debugging purposes though, you're usually just trying to read the claims, not revalidate the signature.
Why Do Tokens Expire, and What Happens When They Do?
Token expiry is a security control, not a convenience feature. If a JWT gets stolen — intercepted in transit, leaked from a log file, grabbed from browser storage — the window of misuse is bounded by the expiry time. Short-lived tokens (5–15 minutes) are common in high-security contexts; longer-lived ones (hours or days) are used where the tradeoff between security and user friction tips the other way.
When a token is expired, a well-implemented API returns a 401 Unauthorized. The client then typically uses a refresh token — a longer-lived, server-side-tracked credential — to obtain a new JWT without forcing the user to log in again. The refresh token itself isn't a JWT; it's an opaque reference that the authorization server looks up in a database, which means it can be revoked.
The expiry timestamp in a JWT is a Unix epoch time — seconds since January 1, 1970 UTC. Converting that to a human-readable date immediately tells you whether the token is still live or long dead.
Common Debugging Scenarios Where JWT Decoding Saves Time
One frequent situation: a user reports they can't access a feature they should have. You decode their token, look at the roles or scopes claim, and discover the token was issued before a permission change took effect. The fix isn't in the code — they just need to log out and log back in to get a fresh token.
Another: a service-to-service API call keeps failing with 401. You decode the token being sent, check the aud claim, and realize it's set to the staging environment's audience while the call is going to production. Classic misconfiguration that's invisible without looking inside the token.
Expired tokens are the most common culprit in support tickets about "sudden" authentication failures. Decode, check exp, compare to the current time — often the investigation ends right there.
A Word on Client-Side Decoding and Security
Decoding a JWT in the browser is safe for inspection purposes — you're just reversing Base64URL encoding and parsing JSON. What you cannot do client-side is verify the signature without the secret or private key, and you should never trust a token based solely on its payload without proper server-side validation.
Never paste production tokens into online tools run by third parties you don't trust. A JWT often contains user identifiers, session context, and potentially sensitive claims. Even if the token is expired, the information inside it could be used for user enumeration or targeted attacks. Using a browser-side tool where the processing happens locally — nothing leaves your machine — is the right approach for development and debugging work.