Skip to content

JWT Decoder Online Free

Decode a JWT into its header, payload, and signature with expiration status and human-readable timestamps.

In your browseryour files never leave your device.

Learn more
⌘K focus · Esc clear
Header
Algorithm and token type will appear here
Payload
Claims (sub, name, email, exp, iat…) will appear here
Signature
Signature will appear here

About this tool

A JSON Web Token (RFC 7519) is three Base64URL-encoded segments joined with dots: header.payload.signature. The first two are JSON objects you can read with any parser. The third is a cryptographic signature that proves the issuer minted the token and nothing was tampered with. This tool decodes the header and payload, shows the signature as opaque text, and — when you paste the shared secret — verifies HS256 signatures locally via the Web Crypto API (HMAC-SHA-256). RS256 and ES256 tokens are decode-only here because verifying them requires the issuer's public key from a JWKS endpoint, which is a server-side concern. Expiration, issued-at, and not-before claims convert from Unix epoch to readable dates so you can see at a glance whether the token is valid right now. A green or red expiration badge tells you the status before you read a single claim.

How to jwt decoder online free

  1. Paste the JWT

    The full string with the two dots. Example: eyJhbGciOiJIUzI1NiI...signature. The decoder splits on dots and decodes each segment from Base64URL (the URL-safe variant of Base64 that uses - and _ instead of + and /).

  2. Read the expiry badge

    A green pill means the token is still good; red means it has expired. The badge shows "Expires in 23m" or "Expired 4h ago" — readable, not raw epoch. If the token has no exp claim (some long-lived API keys minted as JWTs do not) the badge does not appear, which is itself information.

  3. Inspect header and payload

    Header shows alg and typ. Payload shows the claims — issuer (iss), subject (sub), audience (aud), expiration (exp), issued-at (iat), plus whatever custom data your auth system added (user_id, roles, scopes, tenant, plan). The pretty-printing makes nested structures scannable.

  4. Cross-check against the issuer

    Compare iss to what your IdP says it should be. Compare aud to your API identifier. If either is wrong, your token validation will fail server-side even if the signature is good. The decoder shows you the data; the server-side log usually tells you which check failed.

Why use this tool

JWTs are the standard auth credential for almost every modern API and almost every modern auth crash. Auth0, Cognito, Firebase Auth, Clerk, Supabase Auth — they all hand back JWTs, and when "401 Unauthorized" lands in your console the first question is "is this token even alive?". Pasting the token in here answers that in two seconds via the exp claim. The second case is debugging custom claims: I added a "roles" claim on my issuer side but the API is still rejecting the request. Did the claim actually make it into the token? Decode and see. The third case is verifying which algorithm the issuer is using — HS256 means there is a shared secret, RS256 means asymmetric with a public key, and the famous "alg: none" attack still shows up in CTFs and the occasional misconfigured library. The fourth is inspecting refresh tokens to confirm their longer lifetime is what you expected. The fifth is comparing two tokens minted by the same issuer to spot which claims differ between them — useful for debugging permission systems. This tool never sends the token anywhere, which matters because production tokens are bearer credentials.

Features

Three-panel decode with color coding

Header, payload, and signature each render in their own card with color coding (orange for header, green for payload, purple for signature). Easy to spot which part you are reading. The payload is the part you usually care about, since that holds the user identity, the issued-at and expiration timestamps, and any custom claims your auth system added. The header tells you the signing algorithm — HS256, RS256, ES256 — and the token type, which is almost always "JWT" but can be "JWT" with extensions for specific signed JWS variants.

Expiration status badge

A green or red pill at the top tells you "Expires in 23m" or "Expired 4h ago". No more squinting at the exp claim and doing epoch math in your head. Useful for the "is the token even valid" question that opens every JWT debug session. The badge also handles the nbf (not-before) claim if present — a token can be valid in the future, and the badge reflects that case as "Not valid until..." rather than just "Expired."

Pretty-printed JSON inside each segment

The header and payload are decoded from Base64URL, parsed as JSON, and rendered with 2-space indentation so the claims are readable. Standard claim names (iss, sub, aud, exp, iat, nbf, jti) and custom claims appear together. The pretty-printing means a nested permissions object or a claims dictionary is easy to scan rather than a single jumbled line. Each panel has a copy button so you can grab the decoded JSON for use elsewhere.

Local-only decoding — verifiable in DevTools

JWTs are bearer tokens — anyone with the string can impersonate the subject until it expires. Pasting one into a third-party site that POSTs the input to a server is a credential leak. This tool decodes in your browser via atob and JSON.parse with zero network calls. Verify in DevTools — open the Network tab, paste a token, and see no outbound requests. Compare to other "online JWT decoder" sites that POST the token to their servers (some of which have been caught logging tokens for analysis).

HS256 signature verification in the browser

Paste the shared secret and the tool recomputes the HMAC-SHA-256 over base64url(header) + "." + base64url(payload) via the Web Crypto API, then compares it byte-for-byte against the token's signature. A green "Signature is valid" confirms the token was minted by someone holding the secret and has not been tampered with. The secret never leaves the browser — verifiable in DevTools, no network calls. RS256 and ES256 are decode-only here; for those you fetch the issuer's public key from a JWKS endpoint and verify server-side, which is the standard production pattern anyway.

Privacy & security

Decoding the three Base64URL segments is a one-line operation in JavaScript, and that is what runs here — atob plus a small string transform for the URL-safe alphabet. If you paste the shared secret for HS256 verification, the HMAC-SHA-256 check runs through the Web Crypto API on your machine; the secret is never serialized anywhere except memory. Real JWTs often carry user IDs, scopes, and sometimes whole user objects in the payload — keeping that all client-side is the whole point.

Frequently asked questions

Does this verify the signature?
Yes for HS256 — paste the shared secret and the tool recomputes the HMAC-SHA-256 via the Web Crypto API and compares it constant-time against the token's signature. The secret stays in the browser, verifiable in DevTools (no network calls). RS256 and ES256 are decode-only here because verifying them requires the issuer's public key, which lives at the JWKS endpoint of your identity provider — fetching keys, picking the right one by kid, and validating the signature is a server-side workflow. If you need to verify an RS256/ES256 token, your backend's JWT library does it in two lines, or jwt.io will fetch the JWKS for you in a sandbox.
HS256 versus RS256 versus ES256 — what does the algorithm tell me?
HS256 is HMAC-SHA256, a symmetric algorithm where the same secret signs and verifies. Good for one service that mints tokens for itself. RS256 is RSA-SHA256, asymmetric — the issuer signs with a private key, anyone with the public key (typically distributed via a JWKS endpoint) can verify. Standard for OAuth and OpenID Connect providers like Auth0, Google, and Microsoft. ES256 is the same idea as RS256 but with elliptic-curve signatures, producing smaller and faster signatures. Common with Apple Sign In and newer providers; expect to see more of it over time as ECC becomes the default over RSA.
What is the "alg: none" attack?
JWT permits an "alg": "none" header that means "no signature required." If a server library accepts that without checking — and several old libraries did, famously the Node jsonwebtoken pre-5.0 — an attacker can forge any token by setting the algorithm to none and leaving the signature blank. Modern libraries reject it by default and require the verifier to whitelist allowed algorithms, but it still appears in CTF challenges and the occasional misconfigured production system. Always pass an explicit allowed algorithms list to your JWT verification function.
Why does my token decode here but get rejected by my API?
Common reasons in order of frequency: (1) expired — check the exp badge; (2) wrong audience — the aud claim does not match the API identifier the server expects; (3) wrong issuer — iss is from a different IdP than the API expects; (4) clock skew — token is "not yet valid" because nbf is a few seconds in the future and the server clock is slightly behind; (5) signature does not verify against the key the server is using (rotated keys, wrong JWKS endpoint, key not yet propagated). The decoder shows you the data; the server-side log usually tells you which check failed. If your server has no log, add one — every JWT library exposes a way to log the rejection reason.
Are JWTs encrypted?
Not by default. JWT (RFC 7519) tokens are signed, not encrypted — anyone with the token can read the payload by doing exactly what this tool does. The Base64URL encoding looks opaque but it is not. If you need confidentiality (the token contents should be hidden even from someone who intercepts it), the related spec is JWE (JSON Web Encryption, RFC 7516), which wraps the JWS inside an encrypted envelope. Most APIs do not use JWE because it adds key management complexity for limited benefit; transport encryption (HTTPS) is the standard protection.
Should I put secrets in a JWT payload?
No. The payload is Base64URL-encoded, not encrypted. Anyone with the token reads it trivially. Put a user ID, a session reference, scopes, roles — things you would put in a session cookie. Never put a password, an API key, sensitive PII, payment information, or anything else that should stay confidential in the JWT payload. The token will eventually live in browser localStorage, in proxy logs, in error reports, and any number of other places where you cannot count on it being protected.
How long should a JWT live?
Depends on the threat model. Public APIs commonly issue access tokens for 15-60 minutes with a refresh token that lives much longer (days to weeks). The shorter the access token, the less window an attacker has to use a stolen one before it dies. Server-side revocation is hard with stateless JWTs (you would need a denylist that defeats the stateless benefit), so short lifetimes are the standard mitigation. Internal service-to-service tokens can be even shorter; long-lived bot tokens are usually a sign you should be using a different auth scheme entirely.
What are the standard claims I see in every payload?
RFC 7519 defines seven registered claims, all optional: iss (issuer), sub (subject), aud (audience), exp (expiration time, Unix seconds), nbf (not before), iat (issued at), and jti (JWT ID, a unique identifier for the token). Most production tokens carry sub, exp, iat, iss, and aud. Custom claims live alongside these — typical examples are roles, scopes, tenant_id, plan, or user_id. There is also a convention of namespacing custom claims under a URL prefix (https://example.com/roles) to avoid collisions with future registered claims.
Vs jwt.io?
jwt.io is the canonical decoder, run by Auth0. Same decoding logic, same three-panel UI. The main difference for HS256 is now parity — paste the secret here and verification runs locally via Web Crypto, same as jwt.io. The difference that remains is RS256/ES256: jwt.io can fetch the issuer's JWKS and verify those for you in its sandbox; this tool keeps RS256/ES256 as decode-only and points you at your backend's JWT library for verification. If you want the lightest read-the-claims path with HS256 verification thrown in, this tool covers it; if you specifically need browser-side verification of an RS256/ES256 token, jwt.io is the standard pick.