Dev Hub Solutions

Product studio

Get in touch
DeveloperLive

JWT Decoder

Decode JWT tokens locally — header, payload, expiry.

Decoded locally. We never see or send your token.

Header

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

Payload

{
  "sub": "user_123",
  "name": "Abdullah Basim",
  "iat": 1716239022,
  "exp": 1731775022,
  "iss": "devhubsolutions.net"
}
⚠ Expired 2024-11-16T16:37:02.000Z

Signature

signature_would_go_here

About JWT Decoder

A safe JWT decoder. Most JWT debug sites send your token through their server — terrible idea for production tokens. This one decodes locally.

Why we built it

jwt.io is great but pushes tokens through analytics. We wanted a 100%-local alternative for production tokens.

How to use

  1. 1Paste your JWT into the editor.
  2. 2View decoded header, payload and signature.
  3. 3Check expiry, issuer and audience claims.

A JWT (JSON Web Token) is a compact, URL-safe way to carry signed claims between systems. Every modern auth system you touch — Auth0, Clerk, Supabase Auth, Firebase Auth, your home-rolled Node service — issues them. This decoder reads any JWT and shows you what's inside: who issued it, who it was issued to, when it expires, what permissions or scopes it grants. It does this locally, in your browser, because real production tokens shouldn't go anywhere else.

Anatomy of a JWT

Three Base64url-encoded sections joined by dots: `xxxxx.yyyyy.zzzzz`. The first section (header) declares the signing algorithm — typically `HS256`, `RS256`, or `ES256` — and a token type of `JWT`. The second (payload) holds claims: `sub` (subject — usually a user ID), `iss` (issuer), `aud` (audience), `exp` (expiration as a Unix timestamp in seconds), `iat` (issued at), `nbf` (not before), plus any custom claims the issuer added. The third (signature) is the result of running the header and payload through the chosen algorithm with the issuer's key. Anyone can read the first two parts. Only the issuer can produce a valid third part.

Why local decoding is non-negotiable for production tokens

jwt.io is great, but the famous decoder at jwt.io was historically backed by analytics that observed input. Multiple smaller "JWT debug" sites pipe tokens through their server to decode. Until the token expires, anyone who saw it can replay it — and a typical auth token from a system like Auth0 or Clerk has a 24-hour expiry. Pasting a production token into a decoder you don't control is functionally identical to leaking a working credential. This decoder uses `atob()` + `JSON.parse()` in your browser. No network call. No log entry. Open DevTools, confirm.

Claims that matter, and how to read them

`exp` is the most important — it's a Unix timestamp in seconds (not milliseconds). We render the exact wall-clock time in your local timezone and show whether the token is currently valid. `iat` is when it was minted; the gap between `iat` and `exp` is the token's lifetime. `sub` identifies the principal — for user tokens, this is the user ID. `iss` and `aud` matter for federation and multi-tenant setups: a token issued by `https://auth.example.com` and intended for audience `api.example.com` should be rejected by a service that thinks it's serving a different audience. Custom claims (anything not in RFC 7519) live alongside the standard ones — common examples: `role`, `permissions`, `tenant`, `email`, `org_id`.

Common mistakes that look like JWT bugs

Tokens that "expired immediately" usually have a clock skew between the issuer and the verifier — most verifiers allow a small clock skew window (typically 30 seconds), so a difference larger than that produces a fresh-but-expired-looking token. Tokens that decode fine but get rejected by the server usually fail signature verification — the server has a different key than the one that signed the token. "My JWT is too big" usually means someone stuffed the user's permissions array into the payload — JWTs balloon fast that way. The fix is to reference a session record on the server instead of dumping everything into the token.

Frequently asked questions

Quick answers to the questions people actually ask about JWT Decoder.

Is it safe to decode a JWT online?

Only if the decoding is local. Many JWT debug sites send the token through their server for parsing, which means staff and infrastructure logs can see your token — and a JWT with `exp` 24 hours from now is a working credential. This decoder runs entirely in your browser. Open DevTools, paste a token, watch the Network tab: zero outbound requests.

What are the three parts of a JWT?

A JWT is three base64url-encoded segments joined by dots: `header.payload.signature`. The header declares the signing algorithm. The payload contains claims (`sub`, `iss`, `exp`, plus whatever the issuer added). The signature proves the issuer signed the first two parts — without the issuer's secret or public key, you can't verify it, but you can always read it.

What does "expired" mean?

The `exp` claim is a Unix timestamp (seconds since epoch). If it's in the past, the token has expired and a properly-configured server will reject it. `iat` is when it was issued, `nbf` is "not before" — the earliest time it's valid. We display all three in your local timezone so you can see exactly when each kicks in.

What's the difference between signing and encrypting a JWT?

A signed JWT (JWS) is encoded but not encrypted — anyone can read the payload. That's a security pitfall if you put PII or secrets in there. An encrypted JWT (JWE) wraps the whole thing so the payload is only readable with the key. Most JWTs in the wild are JWS — including your auth tokens, almost certainly. Don't put anything sensitive in the payload.

Why does the header say `alg: none`?

Some JWTs use `alg: none` as a way to disable signature verification — which is also a notorious vulnerability if the server accepts it. Real production tokens use `HS256` (HMAC-SHA256, symmetric), `RS256` (RSA, asymmetric), or `ES256` (ECDSA). If you see `alg: none` on a production token, that's a finding.

Can this verify the signature?

Not yet — verification requires the issuer's public key (RS256/ES256) or shared secret (HS256), and we want to avoid being a place where shared secrets end up pasted. For verification, use a backend library: `jose` (Node), `PyJWT` (Python), `golang-jwt/jwt` (Go).