JWT Decoder
Decode JSON Web Tokens — header, payload, signature.
How to use JWT Decoder
- Paste a JWT into the input area. A leading `Bearer ` prefix is stripped automatically.
- Read the meta bar above the output — it shows the signing algorithm, token type, and a live countdown until expiration.
- Use the Header and Payload panels to inspect every claim as pretty-printed JSON.
- The Signature panel shows the raw base64url signature segment — useful for comparison but not verifiable here.
- Click Copy on any panel to grab the formatted JSON or the signature for your own verifier.
- Click Share to copy a URL that restores the token into this tool for a teammate. The token stays in the URL fragment, which browsers never send to a server.
JWT Decoder
A fast, private JWT decoder that splits a JSON Web Token into its three parts — header, payload, signature — pretty-prints the JSON, surfaces the standard registered claims, and tells you at a glance whether the token has expired. Everything runs in your browser. Your token is never uploaded.
Why another JWT decoder?
Because most of them are surprisingly casual about what they do with your input. The canonical debugger at jwt.io is excellent, but dozens of clones ship input straight to a server, log it in analytics, or bundle a chain of third-party scripts whose job descriptions include "see what the user types." JWTs are credentials — access tokens, ID tokens, refresh tokens. Pasting one into a random decoder that happens to rank on Google is strictly worse than pasting a password there: the token usually has a broader blast radius (a single stolen access token can unlock multiple APIs for its whole TTL) and the user interface makes the pasting feel safe.
This tool runs the entire decode transform client-side: atob for base64url, TextDecoder for UTF-8, JSON.parse for structure, and five lines of arithmetic for the timestamp math. There is no network call, no analytics on input content, and no third-party script in the chain between your clipboard and the three JSON panels you see on the page. The "Share" button encodes state into the URL fragment (#s=…), which browsers, per the HTTP spec, never send to any server — shared links stay peer-to-peer.
What it decodes
- Header. The JOSE header JSON:
alg(signing algorithm — HS256, RS256, ES256, PS256, EdDSA, and the rest of the RFC 7518 menagerie),typ(usuallyJWT),kid(key ID for JWKS lookups),cty(content type for nested tokens), and whatever custom fields your issuer added. - Payload. The JSON claims object. All seven RFC 7519-registered claims (
iss,sub,aud,exp,nbf,iat,jti) plus anything else your issuer put in there — scopes, roles, tenant IDs, email addresses, feature flags, nested objects, arrays. Full Unicode is preserved: if yournameclaim contains emoji or CJK characters, the decoded JSON shows them exactly as the issuer encoded them. - Signature. The raw base64url-encoded signature segment. You can copy it for comparison with another decoder, but you can't verify it here without the issuer's key (see FAQ #1).
What the meta bar tells you
Above the three panels sits a compact strip of badges derived from the most important claims:
- Algorithm. The
algheader value.alg: noneis flagged explicitly — it is almost always a bug, and a security issue if accepted by a verifier. - Expiration. If
expis present, the decoder converts the NumericDate to a Date and compares against your local clock. Expired tokens get a red badge. Tokens that are still valid show a live countdown likeExpires in 12m 40sthat ticks down once per second — useful for catching tokens that are about to roll over while you debug. - Not-yet-valid. If
nbf(not before) is in the future, a warning badge appears alongside the absolute NBF timestamp. - sub / iss / aud. Displayed verbatim.
audis rendered as a comma-separated list when the issuer used the array form.
Privacy-first, offline-capable
The entire tool is a few hundred lines of TypeScript plus a pair of web platform APIs. After the first visit the whole page is cached, which means the decoder works offline — useful at airports, in customer datacenters, on restricted networks where a jwt.io request would be blocked outright. No JWT data ever leaves your machine; we don't proxy tokens, we don't log inputs, and the getBoundingClientRect observer you'd find in an analytics-heavy page is simply not there.
If you want to be paranoid, open the browser devtools Network tab and decode a token. You will see exactly zero outbound requests from the decode interaction — the only requests in the trace are the static page assets that loaded on navigation.
What this tool deliberately doesn't do
- Signature verification. Requires a secret or public key that we refuse to handle client-side. Use a server-side verifier (see FAQ #1).
- JWE (encrypted JWT). Different format, five segments, needs a decryption key. Planned as a separate tool.
- Signing or creating new JWTs. Token issuance is the issuer's job — we wouldn't want a browser tool to mint live credentials that could then leak through the URL bar.
- Nested JWT auto-unwrapping. Copy the inner token and paste it back in to peel the next layer. A future iteration may auto-unwrap when it detects
typ: JWTinside the payload.
Related tools
- Base64 Encode / Decode — decode the individual segments by hand if you want to see what the raw bytes look like before JSON-parsing.
- JSON Formatter — pretty-print or minify any JSON blob, including the header/payload you copy out of this decoder.
- SHA-256 Hash — hash the "header.payload" portion if you are debugging a signing implementation that uses HMAC-SHA-256.
When you just need to see what is inside a token, this is the shortest path: paste, read, copy, move on.
Frequently asked questions
Can I verify the signature of my JWT in the browser?
No — not with this tool, and not with any decoder that doesn't already have your signing secret or public key. Verifying an HS256 token requires the shared HMAC secret; verifying an RS256 or ES256 token requires the issuer's public key (usually fetched from a JWKS endpoint). This is a decoder, not a verifier, and it deliberately never asks for a secret. When your app needs to trust a JWT, verify it server-side with `jose`, `jsonwebtoken`, `PyJWT`, or whatever your language's library of choice is. Use this tool to inspect what's inside a token — not to decide whether to accept it.
Is my JWT safe to paste into this tool?
The decoder runs 100% in your browser. Nothing is uploaded, no analytics capture the input, and there is no server-side JWT endpoint in the request chain. That said, JWTs typically carry real secrets by design — session identifiers, refresh tokens, user IDs, internal service claims, tenant identifiers, occasionally even email addresses and role bitmaps. Be careful where you paste them regardless of the tool. If the token protects production data, treat it the way you'd treat a password — don't share it in a chat, don't leave it in browser history, and rotate it if you ever lose track of where it has been.
Why does the tool say "header.payload.signature" must have three parts?
A JWT per RFC 7519 §7.1 is literally three base64url-encoded segments joined by dots. The first is the JOSE header (algorithm + token type), the second is the JSON claims payload, the third is the signature over the first two. A token with only two parts is usually a truncated copy-paste; a token with four parts is more likely a JWE (JSON Web Encryption), which is a different format with five segments. This tool handles JWS-style JWTs only. JWE support is on the roadmap.
What does the "Expired" badge mean exactly?
The decoder reads the `exp` claim (RFC 7519 §4.1.4 — expiration time as seconds since 1970-01-01 UTC) and compares it to your local clock. If `exp` is in the past, the red "Expired" badge appears and the TTL shows a negative value like `32m ago`. If `exp` is in the future, you get a green "Expires in 12m 40s" badge that ticks down once per second. Tokens without an `exp` claim show no expiry badge — they are either long-lived refresh tokens or tokens whose issuer relies on some other revocation mechanism.
Does this tool handle nested JWTs, JWKs, or JWE payloads?
Not in v1. A nested JWT (a JWT whose payload is itself a JWT, common in some identity-federation flows) will decode the outer envelope — copy the inner `payload.jwt` value and paste it back in to peel the next layer. JWE (encrypted JWT) has a different five-segment shape and needs a decryption key, which a client-side tool shouldn't be handling. JWKs (the public-key format the issuer publishes) are just plain JSON — paste them into the JSON formatter instead.