Free tool

JWT decoder

This free JWT decoder takes a JSON Web Token and instantly shows you what's inside: the decoded header, the payload with every claim, human-readable timestamps, and a live “expires in” countdown. You can also verify HS256/HS384/HS512 signatures against a secret — locally, via your browser's WebCrypto API. The token and secret never leave your browser.

JWT decoder

Paste a JSON Web Token to see its header, payload, and claims instantly — and verify HMAC signatures locally. Nothing ever leaves your browser.

FreeToken never leaves your browserDecode + HS256/384/512 verify

Decoding is plain Base64URL + JSON parsing and signature checks use the built-in WebCrypto API — all of it local to this tab, with zero network requests. Remember that a JWT's payload is only encoded, not encrypted: anyone holding the token can read it, so treat tokens like passwords.

How to decode a JWT online

  1. Paste the token. Drop the JWT into the box above — straight from a browser's developer tools, a log line, or an Authorization header. A leading “Bearer ” prefix, surrounding quotes, and stray line breaks are cleaned up automatically.
  2. Read the three segments. The token is shown split into its color-coded parts — header, payload, and signature — so you can see exactly where each segment begins and ends.
  3. Inspect header, payload, and claims. Both JSON documents are pretty-printed with copy buttons, and the registered claims (iss, sub, aud, iat, nbf, exp, jti) appear in a table with their meanings and, for the time-based ones, real dates instead of raw Unix timestamps.
  4. Optionally verify the signature. Expand the verification panel, paste the shared secret, and get an immediate Valid / Invalid answer for HMAC-signed tokens.

Everything is live — paste a different token and the whole view updates instantly, with the expiry badge counting down in real time.

What's inside a JSON Web Token

A JWT is three Base64URL-encoded segments joined by dots: header.payload.signature. The header is a small JSON object that says how the token is signed — typically an alg claim like HS256 or RS256 and a typ of JWT. The payload is the actual data: who the token is about, who issued it, when it expires, plus any custom claims the issuing application added — user roles, email, tenant IDs. The signature is what makes the token trustworthy: it's a cryptographic checksum of the first two segments, produced with a secret (HMAC) or a private key (RSA/ECDSA), so any tampering with the header or payload makes the signature stop matching.

This structure explains the golden rule of JWT debugging: anyone can read a token, but only the holder of the key can mint one. Decoding requires no secrets at all — which is exactly what this jwt token decoder does — while verification is a separate, cryptographic step.

Decoding is not decrypting

A surprisingly common misconception is that a JWT is encrypted. A standard signed JWT (a JWS) is encoded, not encrypted: Base64URL is a plain reversible transformation — the same family as the encoding handled by the Base64 encoder / decoder — with two URL-safe character substitutions and the padding stripped. That's why this tool can show you the payload instantly with zero keys: it fixes the padding, swaps the characters back, decodes the bytes as UTF-8, and parses the JSON.

The practical consequence: never put secrets in a JWT payload. Passwords, API keys, and personal data in a token are readable by anyone who ever sees the token — in a log file, a crash report, a browser extension, or a support screenshot. The signature stops tampering; it does nothing to stop reading. (Encrypted tokens do exist — JWE, with five segments instead of three — but the tokens used for everyday API auth are almost always signed JWS tokens.)

The registered claims, explained

The JWT specification (RFC 7519) reserves seven short claim names with defined meanings. This decoder recognizes all of them and explains each one inline:

ClaimNameMeaning
issIssuerWho created and signed the token — often an auth server URL
subSubjectWho the token is about, usually a user ID
audAudienceWhich service the token is meant for — receivers must reject tokens aimed elsewhere
iatIssued atWhen the token was created (Unix seconds)
nbfNot beforeThe token must be rejected before this moment
expExpirationThe token must be rejected after this moment
jtiJWT IDA unique identifier, useful for one-time use and revocation lists

Anything else in the payload is a custom claim defined by whoever issued the token — name, email, roles, scope, and tenant identifiers are common. Those appear in the pretty-printed payload JSON, while the table focuses on the registered set.

Checking expiry: exp, iat, and nbf

The time claims are Unix timestamps — seconds since January 1, 1970 — which is why a raw payload shows unhelpful numbers like 1516239022. The decoder converts each one to a real date in your local timezone and adds a relative reading (“in 2h 14m”, “3 days ago”). For exp specifically, a live badge counts down to the second: green “Expires in…” while the token is alive, red “EXPIRED … ago” once it isn't, and a note when there's no exp claim at all — which is worth flagging, because a token that never expires is a standing risk if it ever leaks.

When you're debugging a “token expired” error that makes no sense, compare the exp date here against the server's clock, not just your own: a few minutes of clock drift between machines is enough to reject freshly issued tokens, which is why validators typically allow a small leeway. And if you're working with raw timestamps elsewhere, the timestamp converter does the Unix-to-date math on its own.

Verifying an HMAC signature with a secret

Decoding tells you what a token says; verification tells you whether it's genuine. For HMAC-signed tokens (alg of HS256, HS384, or HS512), the signature is a keyed hash of header.payload computed with a shared secret. Expand the verification panel, paste the secret, and the tool recomputes the HMAC with your browser's WebCrypto API and compares it against the token's third segment — a clear Valid or Invalid, updating live as you type the secret.

Scope, stated honestly: this covers the HS family only. Tokens signed with RSA or ECDSA (RS256, ES256, and friends) use public/private key pairs, and this tool doesn't include public-key verification — if a token uses one of those algorithms, the panel says so instead of pretending. Verifying here is ideal for development and debugging: checking that your app and your auth service agree on the secret, or confirming that a rejected token really was tampered with. It is not a substitute for verification in your backend, which must also validate exp, aud, and iss on every request.

Why your token should never leave your browser

Here's the thing about pasting a JWT into a random website: a live token is a credential. Whoever holds it can call your API as you until it expires. That makes “paste your token into this online tool” a genuinely risky habit — you're trusting the site's owner, every script it loads, and every analytics vendor it embeds. Well-known decoders like jwt.io do run client-side, but the safest default is a decoder that provably has nothing to send: this page performs zero network requests with your input. Decoding is local Base64URL and JSON parsing; verification is the WebCrypto API built into your browser; the secret field is never transmitted, stored, or logged. Once loaded, the page works with your connection switched off.

Even so, habits worth keeping: prefer decoding expired or development tokens over production ones, rotate any secret you've pasted anywhere you're unsure about, and treat tokens in logs and screenshots exactly like passwords.

Common reasons a JWT fails to decode or validate

  • Truncated copy. Tokens are long, and terminals and chat apps love to cut them off or wrap them. If the decoder reports a segment that isn't valid Base64URL, re-copy the token from the source.
  • Wrong number of parts. Two dots, three segments. One dot means it isn't a JWT (or the signature is missing); four means you may have an encrypted JWE, which this tool can't open.
  • Expired token. The single most common cause of a rejected API call — check the live exp badge before blaming anything else.
  • Signature mismatch. The secret differs between services (a trailing newline in an env var is a classic), or the token was signed with a different algorithm than the validator expects.
  • Clock skew. Freshly issued tokens rejected as “not yet valid” usually mean the issuer's clock is ahead of the validator's — compare iat and nbf against real time.

Who uses a JWT decoder?

  • Backend developers checking what claims an auth service actually put in the token.
  • Frontend developers debugging 401s by inspecting the token the app is really sending.
  • QA engineers confirming roles, scopes, and expiry times in test environments.
  • DevOps & SREs reading tokens out of logs and traces during incident response.
  • Security reviewers auditing token lifetimes, audiences, and algorithm choices.

Related jobs, same toolbox: the JSON formatter for the payload you just copied, the hash generator for checksums, and the XML formatter when the legacy half of your stack answers in XML.

Frequently asked questions

Is this JWT decoder free and safe to use?
Yes. It's free with no sign-up, and it makes zero network requests with your input — decoding and signature verification both run locally in your browser, and the page keeps working offline once loaded.
Can you decode a JWT without the secret?
Yes — the header and payload are only Base64URL-encoded, not encrypted, so anyone can read them without any key. The secret is only needed to verify the signature or to create a valid token.
Does this tool verify JWT signatures?
Yes, for HMAC algorithms: HS256, HS384, and HS512. Paste the shared secret and the signature is checked locally via the WebCrypto API. RSA and ECDSA tokens (RS256, ES256, etc.) are decoded but not verified — the tool tells you so rather than guessing.
How do I read the exp claim?
exp is a Unix timestamp in seconds. The decoder converts it to a date in your timezone and shows a live badge — 'Expires in 1h 23m' while valid, 'EXPIRED' with how long ago once it isn't.
Why does my token fail to decode?
The usual causes are a truncated or line-wrapped copy (breaking the Base64URL), the wrong number of segments (a JWT has exactly three, separated by two dots), or a value that isn't actually a JWT. The error message says which segment failed and why.
Is it safe to paste a production token here?
This page never transmits your token — everything is local. That said, a live token is a credential, so the safest habit with any tool is to prefer expired or development tokens, and to rotate secrets you've pasted anywhere you don't fully trust.

Decode the token, then shorten the docs link

fewly turns any URL into a short, branded, trackable link — free to start, no credit card.