JWT Decoder

JWT Decoder / Encoder

Decode any JSON Web Token to see its header, payload, and signature — or sign a new one with HS256/384/512. Verifies HMAC signatures locally. 100% in your browser.

JWT Decoder / Encoder — TL;DR

Decode any JSON Web Token to see its header, payload, and signature — or sign a new one with HS256/384/512. Verifies HMAC signatures locally. 100% in your browser.

No. The whole tool is JavaScript inside this page. Paste a token, decode happens in your browser, the bytes never leave the tab. Open DevTools → Network and watch — no requests are sent during decode or verify. That makes it safe to paste real customer or production tokens.

It proves the token was signed by someone holding the secret (HMAC) or the private key (RSA/ECDSA). It does NOT encrypt the payload — the header and payload are just base64url-encoded JSON, anyone with the token can read them. The signature only stops tampering: if you change a single byte of the payload, the signature no longer matches.

A JWT often carries the user ID, email, scopes, and sometimes session cookies' equivalent — exactly the data you must NOT paste into a stranger's server. iKit's decoder runs as JavaScript already loaded in your browser tab. Verifiable in DevTools → Network: no fetch, no XHR, no beacon during decode or verify.

Header

Payload

Signature

Standard claims


            

Verify HMAC signature

For HS256/384/512 tokens, type the signing secret to verify the signature locally. For RS256/ES256 (RSA/ECDSA), use a server-side library — public-key verification needs a PEM file we don't accept here.

Why iKit JWT Decoder

The fastest way to debug a JWT — no upload, no signup, no third party between you and your token.

Three panes, one paste

Paste a JWT, see the decoded header, payload, and signature side by side. Standard claims (iss, sub, aud, exp, iat) are timestamped and labelled.

Local HMAC verification

For HS256/384/512 tokens, type the secret to verify the signature using the browser's Web Crypto API. The secret never leaves your tab.

Sign your own tokens

Switch to Encode mode, edit the header and payload as JSON, choose the algorithm, type a secret, and get a signed token instantly.

Privacy by design

JWT payloads contain user IDs, emails, sometimes scopes — never paste them into a server tool. iKit's decoder runs as JavaScript in your browser. Verifiable in DevTools → Network.

Expiry awareness

Standard claims like exp, nbf, iat are highlighted with human-readable dates and a clear EXPIRED / valid badge so you can tell at a glance whether the token is still good.

Open standard, open code

Built on the browser's native Web Crypto API and JSON parser — same algorithms as OpenSSL, libjwt, jose. The behaviour matches every modern JWT library.

How JWT decoding actually works

A JWT is three base64url-encoded JSON segments separated by dots — that's it.

  1. 1

    Split on the two dots

    A JWT looks like aaa.bbb.ccc. We split on the two literal dots, giving the encoded header, payload, and signature. If we don't get exactly three parts, the token is malformed.

  2. 2

    Base64URL-decode each part

    Header and payload are base64url-encoded UTF-8 JSON. Base64URL = Base64 with -/_ instead of +//= and no padding. We do atob after replacing characters back, then JSON.parse the resulting string.

  3. 3

    Render with structure

    Header tells us the algorithm (alg: HS256, RS256, etc.) and type. Payload contains the claims — standard ones (iss, sub, aud, exp, iat, nbf, jti) plus any custom fields. We display each in a labelled section.

  4. 4

    Verify (HMAC only)

    For HS256/384/512, we re-compute the HMAC of header.payload using the secret you typed and compare to the signature in the third segment. Same as HMAC(SHA-256, secret, signing_input) base64url-encoded. Match = signature valid.

Common JWT debugging tasks

Real situations where you'll reach for a JWT decoder.

Inspecting a token from your auth provider

Auth0, Firebase, Keycloak, AWS Cognito all return JWTs after login. Paste the access_token to see what claims your app is actually receiving — what's the user ID, what scopes, when does it expire?

Debugging a 401 Unauthorized

API rejecting your request? Decode the token to check: is it expired (exp in the past)? Is the audience claim (aud) what the API expects? Is the issuer (iss) the right tenant?

Verifying a webhook signature

Stripe, GitHub Apps, Slack send webhook payloads signed as JWTs. After receiving one, paste it into Decode mode plus the shared secret to confirm the request actually came from them.

Generating test tokens

Need a fresh signed JWT for an integration test? Switch to Encode mode, edit the payload (custom user ID, custom expiry), pick HS256 + your test secret, get a token in milliseconds. No backend round-trip.

Why local JWT decoding matters

A JWT often carries the user ID, email, scopes, and sometimes session cookies' equivalent — exactly the data you must NOT paste into a stranger's server. iKit's decoder runs as JavaScript already loaded in your browser tab. Verifiable in DevTools → Network: no fetch, no XHR, no beacon during decode or verify.

  • Zero network requests during decode or verify — verifiable in DevTools.
  • Secret you type for verification stays in browser memory and is wiped on Clear / refresh.
  • Safe for production tokens, customer access tokens, and webhook secrets.

Related guides

Deep-dive tutorials and tool comparisons from the iKit blog.

Frequently Asked Questions

Is this safe? Are my JWTs uploaded?

No. The whole tool is JavaScript inside this page. Paste a token, decode happens in your browser, the bytes never leave the tab. Open DevTools → Network and watch — no requests are sent during decode or verify. That makes it safe to paste real customer or production tokens.

What does the JWT signature actually verify?

It proves the token was signed by someone holding the secret (HMAC) or the private key (RSA/ECDSA). It does NOT encrypt the payload — the header and payload are just base64url-encoded JSON, anyone with the token can read them. The signature only stops tampering: if you change a single byte of the payload, the signature no longer matches.

Why does my decoded payload look fine but verification fails?

Three common causes: (1) wrong secret — JWT secrets are case-sensitive and any whitespace mismatch breaks verification. (2) Algorithm mismatch — the header says HS256 but the secret was used with HS512 originally. (3) Token was modified after signing — even one byte breaks the signature. Check the header.alg matches what you expect.

What about RS256, ES256, and other public-key algorithms?

iKit currently supports HMAC verification (HS256/384/512) only. RS256 and ES256 use public-key cryptography — verification needs the issuer's public key in PEM format, which is a more involved UI. For now, decoding still works (the header/payload/signature parts display correctly), but the Verify button will tell you it's unsupported. RSA/ECDSA verification is planned.

How is this different from jwt.io?

Same idea, different defaults. iKit's decoder runs entirely in your browser (jwt.io does too, but iKit's code is open to view-source and our domain has no third-party trackers). We add a clear EXPIRED / valid badge for the exp claim, structured claim notes (iat / nbf / iss / sub / aud / jti as readable rows), and a copy-everything-decoded button that gives you the full structured output for paste into a bug report.