🔑 JWT Debugger — Decode & Verify

Token Summary
Header

    
Payload (Claims)

    
Registered Claims
ClaimValueMeaning
Expiration Status
Signature Verification

💡 Decode needs no key. For signature verification: HS256/HS384/HS512 → paste the shared secret; RS256/RS384/RS512 → paste the RSA public key (PEM); ES256/ES384/ES512 → paste the EC public key (PEM). Asymmetric verification never requires the private key. Everything runs locally with the Web Crypto API — nothing is uploaded.

📖 What is a JWT (JSON Web Token)?

A JSON Web Token (JWT) is a compact, URL-safe token format defined by RFC 7519 used to transmit claims securely between two parties — typically between an authentication server and your application, or between a frontend and a backend API.

Unlike opaque session IDs that require a server-side lookup, a JWT is self-contained: all the information the server needs (who the user is, when the token expires, what the user is allowed to do) is embedded directly in the token itself. That makes JWTs the standard choice for stateless authentication in REST APIs, single-page applications, mobile apps, and microservices — you will meet them in OAuth 2.0, OpenID Connect, Firebase Auth, Auth0, AWS Cognito, and countless enterprise SSO setups.

A typical token looks like this:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

When you paste this token into the debugger above, you will see it split into its three parts instantly. The debugger is the fastest way to understand what any JWT actually contains — whether it is a token from your own login flow, a third-party API, or a sample in documentation.

🧩 The Three-Part Structure — Header, Payload, Signature

Every JWT is a dot-separated string with exactly three segments: header.payload.signature. Each segment is base64url-encoded (the URL-safe variant of base64, where + becomes - and / becomes _, and padding = is stripped).

1. Header

The header is a small JSON object that describes how the token was signed. It almost always contains:

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

2. Payload

The payload contains the claims — statements about the subject and metadata about the token. Claims come in three flavors:

Example: {"sub":"1234567890","name":"John Doe","iat":1516239022,"admin":true}

3. Signature

The signature is computed over the string base64url(header) + "." + base64url(payload) using the algorithm in the header and a key that only the token issuer knows (for HMAC) or the issuer's private key (for RSA/ECDSA). It is the security backbone of the JWT: if anyone edits the payload, the signature no longer matches and the token is rejected by any honest verifier.

Note that JWT is signed, not encrypted. The header and payload are only base64-encoded — anyone can read them without any key. Never put passwords, credit-card numbers, or other secrets inside a JWT payload. If you need confidentiality, use JWE (JSON Web Encryption) instead.

📋 Registered Claims Explained

The JWT spec reserves seven claim names. The debugger above highlights them in a table automatically whenever they are present, converting Unix timestamps into human-readable dates:

Claim Full Name What It Means
issIssuerWho created and signed the token (a URL or identifier, e.g. https://auth.example.com). Verifiers should check this matches their trusted issuer.
subSubjectThe principal the token is about — usually the user ID. Must be unique per issuer and never reused.
audAudienceWho the token is intended for (an API, a client ID, or an array of them). Recipients must verify they are in the audience.
expExpiration TimeUnix timestamp (seconds) after which the token is invalid. The most common claim to debug — see the expiry badge in the tool.
nbfNot BeforeUnix timestamp before which the token must NOT be accepted. Useful for tokens that only become valid at a scheduled time.
iatIssued AtUnix timestamp of when the token was issued. Lets servers estimate token age and rotate long-lived sessions.
jtiJWT IDA unique identifier per token, used to prevent replay attacks (the server remembers used jti values).

Unit gotcha: all JWT time claims are in seconds. JavaScript's Date.now() returns milliseconds — a classic bug is issuing a token with exp: Date.now() instead of Math.floor(Date.now()/1000), which makes the token look expired by decades. When debugging an "immediately expired" token, check the raw number first.

🔐 Signing Algorithms: HS256 vs RS256 vs ES256

The alg header decides both the cryptographic algorithm and which key model is used. There are two families:

HMAC — HS256 / HS384 / HS512 (symmetric)

RSA — RS256 / RS384 / RS512 (asymmetric)

ECDSA — ES256 / ES384 / ES512 (asymmetric, elliptic curve)

⚙️ How JWT Signature Verification Works

Verifying a JWT is a four-step process, and you can watch every step happen in the debugger above:

  1. Split the token into its three segments at the dots. A token with fewer or more than two dots is malformed.
  2. Read the alg claim from the decoded header. This tells you which key and algorithm to use. Reject tokens whose alg you did not expect (see the alg:none attack below).
  3. Recompute the signature locally over the exact byte string segment1 + "." + segment2 — with the shared secret (HMAC) or by verifying against the public key (RSA/ECDSA). This tool uses the browser's native Web Crypto API (crypto.subtle), the same primitives Node.js and browsers use.
  4. Compare the computed signature with segment 3. If they match, the token is authentic and unmodified; if not, the token was tampered with, signed with a different key, or corrupted in transit.

Signature validity is only half the story — a production verifier must also check the claims: exp not passed, nbf reached, iss matches your issuer, and aud includes your application. A token with a perfect signature can still be expired or targeted at a different service.

🔍 Common JWT Debugging Scenarios & Errors

1. "Token expired" immediately after login

Almost always a seconds-vs-milliseconds bug (Date.now() instead of Date.now()/1000) or a timezone/clock-skew issue on the server. Decode the token and look at the raw iat / exp values — if they are 13-digit numbers, they are milliseconds.

2. Signature verification fails with a valid-looking token

3. Payload decodes but shows gibberish

The payload segment is not valid JSON. Some tokens embed non-JSON payloads (rare, but permitted by the spec). If the base64url decodes to readable text that is not JSON, the token may use a custom serialization — most commonly you will still see valid JSON, so gibberish usually means a copy/paste error truncated the token.

4. "Invalid JWT format" — wrong number of parts

You pasted a token that is not a JWT (e.g. an OAuth opaque access token, a session cookie, or a SAML assertion), or the token got truncated. JWTs always have exactly two dots. Some systems prepend Bearer — strip that prefix first.

🛡️ JWT Security Pitfalls to Avoid

❓ Frequently Asked Questions

What is a JWT debugger?

A JWT debugger is a tool that decodes a JSON Web Token into its three readable parts — header, payload, and signature — and lets you inspect registered claims such as issuer, subject, audience, and expiration. Advanced debuggers (like this one) also verify the token signature so you can confirm a token is authentic and has not been tampered with.

Can I verify a JWT signature in the browser?

Yes. Paste the JWT plus your shared secret (for HS256/HS384/HS512) or your RSA/EC public key (for RS256/RS384/RS512/ES256) and the tool computes the signature locally using the Web Crypto API. You get a clear VALID or INVALID result without any data leaving your browser.

Is this JWT debugger really free and private?

Yes. There is no sign-up, no usage limit, and no server involved at all. Decoding and signature verification run 100% client-side with the Web Crypto API, so your token, secret, and keys never leave your device.

What does the three-part JWT structure mean?

A JWT looks like xxxxx.yyyyy.zzzzz. The first part is the base64url-encoded header (algorithm and token type), the second is the base64url-encoded payload (the claims), and the third is the signature computed over header.payload using the algorithm named in the header. The signature is what prevents someone from editing the payload without invalidating the token.

Why does my JWT show an EXPIRED badge even though it was just issued?

The exp claim is a Unix timestamp in seconds, not milliseconds. If a token was created with exp in milliseconds (a common mistake), it appears expired decades early. Check the raw claim value — this tool shows both the human-readable date and the raw timestamp so you can spot unit mismatches instantly.

Does the tool support HS256, RS256, and ES256 verification?

Yes. HS256, HS384, and HS512 are verified with a shared secret. RS256, RS384, and RS512 are verified with an RSA public key in PEM format, and ES256/ES384/ES512 with an EC public key in PEM format. For asymmetric algorithms you never need the private key — verification only requires the public key.

Can I decode a JWT that has no signature or an "alg: none" header?

This tool will still decode the header and payload of any three-part token, but if the algorithm is none or the signature is empty the verification step will report INVALID. Accepting unsigned or alg:none tokens is a serious security vulnerability, so a good debugger always flags them.