How to Decode JWT Tokens Using Base64 in JavaScript

JSON Web Tokens (JWTs) are widely used for authentication and information exchange. While verifying a JWT requires the secret or public key, decoding its contents to read the payload is straightforward — the header and payload are simply Base64Url-encoded JSON. This is useful for debugging, logging, and extracting claims on the client side.

JWT structure

A JWT is three dot-separated Base64Url-encoded strings:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9    ← header
.
eyJ1c2VySWQiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ  ← payload
.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c  ← signature

Decoding the payload in the browser

function decodeJwt(token) {
  const parts = token.split('.');
  if (parts.length !== 3) throw new Error('Invalid JWT format');

  function base64UrlDecode(str) {
    // Pad and normalise URL-safe chars
    const base64 = str.replace(/-/g, '+').replace(/_/g, '/');
    const padded = base64.padEnd(base64.length + (4 - base64.length % 4) % 4, '=');
    const binary = atob(padded);
    const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
    return JSON.parse(new TextDecoder().decode(bytes));
  }

  return {
    header:  base64UrlDecode(parts[0]),
    payload: base64UrlDecode(parts[1]),
    // signature is binary — we just note it exists
    signature: parts[2],
  };
}

// Usage
const { header, payload } = decodeJwt(token);
console.log(payload.userId);  // "123"
console.log(payload.role);    // "admin"
console.log(payload.exp);     // expiry timestamp (Unix seconds)

Decoding in Node.js

function decodeJwtNode(token) {
  const parts = token.split('.');
  if (parts.length !== 3) throw new Error('Invalid JWT');

  const decode = (str) => {
    const base64 = str.replace(/-/g, '+').replace(/_/g, '/');
    return JSON.parse(Buffer.from(base64, 'base64').toString('utf8'));
  };

  return { header: decode(parts[0]), payload: decode(parts[1]) };
}

const { payload } = decodeJwtNode(token);
console.log(payload);

Reading the expiry time

const { payload } = decodeJwt(token);

if (payload.exp) {
  const expiresAt = new Date(payload.exp * 1000); // exp is Unix seconds
  const isExpired = Date.now() > payload.exp * 1000;
  console.log('Expires:', expiresAt.toLocaleString());
  console.log('Expired:', isExpired);
}

Important security note

Decoding a JWT reads the contents but does NOT verify the signature. Never trust the claims in a JWT payload on the server without verifying the signature using your secret key or the issuer's public key. Use libraries like jsonwebtoken (Node.js) or jose for proper verification.

  • Client-side decoding is fine for displaying the username or reading the expiry to auto-refresh tokens.
  • Server-side, always use jwt.verify() — never jwt.decode() alone for access control decisions.

Decode Base64 strings instantly

You can paste any Base64Url-encoded JWT section directly into our Base64 Encoder / Decoder to read the raw JSON — useful for quick debugging without writing any code.