JWT Decoder

Free online JWT decoder — paste any JSON Web Token, bearer token, or access token to instantly decode the header, payload and claims. Inspect standard JWT claims (exp, iat, iss, sub), check token expiry, and decode JWT online free. Runs entirely in your browser — tokens never leave your device.

Timestamp display

Load example

JWT structure

Header — alg, typ, kid
Payload — claims, data
Signature — verification hash

Runs in your browser

Tokens are decoded locally in JavaScript and never sent to any server. Do not paste production tokens if they contain sensitive personal data.

Bearer prefix stripped — decoding token only.

Token

Header

Payload

Signature

The signature is a base64url-encoded cryptographic hash of the header and payload. Verification requires the secret key (HS256) or public key (RS256/ES256). This tool decodes only — use a library like jsonwebtoken, PyJWT, or firebase/php-jwt to verify signatures in production.

What is a JWT token?

A JWT (JSON Web Token) is an open standard (RFC 7519) for securely transmitting information between parties as a compact, URL-safe JSON object. JWTs are digitally signed — using HMAC-SHA256 (HS256) or RSA/ECDSA (RS256, ES256) — so the recipient can verify the token's authenticity and confirm it has not been tampered with.

JWTs are everywhere in modern authentication and authorization systems:

  • API authentication — After login, the server issues a JWT. The client sends it in the Authorization: Bearer <token> header of subsequent API requests.
  • Single Sign-On (SSO) — One JWT from an identity provider (Auth0, Okta, Google) grants access across multiple services without re-authentication.
  • Stateless REST APIs — No server-side session storage needed. The JWT carries all the information the server needs, reducing database lookups.
  • OAuth 2.0 access tokens — Bearer tokens in OAuth 2.0 flows are typically JWTs issued by the authorization server.

Because a JWT is self-contained and signed, any server that holds the verification key can validate it without calling a central session store — making JWTs ideal for distributed systems and microservices.

The three parts of a JWT: header, payload, signature

A JWT is three base64url-encoded JSON objects joined by dots: header.payload.signature. The encoding is URL-safe (uses - and _ instead of + and /, and padding = is omitted).

Header

Specifies the token type and the signing algorithm. The most common fields are:

  • alg — Algorithm: HS256 (HMAC-SHA256, symmetric), RS256 (RSA-SHA256, asymmetric), ES256 (ECDSA, asymmetric)
  • typ — Token type, almost always JWT
  • kid — Key ID: used to select which key to use when multiple keys are in rotation

Payload

Contains the claims — statements about the subject and additional metadata. Claims can be registered (standardised in RFC 7519), public (registered with IANA), or private (custom to your application).

{"sub":"user_123","name":"Alice","iat":1735689600,"exp":1735776000,"roles":["admin"]}

Signature

Computed as HMAC-SHA256(base64url(header) + "." + base64url(payload), secret) for HS256, or the equivalent RSA/ECDSA operation for RS256/ES256. Any change to the header or payload invalidates the signature, making tampering detectable.

This JWT decoder visualises each part in its conventional colour and decodes the header and payload. Signature verification is not possible without the private key or secret.

JWT claims explained

JWT claims are key-value pairs in the payload. RFC 7519 defines seven registered claims that carry standard meanings recognised by all JWT libraries:

Claim Name Description
issIssuerWho issued the token, e.g. https://accounts.google.com
subSubjectThe principal the token represents, typically a user ID
audAudienceThe intended recipient(s) — your API should reject tokens not addressed to it
expExpiration TimeUnix timestamp after which the token must not be accepted
nbfNot BeforeUnix timestamp before which the token is not valid
iatIssued AtUnix timestamp when the token was issued — useful for calculating token age
jtiJWT IDUnique identifier for this token, used to prevent replay attacks

Beyond these, tokens commonly include public claims registered with IANA (like email, name) and private claims specific to your application (like roles, permissions, tenant_id). This decoder highlights the seven registered claims and shows human-readable timestamps for exp, iat, and nbf.

How to decode a JWT in JavaScript, Python, and PHP

Decoding a JWT only requires base64url-decoding the header and payload — no secret key needed. Here are minimal implementations in three languages. These decode the token; they do not verify the signature. Always verify signatures in production using a trusted library.

JavaScript — Browser

function decodeJWT(token) {
  const [headerB64, payloadB64] = token.split('.');

  function base64urlDecode(str) {
    const b64 = str.replace(/-/g, '+').replace(/_/g, '/');
    const padded = b64.padEnd(b64.length + (4 - b64.length % 4) % 4, '=');
    return JSON.parse(atob(padded));
  }

  return {
    header:  base64urlDecode(headerB64),
    payload: base64urlDecode(payloadB64),
  };
}

const { header, payload } = decodeJWT('eyJhbGci...');
console.log(payload.sub);                   // Subject claim
console.log(new Date(payload.exp * 1000));  // Expiry as Date

JavaScript — Node.js 16+

// Node.js 16+ supports 'base64url' encoding natively via Buffer
const parts   = token.split('.');
const header  = JSON.parse(Buffer.from(parts[0], 'base64url').toString());
const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString());
console.log(payload.exp);  // Expiry Unix timestamp

// Decode-only library — jwt-decode (100M+ weekly downloads, browser + Node.js):
// import { jwtDecode } from 'jwt-decode';
// const payload = jwtDecode(token);

// To VERIFY the signature in production, use jsonwebtoken:
// const jwt = require('jsonwebtoken');
// const verified = jwt.verify(token, process.env.JWT_SECRET);

Python

import base64, json

def decode_jwt(token: str) -> dict:
    """Decode a JWT without signature verification."""
    header_b64, payload_b64, _ = token.split('.')

    def b64url_decode(s: str):
        s += '=' * (-len(s) % 4)  # restore padding
        return json.loads(base64.urlsafe_b64decode(s))

    return {'header': b64url_decode(header_b64), 'payload': b64url_decode(payload_b64)}

# Usage
decoded = decode_jwt('eyJhbGci...')
print(decoded['payload']['sub'])   # Subject
print(decoded['payload'].get('exp'))  # Expiry Unix timestamp

# To also VERIFY the signature, use PyJWT (pip install PyJWT):
# import jwt
# payload = jwt.decode(token, key, algorithms=['HS256'])
# For decode-only without verification:
# payload = jwt.decode(token, options={'verify_signature': False}, algorithms=['HS256'])

PHP

function decodeJWT(string $token): array {
    [$headerB64, $payloadB64] = explode('.', $token);

    $decode = function (string $b64url): array {
        $b64    = strtr($b64url, '-_', '+/');
        $padded = str_pad($b64, strlen($b64) + (4 - strlen($b64) % 4) % 4, '=');
        return json_decode(base64_decode($padded), true);
    };

    return ['header' => $decode($headerB64), 'payload' => $decode($payloadB64)];
}

// Usage
$decoded = decodeJWT($token);
echo $decoded['payload']['sub'];
echo date('c', $decoded['payload']['exp']); // ISO 8601 expiry

// To VERIFY signatures in production, use firebase/php-jwt (composer require firebase/php-jwt):
// use Firebase\JWT\JWT; use Firebase\JWT\Key;
// $decoded = JWT::decode($token, new Key($secret, 'HS256'));

Working with hex-encoded binary data alongside JWTs? Try our hex decoder to convert hexadecimal strings to readable text.

JWT security best practices

JWTs are powerful but misused ones create serious vulnerabilities. Key guidelines:

  • Never store sensitive data in the payload. The payload is base64-encoded, not encrypted — anyone with the token can decode it instantly (as this tool demonstrates). Keep secrets, passwords, and PII out of JWTs.
  • Always verify the signature server-side. Never trust a decoded JWT payload without first verifying the signature. Use a well-tested library rather than rolling your own verification.
  • Set short expiry times (exp). A stolen JWT is valid until it expires. Access tokens should expire in minutes (15m is common); use refresh tokens for long-lived sessions.
  • Validate iss and aud claims. Ensure the token was issued by the expected authority and is intended for your service. Ignoring these allows confused deputy attacks.
  • Prefer RS256 over HS256 for public-facing APIs. RS256 uses an asymmetric key pair — the private key signs, the public key verifies. This means you can distribute the public key widely without compromising signing ability.
  • Transmit over HTTPS only. JWTs in transit over plain HTTP can be intercepted and replayed.
  • Consider token revocation. JWTs are stateless and cannot be invalidated before expiry without a blocklist. For sensitive operations, maintain a revocation list or use opaque tokens.

Frequently asked questions

A JWT (JSON Web Token) is an open standard (RFC 7519) for securely transmitting information between parties as a digitally signed, compact JSON object. It is widely used for API authentication — after a successful login, the server issues a JWT which the client sends with each request in the Authorization header. Because the token is self-contained and signed, servers can verify it without a database lookup.
Yes — the JWT header and payload are base64url-encoded, not encrypted. Anyone with the token string can decode them without any key. The secret key (HS256) or private key (RS256/ES256) is only required to verify the signature — confirming the token was issued by a trusted party and has not been modified. This tool decodes without any key. Important: never store sensitive data in the payload because it is readable by anyone who holds the token.
This decoder runs entirely in your browser — tokens are never sent to any server. The base64url decoding is performed locally in JavaScript on your device. That said, avoid pasting real production tokens that contain sensitive user data (email, PII, session credentials) into any online tool. For live environments, use a local library or CLI instead.
The exp claim (Expiration Time) specifies when the token expires. Its value is a NumericDate — the number of seconds elapsed since January 1 1970 UTC (Unix timestamp). For example, exp: 1735776000 means the token expired on January 2 2025 at 00:00:00 UTC. This decoder shows exp as a human-readable date and flags expired tokens with a red badge.
Split the token on ., take the payload part, replace - with + and _ with / (base64url → base64), add padding, then use atob() and JSON.parse(). This decodes the claims but does not verify the signature. In production, use jsonwebtoken (jwt.verify()) to both decode and verify.
A bearer token is an access token sent in the HTTP header as Authorization: Bearer <token>. "Bearer" means that anyone who holds the token can use it — no additional proof of identity is required. JWTs are the most common format for bearer tokens in REST APIs and OAuth 2.0 flows. This decoder automatically strips the Bearer prefix when you paste a full Authorization header value.

In Node.js 16+ you can decode the payload natively with Buffer.from:

const payload = JSON.parse(Buffer.from(token.split('.')[1], 'base64url').toString());

For a lightweight decode-only library, use jwt-decode (100M+ weekly npm downloads): import { jwtDecode } from 'jwt-decode'; const payload = jwtDecode(token);

To also verify the signature, use jsonwebtoken: jwt.verify(token, secret). Decoding and verifying are different — always verify in production.

JWTs have real limitations worth knowing: (1) Hard to revoke — a stateless JWT cannot be invalidated before its exp without a server-side blocklist; if a user logs out or is banned, the token stays valid until expiry. (2) Sensitive data is visible — the payload is only base64-encoded, not encrypted; anyone who holds the token can decode it (as this tool shows). (3) Algorithm confusion attacks — accepting multiple algorithms can allow attackers to forge tokens. (4) Token size — JWTs are larger than opaque session IDs, adding overhead to every request. For apps that need instant session revocation, traditional server-side sessions may be safer. JWTs shine in stateless REST APIs and distributed systems.