How to Decode JWT Tokens: Complete Guide with Examples

April 4, 2026 ยท 10 min read ยท Updated for 2026

๐Ÿ“‹ Table of Contents

What is a JWT Token?

A JSON Web Token (JWT) is a compact, URL-safe way to represent claims between two parties. JWTs are commonly used for authentication and authorization in web applications. When you log in to a website, the server often returns a JWT that your browser includes in subsequent requests.

JWTs are defined in RFC 7519 and are widely used in OAuth 2.0, OpenID Connect, and API authentication.

JWT Structure: Header, Payload, Signature

Every JWT consists of three parts separated by dots (.):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

1. Header (JOSE Header)

The header typically contains two fields:

{
  "alg": "HS256",   // Signing algorithm
  "typ": "JWT"      // Token type
}

Common algorithms include HS256 (HMAC-SHA256), RS256 (RSA-SHA256), and ES256 (ECDSA-SHA256).

2. Payload (Claims)

The payload contains the claims โ€” statements about the user and metadata:

{
  "sub": "1234567890",   // Subject (user ID)
  "name": "John Doe",    // Custom claim
  "iat": 1516239022      // Issued at (Unix timestamp)
}

3. Signature

The signature verifies the token hasn't been tampered with. For HS256:

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

Important: The header and payload are only Base64URL-encoded, NOT encrypted. Anyone can decode and read them. The signature only ensures integrity, not confidentiality.

How to Decode a JWT Manually

Since JWT parts are Base64URL-encoded, you can decode them with any Base64 decoder:

  1. Split the token by dots (.) into three parts
  2. Replace - with + and _ with /
  3. Add padding (=) if needed to make length a multiple of 4
  4. Base64-decode each part

In a terminal:

# Decode the header
echo 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9' | base64 -d
# Output: {"alg":"HS256","typ":"JWT"}

# Decode the payload
echo 'eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ==' | base64 -d
# Output: {"sub":"1234567890","name":"John Doe","iat":1516239022}

Decoding JWTs in JavaScript

In the browser or Node.js:

function decodeJWT(token) {
  const parts = token.split('.');
  if (parts.length !== 3) throw new Error('Invalid JWT');
  
  const header = JSON.parse(atob(parts[0]
    .replace(/-/g, '+').replace(/_/g, '/')));
  const payload = JSON.parse(atob(parts[1]
    .replace(/-/g, '+').replace(/_/g, '/')));
  
  return { header, payload, signature: parts[2] };
}

// Usage
const token = 'eyJhbGciOiJIUzI1NiIs...';
const { header, payload } = decodeJWT(token);
console.log(payload.sub);  // "1234567890"
console.log(payload.name); // "John Doe"

With the jose library for full verification:

import * as jose from 'jose';

const secret = new TextEncoder().encode('your-secret');
const { payload } = await jose.jwtVerify(token, secret);
console.log(payload); // Verified payload

Decoding JWTs in Python

import jwt  # pip install PyJWT

# Decode without verification (for inspection)
payload = jwt.decode(token, options={"verify_signature": False})
print(payload)

# Decode WITH verification
payload = jwt.decode(token, "your-secret", algorithms=["HS256"])
print(payload["sub"])  # "1234567890"

For RS256 tokens (common in OAuth):

import jwt
import requests

# Fetch the public key from JWKS endpoint
jwks = requests.get("https://example.com/.well-known/jwks.json").json()
public_key = jwt.algorithms.RSAAlgorithm.from_jwk(jwks["keys"][0])

payload = jwt.decode(token, public_key, algorithms=["RS256"],
                     audience="your-audience")

Common JWT Claims Explained

The JWT spec defines several registered claims:

Applications also add custom claims like name, email, role, permissions, etc.

JWT Security Best Practices

  1. Always verify the signature โ€” Never trust a JWT without verification
  2. Check expiration โ€” Always validate exp and nbf claims
  3. Use strong secrets โ€” For HS256, use at least 256-bit random secrets
  4. Prefer RS256 over HS256 for public-facing APIs โ€” asymmetric keys are safer
  5. Don't store sensitive data in the payload โ€” it's readable by anyone
  6. Set short expiration times โ€” Use refresh tokens for long sessions
  7. Validate the iss and aud claims โ€” Prevent token confusion attacks
  8. Use HTTPS โ€” Always transmit JWTs over encrypted connections

Try our free JWT Decoder tool โ€” decode any JWT token instantly in your browser

Open JWT Decoder โ†’

Online JWT Decoder Tools

If you need to quickly inspect a JWT token, use our free JWT Decoder. It runs entirely in your browser โ€” no data is sent to any server. Features:

For more developer tools, check out our complete tools collection with 40+ free browser-based utilities.

\xF0\x9F\x92\x99 Tip\xF0\x9F\x93\x9A Get Bundle \x244.99