Decode JWT header, payload, and signature — fully client-side, never transmitted
Token structure
Header
Payload
Signature (raw base64url — not verified)
Standard claims
| Claim | Raw value | Decoded |
|---|
This token is decoded locally — it is never sent to any server. The signature is displayed but not cryptographically verified. Do not rely on this tool for security decisions.
The JWT Decoder takes a JSON Web Token and instantly decodes all three parts: the header (algorithm, token type), the payload (claims, expiry, subject, issuer), and the signature segment. Timestamp claims (iat, exp, nbf) are shown as human-readable dates with a live expiry countdown. Everything runs in the browser using native APIs — the token is never transmitted anywhere.
It’s the fastest way to inspect a JWT when debugging auth middleware, checking token expiry, or verifying the claims your backend is encoding without setting up a full auth test harness.
xxxxx.yyyyy.zzzzz.alg) and token type (typ).iat, exp, and nbf converted to human-readable datetime strings.A JWT consists of three base64url-encoded segments separated by dots: header.payload.signature.
Decoding process:
. — any token with more or fewer than two dots is structurally invalid.- with + and _ with /, then pad with = to the next multiple of 4.atob() — a native browser function available in all modern browsers, no library needed.Why base64url instead of standard base64? Standard base64 uses + and / as characters, which have special meaning in URLs (+ = space, / = path separator). JWTs are frequently embedded in URLs (query strings, Authorization headers). Base64url substitutes - for + and _ for /, making the token URL-safe without percent-encoding.
JWT claims reference:
| Claim | Meaning |
|---|---|
iss | Issuer — who created the token (e.g., https://auth.example.com) |
sub | Subject — who the token represents (usually a user ID) |
aud | Audience — intended recipient(s) of the token |
exp | Expiry — Unix timestamp; shown as local date + countdown |
nbf | Not Before — token is invalid before this time |
iat | Issued At — when the token was created |
jti | JWT ID — unique identifier for this specific token |
Signature segment: the third part of the JWT is the signature — an HMAC or RSA/ECDSA signature over the first two segments. This tool displays the raw base64url value but does not verify the signature. Verification requires the server’s secret key (HMAC) or public key (RSA/ECDSA), which you would supply yourself. Decoding and verification are independent operations.
JWT debugging comes up constantly in auth middleware development: a request is failing with 401, the token claims look right in the code that generates them, but something downstream is rejecting it. The fastest diagnosis path is to grab the raw token from the Authorization header and decode it to check what’s actually being sent.
The exp claim is the most common culprit. Tokens with 15-minute expiry windows fail in production systems where clocks between services drift more than expected, or where a cached token isn’t refreshed in time. The live expiry countdown here shows exactly how much time a specific token has left — or how long ago it expired.
The signature MUST be verified server-side. This tool only decodes the payload — it does not verify that the signature is valid. A JWT with a manipulated payload but a broken signature is structurally decodable here but will (correctly) fail verification on any properly implemented server. Never trust a decoded JWT payload client-side without server-side signature verification. The payload is base64-encoded, not encrypted or signed from the client’s perspective — anyone with the token can read the claims.
JWTs are not secret by default. They’re signed, not encrypted. Unless you’re using JWE (JSON Web Encryption, 5 segments), anyone who intercepts the token can read all the claims in the payload. This is why JWTs should not contain sensitive information like SSNs, full credit card numbers, or passwords — only identifiers and non-sensitive metadata.
Auth debugging workflow: when an API call returns 401 and the client is sending a Bearer token, copy the token from the Authorization header (visible in browser DevTools > Network > request headers), paste it here, and immediately see: is the token expired? Does the aud claim match what the server expects? Does the sub match the expected user? This answers 80% of JWT auth debugging questions without touching server logs.
exp before filing a bug report. If the token is expired, that’s the issue — not a server bug. The expiry countdown makes this unambiguous.iat and exp to verify token lifetime. If exp - iat = 900 seconds (15 minutes) and you expected 24 hours, the token generation code has a configuration error.aud claim mismatch is the second most common 401 cause after expiry. If your server expects aud: api.example.com and the token contains aud: auth.example.com, the server will correctly reject it. Decoding reveals this immediately.exp value you’re looking at in code before it exists as a full token.gekro.com before pasting sensitive tokens.Never paste tokens from production systems into third-party web tools. This decoder runs entirely in your browser — the token is never sent anywhere — but the best practice is still to use a local tool. If you are pasting a token here, verify that the URL bar shows gekro.com and not a lookalike domain.
For informational purposes only. Not financial, medical, or legal advice. You are solely responsible for how you use these tools.