Skip to main contentSkip to navigationSkip to searchSkip to footer

How to Decode a JWT Token: Complete Guide (Without Code) 2026

Learn how to decode JWT tokens to inspect claims, debug authentication, and understand the header, payload, and signature structure. Free online JWT decoder. No code needed.

NextUtils Team
9 min read
πŸ“šTutorials
jwtauthenticationsecurityweb-developmentapi
Security and authentication tools experts

If you've worked with modern web authentication, you've encountered a JWT (JSON Web Token) β€” that long string of characters starting with eyJ... sitting in your browser's localStorage or Authorization header. Decoding a JWT is essential for debugging authentication issues, inspecting user claims, checking expiration, and understanding what your auth server is actually returning. The good news: the first two parts of a JWT are just Base64-encoded JSON β€” no cryptography required to read them.

Important Security Warning

Never paste production JWTs with sensitive claims into untrusted third-party websites. While decoding only reads the payload (it doesn't need the secret key), the token itself grants access to your system if it's still valid. Our decoder runs entirely in your browser β€” nothing is sent to any server β€” making it safe for inspecting real tokens.

What Is a JWT?

A JSON Web Token (JWT, pronounced β€œjot”) is a compact, URL-safe way to represent claims between two parties. Defined in RFC 7519, JWTs are used primarily for:

Authentication

After login, the server issues a JWT. The client sends it with each request to prove identity.

Authorization

The JWT payload contains claims like roles and permissions the server trusts without a DB lookup.

Information Exchange

Microservices pass signed JWTs to share verified user data without re-querying the auth service.

JWT Structure: 3 Parts Separated by Dots

A JWT always has the format xxxxx.yyyyy.zzzzz β€” three Base64URL-encoded segments separated by periods:

Example JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

β–ˆ Headerβ–ˆ Payloadβ–ˆ Signature
1Header β€” Algorithm & Token Type
{
  "alg": "HS256",   // Signing algorithm: HS256, RS256, ES256...
  "typ": "JWT"      // Token type (always "JWT")
}

The header is Base64URL-encoded but not encrypted. alg is critical β€” it tells the receiver which algorithm was used to sign the token. Never set alg to β€œnone” β€” this disables signature verification and is a severe security vulnerability.

2Payload β€” Claims (The Data)
{
  "sub": "1234567890",     // Subject (user ID)
  "name": "John Doe",      // Custom claim
  "email": "john@example.com",
  "roles": ["admin", "user"],
  "iat": 1516239022,       // Issued At (Unix timestamp)
  "exp": 1516325422,       // Expiration (Unix timestamp)
  "nbf": 1516239022        // Not Before (optional)
}

The payload contains claims β€” statements about the user plus metadata. Standard claims include sub (subject), iat (issued at), exp (expiration), and iss (issuer). Custom claims like roles and email are added by your auth server. The payload is Base64-encoded, not encrypted β€” anyone with the token can read it.

3Signature β€” Tamper Protection
HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret_key  // Only the server knows this
)

The signature verifies that the token hasn't been tampered with. It requires the secret key (or private key for RSA/ECDSA). You cannot forge a valid JWT without the key. Decoding the payload does NOT require the signature β€” but trusting the payload absolutely requires verifying it on the server.

✨ Decode Any JWT Instantly β€” 100% Client-Side

Paste your JWT and instantly see the decoded header, payload, and expiration details. Token never leaves your browser β€” no server calls, no logging.

Open JWT Decoder β†’

How to Decode a JWT (3 Methods)

Method 1: Online Decoder (No Code)

  1. Copy your JWT token (from your browser DevTools, Postman, or auth logs)
  2. Open the JWT Decoder
  3. Paste the token into the input field
  4. The header and payload are immediately shown as formatted JSON
  5. Check expiration: the tool converts exp Unix timestamp to a human-readable date

Method 2: JavaScript (Browser / Node.js)

// Decode JWT payload without verifying signature
// ONLY use this for debugging β€” never for auth decisions
function decodeJwt(token) {
  const parts = token.split('.');
  if (parts.length !== 3) throw new Error('Invalid JWT format');

  // Base64URL β†’ Base64 β†’ JSON
  const decode = (str) => {
    const base64 = str.replace(/-/g, '+').replace(/_/g, '/');
    const json = atob(base64.padEnd(base64.length + (4 - base64.length % 4) % 4, '='));
    return JSON.parse(json);
  };

  return {
    header: decode(parts[0]),
    payload: decode(parts[1]),
    // Signature is binary β€” not decoded here
  };
}

const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U";
const { header, payload } = decodeJwt(token);
console.log(header);   // { alg: 'HS256', typ: 'JWT' }
console.log(payload);  // { sub: '1234567890' }

// Check if expired
if (payload.exp && Date.now() / 1000 > payload.exp) {
  console.log('Token expired at:', new Date(payload.exp * 1000));
}

Method 3: Python

import base64, json
from datetime import datetime

def decode_jwt(token: str) -> dict:
    """Decode JWT payload without signature verification (debug only)."""
    parts = token.split('.')
    if len(parts) != 3:
        raise ValueError("Invalid JWT format")

    def decode_part(part):
        # Add padding, convert Base64URL to Base64
        padding = 4 - len(part) % 4
        padded = part + '=' * (padding % 4)
        padded = padded.replace('-', '+').replace('_', '/')
        return json.loads(base64.b64decode(padded))

    header = decode_part(parts[0])
    payload = decode_part(parts[1])

    # Convert timestamps to human-readable
    if 'exp' in payload:
        payload['_exp_human'] = datetime.fromtimestamp(payload['exp']).isoformat()
    if 'iat' in payload:
        payload['_iat_human'] = datetime.fromtimestamp(payload['iat']).isoformat()

    return {'header': header, 'payload': payload}

# Or use the pyjwt library for full verification:
# pip install pyjwt
# import jwt
# payload = jwt.decode(token, secret, algorithms=["HS256"])

Standard JWT Claims Reference

ClaimNameDescriptionFormat
subSubjectUnique identifier of the user (user ID)String
issIssuerWho created the token (e.g., "auth.example.com")String / URI
audAudienceWho the token is intended for (API or app)String or Array
expExpirationToken expires at this time β€” reject afterUnix timestamp
iatIssued AtWhen the token was createdUnix timestamp
nbfNot BeforeToken is invalid before this timeUnix timestamp
jtiJWT IDUnique ID to prevent token replay attacksString (UUID)
nameNameUser's full name (custom/OIDC claim)String
emailEmailUser's email address (custom/OIDC claim)String
rolesRolesUser permissions/roles (custom claim)Array of strings

JWT Security: What Developers Get Wrong

Storing JWTs in localStorageRisk: High

localStorage is accessible to any JavaScript on the page β€” including XSS-injected scripts. Prefer HttpOnly cookies for storage, which JavaScript cannot access.

Not validating expiration (exp)Risk: High

A decoded JWT is not the same as a verified JWT. Always check exp on the server before trusting claims.

Trusting algorithm from the headerRisk: Critical

The alg=none attack: an attacker removes the signature and sets alg to "none". Always hardcode the expected algorithm server-side; never read it from the token.

Storing sensitive data in the payloadRisk: Medium

The payload is Base64-encoded, not encrypted. Anyone with the token can read it. Never store passwords, credit cards, or PII in JWT claims.

Frequently Asked Questions

Can I verify the JWT signature online?

For HS256 (shared secret) tokens, you can verify if you know the secret key. Our decoder focuses on decoding the payload (which requires no key) rather than verification, since the secret should never be shared with client-side tools. For RS256/ES256 (public/private key), signature verification requires only the public key.

What is the difference between a JWT and a session token?

A session token is an opaque random string; the server stores session data and looks it up on each request (stateful). A JWT contains the data itself, signed by the server β€” the receiver can validate and read claims without a DB lookup (stateless). JWTs are better for microservices and APIs; sessions are simpler for traditional web apps.

Why does my JWT start with eyJ?

All JWTs start with eyJ because the header always starts with {"alg", and {"a in Base64URL encoding is eyJh. It's a predictable pattern, not a security issue β€” the header contents are intentionally readable.

Share this article

Related Articles

Continue exploring with these related posts

Ready to try our tools?

Explore our collection of free online tools for developers, designers, and power users.

Explore All Tools

Explore More Tools

Discover our collection of free online tools for developers, designers, and power users