JWT Decoder

Decode a JSON Web Token to read its header, payload and claims, see whether it has expired, and optionally verify an HMAC signature. Nothing is sent to a server.

Helpful?
Expired 22 hours ago

Header

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload

{
  "sub": "1234567890",
  "name": "Ada Lovelace",
  "admin": true,
  "iat": 1756945600,
  "exp": 1788481600
}

Claims explained

ClaimValueMeaning
sub1234567890Subject, who or what the token is about
nameAda LovelaceCustom claim defined by the issuer
admintrueCustom claim defined by the issuer
iat1756945600
Thu, 04 Sep 2025 00:26:40 GMT
Issued at, when the token was created
exp1788481600
Fri, 04 Sep 2026 00:26:40 GMT
Expiration time, after which the token must be rejected

Verify HMAC signature

Works for HS256, HS384 and HS512. The secret stays in your browser.

JWT Decoder: Reading, Checking and Understanding JSON Web Tokens

How a JWT Is Put Together

A JSON Web Token is three chunks of base64url text joined by dots. The first is the header, a small JSON object naming the signing algorithm and the token type. The second is the payload, holding the claims. The third is the signature over the first two.

Base64url differs from ordinary base64 in three ways: plus becomes minus, slash becomes underscore, and trailing equals padding is dropped. That makes a token safe to put in a URL or an HTTP header without escaping, which is exactly where tokens live.

The encoding is reversible by anyone. It exists to make arbitrary JSON survive transport intact, not to hide it. Treat the payload as public text that happens to be tamper evident.

Tokens are compact because they travel on every request. Each claim you add costs bandwidth on all of them, which is a good reason to keep payloads lean rather than stuffing a user profile into one.

Registered Claims and What They Mean

Seven claim names are reserved by the specification. iss is the issuer, sub the subject the token describes, aud the intended audience, and jti a unique identifier useful for revocation lists.

Three are timestamps, all counted as seconds since 1 January 1970 in UTC. exp is when the token stops being valid, nbf when it starts, and iat when it was issued. The table above renders each of them as a readable date, because a bare ten digit number tells you nothing at a glance.

Everything else is a custom claim defined by whoever issued the token. Roles, permissions, tenant identifiers and email addresses are all common. The convention is to namespace them with a URI to avoid collisions with future registered names.

Checking aud matters more than people realise. A token issued for one service should be rejected by another, and services that skip this check can be attacked by replaying a legitimately obtained token somewhere it was never meant to go.

Signatures, Secrets and Public Keys

HMAC algorithms, named HS256, HS384 and HS512, use a single shared secret for both signing and verifying. They are simple and fast, and appropriate when the same party does both, such as a single application issuing its own session tokens.

RSA and ECDSA algorithms, named RS256, ES256 and similar, use a private key to sign and a public key to verify. This is what identity providers use, because it lets any number of services validate tokens without ever holding the key that could mint new ones.

This tool verifies HMAC only. Asymmetric verification would need the issuer public key, usually fetched from a JWKS endpoint, and matched by the kid value in the header.

An HMAC secret is a cryptographic key, not a password. Use at least 32 random bytes. Short or guessable secrets can be brute forced offline by anyone holding a single token.

Decoding Is Not Verifying

Decoding reads the payload. Verifying proves the payload has not been altered and came from someone holding the key. They are entirely different operations, and confusing them is the root of most JWT vulnerabilities.

Anyone can forge a token that decodes beautifully. Change admin from false to true, re-encode, and the payload reads exactly as an attacker wants. Only the signature check catches it.

The classic failure is the none algorithm. Early libraries accepted a token whose header claimed no signature was needed, so an attacker could strip the signature entirely. Always pin the expected algorithm server side rather than trusting the header.

A related trap is algorithm confusion, where a token signed with HMAC is presented to a service expecting RSA. If the service passes its public key as the HMAC secret, the check can succeed against a token an attacker forged using that public key.

Expiry, Clock Skew and Refresh

Keep access tokens short lived. Fifteen minutes to an hour is typical, because a JWT is hard to revoke once issued. Anyone holding a valid token has access until it expires, whether or not the account has since been disabled.

Refresh tokens solve the usability problem. They live longer, are stored more carefully, and can be revoked server side because they are checked against a database rather than validated purely from their own contents.

Allow a little clock skew. Server clocks drift, and a token that appears to expire seconds in the future on one machine may already be expired on another. A tolerance of thirty to sixty seconds avoids a class of intermittent authentication failures.

A token with no exp at all never expires by itself, which is almost always a mistake for anything granting access.

Security Mistakes Worth Avoiding

Putting secrets in the payload. It is readable by anyone who has the token, including the browser it is stored in. Passwords, card details and personal data have no place there.

Storing tokens in localStorage. Any injected script can read it. An httpOnly, secure, SameSite cookie is safer against cross site scripting, at the cost of needing CSRF protection.

Trusting the header. The algorithm, the key ID and everything else in the header is attacker controlled until the signature is verified. Decide server side which algorithm you accept.

Assuming a token can be cancelled. Unless you maintain a denylist of jti values, a stolen token stays valid until it expires. That is the price of stateless authentication.

Debugging Tokens in Practice

Check expiry first. The overwhelming majority of mysterious 401 responses are simply expired tokens. The status banner above answers that in a glance.

Then check the audience and issuer. A token that is perfectly valid for one environment will be rejected by another. Mixing staging and production credentials is a common cause.

Look for the claim your code expects. Roles and permissions land under different names depending on the identity provider, and a missing claim usually means the scope was not requested.

Prefer test tokens. This tool never transmits anything, but pasting live production credentials into any browser tab is a habit worth not forming. An expired token decodes exactly the same way.

Frequently Asked Questions

On production tokens: Nothing here is transmitted, but a live access token is a credential. Prefer an expired or test token when you only need to inspect the shape of a payload.

Check out our other tools

Browse all tools