JWT Decoder & Verifier
Paste a JSON Web Token to read its header and payload, see when it expires, and optionally verify the HMAC signature with your secret. Everything runs in your browser — the token is never uploaded. Last reviewed 2026-06-19.
— — —
What a JWT is
A JSON Web Token (JWT, pronounced “jot”) is a compact, URL-safe way to carry
claims between two parties — most often a sign-in token your app receives after a user
authenticates. It has three parts separated by dots:
header.payload.signature. The header and payload are JSON objects that are only
Base64URL-encoded, so they are readable by anyone — the signature is what proves
the token has not been changed and was issued by someone holding the key.
The three parts
- Header — the signing algorithm
(
alg, e.g. HS256 or RS256) and token type (typ). - Payload — the claims: who the token is about, who issued it, when it expires, and any custom data.
- Signature — a keyed hash of
header.payload. For HMAC it uses a shared secret; for RSA/ECDSA it uses the issuer’s private key and is checked with the matching public key.
Registered claims
| Claim | Name | Meaning |
|---|---|---|
iss | Issuer | Who issued the token (the authorization server / app). |
sub | Subject | Who the token is about — usually the user ID. |
aud | Audience | Who the token is intended for; the recipient must reject it if it is not the audience. |
exp | Expiration | Unix time after which the token must not be accepted. Decoded to a human time below. |
nbf | Not before | Unix time before which the token must not be accepted. |
iat | Issued at | Unix time the token was issued. |
jti | JWT ID | A unique identifier, used to prevent replay. |
Verifying the signature
Verification recomputes the signature over the first two segments and checks it matches the third.
This tool verifies the HMAC family (HS256, HS384,
HS512) when you provide the shared secret, using the browser’s native
crypto.subtle. Asymmetric tokens (RS256, ES256,
PS256) are decoded fully, but their signatures can only be verified with the
issuer’s public key (from its JWKS endpoint), so they are not checked here. A
decoded token is never proof of validity — always confirm exp, nbf,
aud and iss too.
Worked example
The classic RFC 7519
sample token below uses HS256 with the secret your-256-bit-secret. Its
header decodes to {"alg":"HS256","typ":"JWT"} and its payload to
{"sub":"1234567890","name":"John Doe","iat":1516239022} — that iat
is 23 January 2018. Click Load example above to decode and verify it instantly.
Where JWTs come from: the JOSE family
The JSON Web Token is defined by RFC 7519 (May 2015), one of a set of related standards collectively known as JOSE (JavaScript Object Signing and Encryption). The signature mechanism this tool checks comes from JWS (JSON Web Signature, RFC 7515); the list of permitted algorithms such as HS256 and RS256 comes from JWA (JSON Web Algorithms, RFC 7518); the format for publishing public keys comes from JWK (JSON Web Key, RFC 7517); and there is a separate standard, JWE (JSON Web Encryption, RFC 7516), for tokens whose contents are actually hidden. A plain JWT — the kind you receive after signing in to almost any modern web app — is a JWS: signed, but not encrypted.
Signed, not secret
The single most important thing to understand about a standard JWT is that it is signed, not encrypted. The header and payload are merely Base64URL-encoded — an encoding, not encryption — so anyone who holds the token can decode and read every claim inside it, exactly as this tool does, with no key at all. The signature does not hide the contents; it only proves two things: that the token has not been altered since it was issued, and that whoever issued it held the signing key. The rule that follows is absolute: never put anything in a JWT payload that the bearer should not be allowed to see — no passwords, no API keys, no sensitive personal data. If the contents truly must be confidential, you need JWE (encryption), not a plain signed JWT.
HMAC vs RSA/ECDSA: two ways to sign
JWS signatures come in two families. HMAC algorithms (HS256, HS384, HS512) are symmetric: a single shared secret both creates and verifies the signature. They are simple and fast and are ideal when the same party issues and checks the token. This tool can verify HMAC tokens directly, because if you hold the secret you have everything needed to recompute the signature in your browser.
RSA (RS256/384/512, PS256/…) and ECDSA (ES256/…) algorithms are asymmetric: the issuer signs with a private key it never shares, and anyone can verify with the matching public key. This is what large identity providers use, because thousands of independent services can validate a token without ever being trusted with the power to mint one. The public keys are published at a well-known JWKS (JSON Web Key Set) endpoint. This tool fully decodes asymmetric tokens but does not fetch remote keys, so it does not verify their signatures — that check belongs on your server, against the issuer's JWKS.
Why use a JWT at all? Stateless authentication
A traditional web session stores a random session ID in a cookie and keeps the real session data in
server memory or a database, so every request requires a lookup. A JWT inverts this: the user's identity
and permissions are written into the signed token itself. When a request arrives, the server
only has to verify the signature and read the claims — no database round-trip, no shared session store.
This statelessness is what makes JWTs popular for APIs, microservices and
horizontally-scaled systems, where any server in a fleet can validate a token on its own. The token is
normally sent on each request in an HTTP header as Authorization: Bearer <token>.
The flip side of statelessness is the revocation problem: because the server keeps no
record of issued tokens, it cannot easily "log someone out" before their token expires. The standard
mitigations are short expiry times, a server-side denylist of revoked token IDs (the jti
claim), or rotating the signing key — each of which reintroduces a little state in exchange for control.
The "alg: none" vulnerability
Early JWT libraries honoured a special algorithm value of none, which means the token is
unsigned. An attacker could take a valid token, change the payload (for example flip
"role":"user" to "role":"admin"), set the header algorithm to
none, delete the signature, and a naïve server would accept it. The defence is to
never accept none in production and to validate the algorithm against an
explicit allow-list rather than trusting the value in the token's own header. This tool flags any token
whose header declares alg: none as unsigned and forgeable.
The RS256-to-HS256 confusion attack
A subtler and famous flaw is the algorithm-confusion (or key-confusion) attack. A
server expects RS256 (asymmetric) and verifies tokens with the issuer's public key — which is,
by definition, public. If the verification code trusts the algorithm named in the token, an attacker can
change the header to HS256 and sign a forged token using that public key as though it were
an HMAC secret. A library that blindly switches to HMAC will then "verify" the forgery against the very
key the attacker used. The defence is the same as for alg: none: the server must
pin the expected algorithm and never let the token choose how it is checked.
Validate more than the signature
A valid signature only proves a token is authentic and unaltered — it does not prove the token should be
accepted right now. A correct verifier also checks the registered claims: exp (is
it expired?), nbf (is it being used too early?), aud (is this service the
intended audience?) and iss (did a trusted issuer mint it?). A token that is perfectly
signed but expired, or meant for a different audience, must be rejected. This is exactly why a server can
legitimately reject a token that this tool shows as having a valid HMAC signature.
Registered, public and private claims
RFC 7519 divides claims into three groups. Registered claims are the short,
standard names in the table above (iss, sub, aud,
exp, nbf, iat, jti) — none are mandatory, but using
them consistently keeps tokens interoperable. Public claims are names registered in the
IANA JSON Web Token registry or namespaced with a collision-resistant URI. Private claims
are the custom fields your own application agrees on — a role, a list of scopes,
a tenant ID. Keeping payloads small matters: the token travels on every request, so a bloated JWT becomes
a real bandwidth and header-size cost on each call.
Access tokens, refresh tokens and where to store them
Because a stolen access token grants access until it expires, good systems keep them short-lived — often
5 to 15 minutes — and pair them with a longer-lived refresh token that is used only to
obtain new access tokens and can be revoked centrally. Where you store a token in a browser is itself a
security decision. Keeping it in localStorage is convenient but exposes it to any
cross-site-scripting (XSS) bug on the page, which can read it. Keeping it in an HttpOnly
cookie hides it from JavaScript (mitigating XSS) but makes the request vulnerable to cross-site request
forgery (CSRF) unless you add the SameSite attribute or an anti-CSRF token. There is no
single right answer — only an informed trade-off for your threat model.
A JWT security checklist
- Pin the algorithm. Decide HS256 or RS256 in your code and reject anything else, including
none. - Use a strong HMAC secret. For HS256 the secret should be at least 256 bits (32 random bytes) of real entropy — a dictionary word is brute-forced offline in moments once an attacker has a token, because verification is local and unlimited.
- Keep payloads non-secret. Treat everything in a signed JWT as readable by the bearer.
- Set and check
exp. Short lifetimes limit the damage of a leaked token. - Validate
audandissso a token meant for another service or from another issuer cannot be replayed against you. - Verify asymmetric tokens against the issuer's JWKS public key (cached and refreshed) — never against a key embedded in the token.
- Have a revocation story — a
jtidenylist or key rotation — for the cases short expiry cannot cover.
Used this way, JWTs are a robust, well-understood building block. Most JWT incidents in the wild come not
from the cryptography but from skipped checks — accepting none, trusting the header's
algorithm, or using a guessable HMAC secret — every one of which is preventable.
What Base64URL encoding is
The dots in a JWT separate three Base64URL-encoded segments. Base64URL is a close cousin of
ordinary Base64 that is safe to drop into a URL: it replaces the + and / characters
with - and _, and it usually omits the = padding. That is the only
"transformation" applied to the header and payload — there is no compression and no encryption, which is why
this tool (and anyone else) can read them with nothing but the token. The signature segment is the Base64URL
encoding of the raw signature bytes, not text, which is why it looks like random characters rather
than readable JSON.
JWT vs opaque session tokens
A JWT is not the only kind of token. The classic alternative is an opaque token — a long random string that means nothing by itself and is simply a lookup key into a server-side store of session data. The trade-off is the mirror image of the JWT's: an opaque token reveals nothing if intercepted and can be revoked instantly (just delete the server record), but every request requires that lookup, so it is not stateless. A JWT needs no lookup and scales effortlessly across servers, but it is readable, larger, and awkward to revoke before expiry. Many systems use both — short-lived JWTs for fast API authorisation, backed by an opaque, revocable refresh token for renewing them — taking the strengths of each.
Frequently asked questions
- Is my token uploaded anywhere?
- No. Decoding and signature verification happen entirely in your browser using the built-in Web Crypto API. The token and the secret never leave your device and are never logged or transmitted — so it is safe to inspect tokens that would be risky to paste into a server-side tool. It also works offline once the page has loaded.
- Is a decoded JWT secret or encrypted?
- No. A standard JWT is signed, not encrypted — the header and payload are only Base64URL-encoded, so anyone holding the token can read them. The signature does not hide the contents; it only proves the token was not tampered with and was issued by someone who knows the key. Never put secrets you would not want a client to see inside a JWT payload.
- Which signatures can this tool verify?
- It verifies HMAC signatures — HS256, HS384 and HS512 — when you supply the shared secret, using the native Web Crypto API. Asymmetric algorithms (RS256, ES256, PS256, EdDSA) are still fully decoded, but their signatures are validated with the issuer’s public key, which only the issuer’s well-known endpoint has, so this tool does not verify them.
- What does "expired" mean here?
- If the payload has an exp (expiration) claim and that moment is in the past compared with your device clock, the token is shown as expired. Likewise a nbf (not-before) claim in the future is shown as not yet valid. These are read straight from the decoded claims; expiry checking is normally done by the server that receives the token.
- Why is the signature "valid" but the server still rejects my token?
- A valid signature only means the token was not altered and the key matches. The server may still reject it because it is expired (exp), used too early (nbf), has the wrong audience (aud) or issuer (iss), or was revoked. Check those claims in the decoded payload too.
Related tools
See all browser tools → · All developer & data conversions →