Paste a JWT token to decode it
Decodes header · payload · claims · expiry · HS256 signature verification
Also accepts Bearer eyJ… format
JWT Decoder Online Free — Read Claims, Verify Signatures & Check Expiry
What's included
Features
About this tool
Decode and Debug JWT Tokens Instantly — No Install, No Sign-Up
You're debugging a 401 Unauthorized error and you need to know what's actually inside the JWT. Is it expired? Does it have the right roles? Is the issuer or audience wrong? Paste the token here and find out in two seconds.
Every JWT has three dot-separated parts. The header says which signing algorithm was used (HS256, RS256, ES256). The payload carries the claims — user ID, email, roles, scope, expiry time. The signature proves neither was tampered with. This decoder Base64URL-decodes the header and payload instantly and shows both as formatted, syntax-highlighted JSON with plain-English descriptions for every recognised claim.
Time-based claims that look like 1715990400 are converted to human-readable dates automatically. If there's an exp (expiry) claim, a live countdown ticks down every second so you can watch a token expire in real time — useful when testing token refresh flows.
For HS256 tokens, you can also verify the signature directly in your browser using the Web Crypto API. Enter the shared secret, click Verify, and get an immediate pass or fail — no server, no code.
This tool handles tokens from Auth0, Firebase, AWS Cognito, Google OAuth, Keycloak, Okta, Azure AD, NextAuth.js, and any other standards-compliant identity provider. Paste a full Authorization header with "Bearer " prefix — it's stripped automatically.
Everything runs 100% in your browser. Nothing is uploaded anywhere. Safe for production tokens with real user data.
Step by step
How to Use
- 1Paste your JWT token into the input boxPaste any JSON Web Token into the large input box at the top. You can paste the raw token (
eyJ...) or the fullBearer eyJ...Authorization header value — the "Bearer " prefix is stripped automatically. The decoder begins parsing the moment you paste. Not sure where to start? Click Sample JWT to load a pre-built example token with name, email, roles, scope, iss, aud, and a far-future expiry. - 2Read the decoded Header and Payload panelsThe tool splits the token into its three dot-separated segments and Base64URL-decodes the header and payload into formatted, syntax-highlighted JSON. The Header panel shows
alg(signing algorithm) andtyp. The Payload panel shows all claims, followed by a claims table that lists every recognised field (iss, sub, aud, exp, iat, roles, scope, email, etc.) with a plain-English description of what each claim means. - 3Check the expiry status and live countdownIf the token contains an
exp(Expiration Time) claim, a colour-coded badge appears in the header bar — Valid (green), Expires soon (amber), or Expired (red) — with a live countdown that ticks every second. A progress bar shows what percentage of the token's lifetime has elapsed. Time-based claims (exp,iat,nbf,auth_time) are displayed as both Unix timestamps and human-readable date strings. - 4Verify an HS256 signature (optional)For tokens using
alg: HS256, scroll to the Signature panel. Enter your shared HMAC secret in the input field (toggle visibility with the eye button) and click Verify Signature. The tool uses the browser's Web Crypto API to re-compute the expected HMAC-SHA256 and compare it against the token — no server involved. A green "Signature is valid" or red "Signature is invalid" result appears instantly. For RS256 or ES256 tokens, a note explains that server-side verification is needed. - 5Watch for security warningsIf the token contains
alg: none— meaning no cryptographic signature — an amber warning appears in the Signature panel immediately. Tokens withalg: noneare completely unsigned and allow an attacker to forge arbitrary claims. Any production server must rejectalg: nonetokens entirely. Copy any panel's JSON using the Copy button for use in other tools or log analysis.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
Paste your JWT token into the input field. The decoder instantly reads the exp (Expiration Time) claim and shows you a live countdown — if the token is expired, you'll see a red "Expired" badge and exactly how long ago it expired. The payload panel shows all claims so you can spot wrong issuer (iss), audience (aud), or scope values that might cause a 401. This is faster than adding console.log statements or reading raw headers in DevTools.
Paste the full JWT into the input field — including or excluding the "Bearer " prefix (it's stripped automatically). The decoder instantly splits the token into its three parts and Base64URL-decodes the header and payload, displaying them as formatted, syntax-highlighted JSON. You don't need a secret key to read the claims — the header and payload are encoded, not encrypted, so anyone with the token string can read them. Every recognised claim (iss, sub, aud, exp, iat, roles, scope, email, etc.) is shown with a plain-English description.
Yes — all processing runs entirely in your browser. Decoding, signature verification, and expiry calculation all happen in client-side JavaScript using the Web Crypto API. Nothing is ever transmitted to any server. If you're handling production tokens with sensitive user data, you can disconnect from the internet before pasting to be completely certain nothing leaves your machine. Unlike jwt.io (which makes network requests), this tool is 100% client-side.
For HS256 (HMAC-SHA256) tokens: paste your JWT, scroll to the Signature panel, enter your shared secret, and click Verify. The tool uses the browser's Web Crypto API to re-compute the expected HMAC-SHA256 signature from the header and payload and compare it against the token — entirely in your browser, no server involved. For RS256 (RSA) or ES256 (ECDSA) tokens from identity providers like Auth0, Cognito, or Google, browser-side verification requires the public key and is not currently supported here — use your server-side JWT library for those.
The exp (Expiration Time) claim is a Unix timestamp — seconds since January 1, 1970. This tool automatically converts exp, iat (Issued At), nbf (Not Before), and auth_time to human-readable date-time strings alongside the raw Unix values, so you can read them instantly. It also shows a live countdown timer that ticks down every second, plus a colour-coded progress bar showing what percentage of the token's lifetime has elapsed.
When you copy an Authorization header value from browser DevTools, Postman, or an API client, it typically reads "Bearer eyJhbGci...". Paste it directly — the tool automatically strips the "Bearer " prefix (case-insensitive) before decoding, so you don't need to edit the string. You can also paste just the raw token if you prefer.
Decoding means reading the header and payload — it requires no secret and simply Base64URL-decodes the first two dot-separated segments. Anyone with the token string can decode it, which is why JWT payloads should never contain sensitive secrets like passwords or credit card numbers. Verifying means checking the cryptographic signature matches the header and payload using the secret or public key — proving the token was issued by a trusted party and hasn't been tampered with. Always verify JWTs on the server side before trusting their claims. Decoding without verifying is only for debugging.
Paste the token — it works with any standards-compliant identity provider. JWTs from Auth0, Firebase Authentication, AWS Cognito, Google OAuth 2.0, Keycloak, Okta, Azure AD, and NextAuth.js all follow the same RFC 7519 structure. OIDC-specific claims like sub, email, picture, locale, roles, scope, and azp (Authorized Party) are all recognised and shown with descriptions. These providers typically use RS256 (RSA-signed), so the signature can be decoded but not verified here without the public key.
alg:none means the JWT carries no cryptographic signature — it's a completely unsigned token. The JWT spec originally allowed this, but an attacker can exploit any server that accepts alg:none tokens by crafting arbitrary payloads with fake user IDs, elevated roles, or extended expiry times — no secret needed. This is CVE-2015-9235, a well-known critical vulnerability. This decoder shows an amber warning when it detects alg:none. A production server must reject tokens with alg:none entirely.
The security of a JWT comes from the signature, not from the encoding. The header and payload are Base64URL-encoded — which is trivially reversible — so anyone who obtains the token can read the claims inside it. This is by design: JWT is transparent, not encrypted. The signature at the end, computed from the header and payload using a secret key, is what prevents tampering. An attacker who modifies any claim will produce an invalid signature that the server will reject. Never put passwords, payment data, or private secrets in a JWT payload — only put data you are comfortable exposing.
These are the five core registered claims defined in RFC 7519. iss (Issuer) identifies who created and signed the token — typically an identity provider URL like https://accounts.google.com or https://your-tenant.auth0.com. sub (Subject) identifies the principal the token represents — usually a user ID or service account ID, unique within the issuer's namespace. aud (Audience) identifies the intended recipients of the token — your API server checks that its own identifier appears here before accepting the token. exp (Expiration Time) is a Unix timestamp after which the server must reject the token. iat (Issued At) is the Unix timestamp when the token was created, used for audit logging and to calculate the token's current age. Your server should validate all five claims on every request.
In JavaScript: const [header, payload] = token.split(".").slice(0, 2).map(part => JSON.parse(atob(part.replace(/-/g, "+").replace(/_/g, "/")))); — atob() decodes Base64, the replace calls convert Base64URL characters to standard Base64. In Python: import base64, json; parts = token.split("."); payload = json.loads(base64.urlsafe_b64decode(parts[1] + "==")) — the "==" padding handles the missing Base64 padding that Base64URL omits. For production code, always use a JWT library (jsonwebtoken for Node.js, PyJWT for Python, jose for browser/edge) that also handles signature verification, claim validation, and algorithm restrictions. Manual decoding without verification is only appropriate for debugging, logging, and inspection tools.