JWT Decoder

Decode a JWT Token: See Header, Payload & Claims

Decode a sample JWT to see the header, payload claims (sub, iss, exp, iat), and signature. Covers JWT structure, Base64url encoding, and security gotchas.

100% client-side. Your data never leaves your browser.

Related Tools

Decoded Header

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

Decoded Payload

{
  "sub": "1234567890",
  "name": "John Doe",
  "email": "john@example.com",
  "role": "admin",
  "iat": 1516239022,
  "exp": 1735689600
}

Signature

TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

The signature cannot be decoded. It is the output of an HMAC-SHA256 operation, not encoded data. To verify it, you need the secret key that was used when the token was issued.

The Three Part JWT Structure

A JWT is three Base64url encoded segments joined by dots:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0
.
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

The structure is defined in RFC 7519 and RFC 7515. Each part serves a distinct purpose:

The header specifies the token type and the signing algorithm. alg tells the verifier which algorithm was used to compute the signature. typ is always JWT for standard tokens. Some tokens also include kid (key ID) to indicate which specific key was used, which matters when an auth server rotates keys.

Payload

The payload contains the claims: statements about the subject and additional metadata. Standard registered claims have short names (sub, iss, exp) to keep tokens compact. Custom claims can be anything your application needs, though the JWT specification recommends using a namespaced format (e.g., https://myapp.com/role) for custom claims to avoid collisions.

Signature

The signature is computed over base64url(header) + "." + base64url(payload) using the algorithm specified in the header. For HS256, this is HMAC-SHA256(secret, data). For RS256, it is RSA-SHA256(privateKey, data). The verifier recomputes the signature from the received header and payload and compares it to the third segment. If they do not match, the token has been tampered with.

Base64url Encoding

JWTs use Base64url, a URL safe variant of Base64. It replaces + with - and / with _, and omits the = padding characters. This makes JWT tokens safe to include in URL query parameters and HTTP headers without percent encoding.

Standard Base64 would require = padding characters and might include + or /, both of which have special meaning in URLs. Base64url avoids all of these by using only characters that need no escaping in URLs.

To manually decode the payload segment:

# The payload segment (middle part, between the two dots)
PAYLOAD="eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0"

# Add padding and decode (macOS/Linux)
python3 -c "
import base64, json, sys
s = sys.argv[1]
pad = s + '=' * (4 - len(s) % 4)
decoded = base64.urlsafe_b64decode(pad)
print(json.dumps(json.loads(decoded), indent=2))
" "$PAYLOAD"

Standard Claims Explained

ClaimNameTypeDescription
subSubjectstringWho the token is about. Typically a user ID.
issIssuerstringWho issued the token. Usually a URL (https://auth.example.com).
expExpirationtimestampUnix timestamp. Token must be rejected after this time.
iatIssued AttimestampUnix timestamp. When the token was created.
audAudiencestring/arrayWho the token is for. The API must verify it is listed.
nbfNot BeforetimestampUnix timestamp. Token must not be accepted before this time.
jtiJWT IDstringA unique identifier for this token. Used to prevent replay.

Not all claims are required. exp and sub are the most commonly used. The aud claim matters for services that share an auth server. Without it, a token intended for service A could be used against service B.

Decoding Does Not Mean Trusting

This is the most important thing to understand about JWT decoders. Decoding a token reveals the claims inside it. It does not tell you whether those claims are true or whether the token is legitimate.

An attacker can construct any JWT they want by hand. Without signature verification, there is no way to distinguish a genuine token from a forged one. This matters because:

  1. The alg: none attack. Some older JWT libraries accepted tokens with "alg": "none" in the header and no signature, treating them as valid. Never accept unsigned tokens.

  2. Algorithm confusion attacks. If your server uses RS256 (asymmetric), an attacker might send a token with "alg": "HS256" in the header, using your public key as the HMAC secret. Libraries with poor algorithm enforcement would verify it successfully. Always specify the expected algorithm explicitly.

  3. Expired tokens. Decoding reveals the exp claim, but you still need to check whether the current time has passed it.

In production, always use a well maintained JWT library that handles verification, algorithm pinning, and expiration checking. Never implement JWT verification yourself.

Where JWTs Are Used

OAuth 2.0 / OpenID Connect

Access tokens and ID tokens in OAuth flows are frequently JWTs. The ID token in OIDC is always a JWT. Access tokens may or may not be JWTs depending on the authorization server.

API authentication

A server issues a JWT when a user logs in. The client sends it in the Authorization: Bearer <token> header with subsequent requests. The server verifies the signature and reads the claims to identify the user and check permissions.

Stateless session data

Some applications encode session state (user ID, role, preferences) in the JWT payload to avoid a database lookup on every request. The tradeoff: tokens cannot be revoked before expiration without additional infrastructure (a denylist or short expiry + refresh tokens).

Service to service authentication

Internal microservices use JWTs to authenticate calls to each other, often with short expiry times (minutes rather than hours).

Debugging JWT Issues

When a JWT authenticated request fails, a decoder is the first tool to reach for:

Signature failures require the actual secret or public key to diagnose. A decoder cannot tell you why a signature is wrong, only what algorithm was supposedly used to create it.