JWT Decoder

Decode and inspect JSON Web Tokens — view the header, payload, and signature with syntax highlighting. Timestamps are automatically converted to human-readable dates. Everything runs in your browser — nothing is uploaded.

shield

Privacy: This tool decodes JWTs entirely in your browser. No token data is sent to any server. Avoid pasting tokens that contain sensitive secrets in shared or public environments.

What it does

Instant decode as you type

Splits the token on its dots and base64url-decodes the header and payload immediately — no submit button.

Human-readable timestamps

iat, exp, and nbf are converted from Unix seconds to dates; expired tokens are flagged in red with a live countdown for active ones.

Algorithm identification

Reads the alg field from the header (HS256, RS256, ES256, PS256, and more) and shows it in the status bar and header panel.

Syntax-highlighted sections

Keys, strings, numbers, and booleans are color-coded across the Header, Payload, and Signature tabs.

Copy by section

Copy Header, Copy Payload, or Copy All to drop decoded output straight into a ticket or doc.

Decode-only by design

No secret or private key is ever requested, so there is never a reason to expose a key in the browser. Verification stays server-side.

How to use JWT Decoder

  1. 1
    Paste your JWT token

    Click the token input field and paste your JWT. The decoder starts parsing immediately as you type or paste — no button press needed.

  2. 2
    Inspect the Header and Payload tabs

    Switch between the Header, Payload, and Signature tabs to explore each part of the token. Keys are highlighted in teal, strings in dark, numbers in amber, and booleans in violet for easy reading.

  3. 3
    Check timestamps and expiry

    Fields like iat (issued at), exp (expiration), and nbf (not before) are automatically converted to human-readable dates. Expired tokens are flagged in red; active tokens show a countdown in the status bar.

  4. 4
    Copy the decoded output

    Use the Copy Header or Copy Payload buttons for individual sections, or Copy All to grab the complete decoded output for use in debugging or documentation.

When to use this

Reading claims while debugging an auth flow

Login works locally but returns 401 in staging — decode the token to check whether sub, iss, and aud match the environment, and read exp instead of doing epoch math by hand.

Verifying a signature — use a library, not this tool

Signature verification needs the secret or public key, which has no business in a browser. Verify server-side with jose or jsonwebtoken (Node), PyJWT (Python), or the equivalent in your stack.

Scripting or CI pipelines — use a CLI

For shell workflows, jwt-cli ('jwt decode <token>') fits into scripts and can verify when you pass it a key. Use this page for an interactive read instead.

Comparing tokens across tenants or environments

When the problem is iss/aud/tenant mismatches rather than one token's contents, the Multi-Tenant JWT Debugger (linked below) compares tokens across issuers and audiences side by side.

Avoiding key exposure that jwt.io invites

jwt.io verifies in-browser by having you paste the secret or public key into the page. This tool skips verification on purpose so a production key is never typed into a web form.

Common errors & fixes

Invalid token: not three parts
A JWT is header.payload.signature with exactly two dots. Strip any 'Bearer ' prefix, surrounding quotes, and stray whitespace or newlines from the paste.
A single segment won't decode in a standard Base64 tool
JWT uses the base64url alphabet ('-' and '_' instead of '+' and '/') with padding removed. Decode with a base64url-aware tool, or re-add padding before using a standard Base64 decoder.
Header shows "alg": "none"
That is an unsigned (or forged) token. Never trust it for a security decision — servers must explicitly reject 'none' and confirm the algorithm matches the one they expect.
Token decodes here but the server rejects it
Decoding ignores validation rules. Check exp (expired), nbf (not yet valid), and aud (wrong audience) — all of which the server enforces but a decoder does not.

Technical details

Decodingbase64url, in-browser only — no network request
Signature verificationNot performed (requires secret or public key)
Algorithms parsedHS256/384/512, RS256/384/512, ES256/384/512, PS256, none
Timestamp claimsiat, exp, nbf converted from Unix seconds to local date
Token formatheader.payload.signature (two dots, three base64url parts)
OfflineWorks after the page has loaded

JWT structure — what the three parts actually contain

A JWT consists of three Base64url-encoded sections separated by dots: header.payload.signature.

The header is a JSON object describing the token type and signing algorithm: {"alg": "HS256", "typ": "JWT"}. The algorithm tells the recipient how to verify the signature. Common values: HS256 (HMAC with SHA-256, uses a shared secret key), RS256 (RSA with SHA-256, uses a public/private key pair), ES256 (ECDSA with P-256 curve, smaller and faster than RSA).

The payload is a JSON object containing claims — assertions about the subject or the token. Standard registered claims include: sub (subject, usually a user ID), iss (issuer, the service that created the token), aud (audience, the service the token is intended for), iat (issued at, Unix timestamp), exp (expiration time, Unix timestamp), nbf (not before, Unix timestamp). Any additional claims are custom (often called "private claims" in RFC 7519 terminology).

The signature is created by: base64url(header) + '.' + base64url(payload), then signing this string with the algorithm and key from the header. For HS256, the signing key is a shared secret. For RS256, the private key signs and the public key verifies. The signature proves the token has not been tampered with — changing any character in the header or payload invalidates the signature.

JWT vs session tokens — when to use each

JWTs and traditional server-side sessions are two different approaches to maintaining authenticated state between HTTP requests.

Server-side sessions: the server stores session data (user ID, permissions, preferences) in a database or in-memory store (Redis). The client holds only a session ID cookie. To validate a request, the server looks up the session ID in the store. This is stateful — adding or revoking a session requires a database operation, but revocation is instant.

JWTs are stateless: all claims are encoded in the token itself. The server validates by verifying the signature — no database lookup needed. This scales horizontally without shared session storage. The trade-off is that revocation is difficult: a valid JWT remains valid until its exp claim passes, even if the user has logged out or had permissions changed. The common workarounds — token blacklists, short expiry times with refresh tokens — add complexity.

Best practices for JWT: set a short exp (15–60 minutes for access tokens), use refresh tokens (longer-lived, stored securely, exchanged for new access tokens), always verify the exp, iat, and aud claims on the server, never decode a JWT in the browser and trust it for security decisions without server-side verification.

Common JWT security mistakes developers make

JWT is frequently misimplemented in ways that create serious security vulnerabilities.

Algorithm confusion ("alg: none" attack): early JWT libraries accepted a token with "alg": "none" and no signature as valid. An attacker could create a forged token, set alg to none, and bypass authentication entirely. Always explicitly verify that the algorithm in the header matches the expected algorithm before validating the signature.

HS256 with a weak secret: HMAC-based JWT (HS256, HS384, HS512) requires a strong secret key. Using a guessable key ("secret", "password", a username, a database name) allows offline brute-force attacks — the attacker just needs a valid token to test candidate keys against. Use a randomly generated secret of at least 32 bytes.

Storing JWTs in localStorage: localStorage is accessible by any JavaScript on the page, making it vulnerable to XSS attacks. If an attacker injects script (via XSS) on your domain, they can steal all tokens from localStorage. Use HttpOnly cookies instead — they are not accessible to JavaScript. The downside is CSRF vulnerability, mitigated with SameSite=Strict or a CSRF token.

Not validating exp: if the server does not check the exp claim, tokens never expire — a stolen token grants permanent access. Always validate exp on every request.

Frequently Asked Questions

What is a JWT token?

A JWT (JSON Web Token) is a compact, URL-safe token format used for securely transmitting information between parties. It consists of three base64url-encoded parts separated by dots: a header (algorithm and token type), a payload (claims like user ID and expiry), and a signature used to verify authenticity.

Is it safe to paste my JWT here?

This tool runs entirely in your browser — no token data is ever sent to a server. That said, JWTs can contain sensitive user information, so avoid pasting production tokens in shared, public, or untrusted environments. For testing, use short-lived tokens or sample tokens.

What do iat, exp, and nbf mean in a JWT payload?

These are standard registered claim names. 'iat' (issued at) is the Unix timestamp when the token was created. 'exp' (expiration time) is when the token expires and should be rejected. 'nbf' (not before) is the earliest time the token is valid. All three are Unix timestamps (seconds since January 1, 1970).

Can this tool verify a JWT signature?

No. Signature verification requires the secret key (for HMAC algorithms like HS256) or the public key (for RSA/ECDSA algorithms like RS256/ES256). Since keys should never be exposed to a browser, this tool only decodes the header and payload. For server-side verification, use a JWT library in your application code.

What JWT signing algorithms are supported?

This decoder can parse tokens signed with any algorithm — HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, and more — since decoding the header and payload only requires base64url decoding, not cryptographic verification. The algorithm is displayed in the status bar and header panel.

Why does JWT use base64url instead of regular Base64?

Tokens travel in URLs and HTTP headers, where '+', '/', and '=' are problematic. base64url swaps '+' for '-', '/' for '_', and drops the trailing padding. If you paste a single segment into a standard Base64 decoder, account for that alphabet difference or it may fail to decode.

My token won't decode — what's wrong?

A JWT must have exactly three parts separated by two dots (header.payload.signature). The most common breakage is a copy-paste that dropped a segment, kept a 'Bearer ' prefix, or added surrounding quotes or a newline. Strip those and try again.

Can I edit a token's claims and re-sign it here?

No. Re-signing requires the secret (HS256) or private key (RS256/ES256) and a cryptographic step this tool intentionally does not perform. Modify and sign tokens in your application code with a JWT library instead.

Does an expired token still decode?

Yes. Expiry is a validation rule, not an encoding rule — the payload decodes regardless, and the status bar flags it as expired. Rejecting expired tokens is the server's job, not the decoder's.

Is there a size limit on the token?

No hard cap. Tokens in the tens of kilobytes decode fine. If yours is that large it usually means too many claims are packed into the payload — keep JWTs lean since they ride on every request.

Related Tools