How to Decode a JWT Token: Header, Payload & Signature Explained

JWT (JSON Web Token) is the standard for authentication tokens in modern APIs. Understanding how to decode one — and what each part means — is an essential skill for any developer working with web services.

What is a JWT?

A JSON Web Token is a compact, URL-safe way to represent claims between two parties. In practice, you get a JWT from a login API, then send it in every subsequent request as proof of your identity. The server validates the token without needing to look up a session in a database.

A JWT looks like three Base64url-encoded strings separated by dots:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

The three parts are: Header · Payload · Signature

Part 1: The Header

The header is a Base64url-encoded JSON object describing the token type and the signing algorithm used. Decode the first segment and you get:

json
{
  "alg": "HS256",   // signing algorithm: HMAC-SHA256
  "typ": "JWT"      // token type
}

Common algorithm values include HS256 (HMAC with SHA-256), RS256 (RSA with SHA-256), and ES256 (ECDSA). The algorithm tells the recipient how to verify the signature.

Part 2: The Payload

The payload contains the "claims" — statements about the user and any additional metadata. Decode the second segment:

json
{
  "sub": "1234567890",   // subject (user ID)
  "name": "John Doe",    // custom claim
  "iat": 1516239022,     // issued at (Unix timestamp)
  "exp": 1516242622,     // expiration (Unix timestamp)
  "role": "admin"        // custom claim
}

Standard registered claims include:

  • sub — Subject: identifies the user (usually a user ID)
  • iat — Issued At: when the token was created (Unix timestamp)
  • exp — Expiration: when the token expires — after this time, reject it
  • nbf — Not Before: the token is not valid before this time
  • iss — Issuer: who issued the token (e.g., "auth.myapp.com")
  • aud — Audience: intended recipient of the token

Part 3: The Signature

The signature verifies the token hasn't been tampered with. It's created by taking the encoded header, a dot, the encoded payload, signing that with a secret key using the specified algorithm, then Base64url-encoding the result.

pseudocode
signature = HMACSHA256(
  base64url(header) + "." + base64url(payload),
  secret_key
)
Important: You can decode the header and payload without the secret key — they are just Base64url, not encrypted. But you cannot verify the signature without the key. Anyone can read a JWT; only the server can verify it is authentic.

How to check if a JWT is expired

The exp claim is a Unix timestamp (seconds since Jan 1, 1970). To check expiry in JavaScript:

javascript
function isExpired(token) {
  const payload = JSON.parse(atob(token.split('.')[1]));
  if (!payload.exp) return false; // no expiry set
  return Date.now() / 1000 > payload.exp;
}

// Usage
if (isExpired(myToken)) {
  // redirect to login
}

Manually decoding a JWT in the browser console

javascript
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U";

const [header, payload, sig] = token.split('.');

// Decode header
JSON.parse(atob(header));
// { alg: "HS256", typ: "JWT" }

// Decode payload
JSON.parse(atob(payload));
// { sub: "1234567890" }

Note: atob() works for standard Base64. For Base64url (which JWT uses), you may need to replace - with + and _ with / before decoding.

Paste any JWT token to instantly see the decoded header, payload, and expiration status.

Open JWT Decoder →
← Previous
What is Base64 Encoding?
Next →
Unix Timestamps Explained