JWT Payload Explained

Everything you need to know about the JWT payload — the second part of every JSON Web Token

1. What Is the JWT Payload?

The payload is the second part of a JSON Web Token, sitting between the header and the signature. It contains the claims — the actual data the token carries. When people talk about "what's in the JWT," they're usually referring to the payload.

A JWT has three parts separated by dots:

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NSIsIm5hbWUiOiJBbGljZSJ9.signature
HeaderPayloadSignature

The green part is the payload — a Base64URL-encoded JSON object. Decoding it reveals the claims inside.

2. Payload Structure & Encoding

The payload is a plain JSON object that gets Base64URL-encoded. This encoding makes it URL-safe but does not encrypt it — anyone with the token can decode and read the payload.

Original JSON:

{
  "sub": "user_12345",
  "name": "Alice Johnson",
  "role": "editor",
  "iat": 1735686000,
  "exp": 1735689600
}

Base64URL-encoded:

eyJzdWIiOiJ1c2VyXzEyMzQ1IiwibmFtZSI6IkFsaWNlIEpvaG5zb24iLCJyb2xlIjoiZWRpdG9yIiwiaWF0IjoxNzM1Njg2MDAwLCJleHAiOjE3MzU2ODk2MDB9

Base64URL vs Base64: JWT uses Base64URL encoding, which replaces + with -,/ with _, and removes padding = characters. This makes the token safe for use in URLs, cookies, and HTTP headers.

3. Real-World Payload Examples

Authentication Token

{
  "sub": "user_12345",
  "email": "alice@example.com",
  "role": "admin",
  "iss": "https://auth.example.com",
  "aud": "https://api.example.com",
  "iat": 1735686000,
  "exp": 1735689600
}

OAuth 2.0 Access Token

{
  "sub": "client_app_456",
  "scope": "read:users write:posts",
  "client_id": "mobile_app_v2",
  "iss": "https://oauth.example.com",
  "exp": 1735689600,
  "jti": "unique-token-id-789"
}

OpenID Connect ID Token

{
  "sub": "user_12345",
  "name": "Alice Johnson",
  "email": "alice@example.com",
  "email_verified": true,
  "picture": "https://example.com/alice.jpg",
  "iss": "https://accounts.google.com",
  "aud": "your-client-id.apps.googleusercontent.com",
  "iat": 1735686000,
  "exp": 1735689600,
  "nonce": "abc123"
}

4. Payload vs Header

Both are JSON objects, but they serve different purposes:

AspectHeaderPayload
PurposeMetadata about the tokenThe actual data (claims)
Typical fieldsalg, typ, kidsub, exp, iat, custom claims
SizeSmall (2-3 fields)Variable (5-20+ fields)
Who reads itJWT library (for verification)Your application logic

The header tells the JWT library how to verify the token. The payload tells your application what the token means.

5. Common Payload Fields

FieldNameTypeDescription
issIssuerStringWho issued the token
subSubjectStringWho the token is about (usually user ID)
audAudienceString/ArrayWho the token is intended for
expExpirationNumberUnix timestamp when the token expires
nbfNot BeforeNumberUnix timestamp when the token becomes valid
iatIssued AtNumberUnix timestamp when the token was created
jtiJWT IDStringUnique identifier to prevent replay
nameFull NameStringUser's display name (OpenID Connect)
emailEmailStringUser's email address (OpenID Connect)
scopeScopeStringSpace-separated list of permissions (OAuth 2.0)

For a deep dive into each claim, see our JWT claims reference.

6. Payload Size Considerations

Every byte in the payload increases the token size. Since JWTs are sent with every HTTP request (typically in the Authorization header), large payloads directly impact performance.

Typical JWT sizes

  • Minimal payload (3-4 claims): ~200-300 bytes total
  • Standard payload (8-10 claims): ~500-800 bytes total
  • Large payload (20+ claims): ~1-2 KB total

Watch out: Most web servers limit HTTP header size to 8 KB. If your JWT exceeds this (common when embedding permissions arrays or nested objects), requests will fail with a 431 status code. Keep payloads lean — store large data server-side and reference it with an ID in the token.

7. Security: What NOT to Put in a Payload

Since the payload is only encoded (not encrypted), anyone with the token can read its contents. Never include:

  • Passwords — not even hashed passwords
  • Credit card numbers or financial data
  • API keys or secrets
  • Social security numbers or government IDs
  • Full addresses or other PII beyond what's necessary
  • Medical records or health information

Safe to include:

  • User IDs and usernames
  • Roles and permissions
  • Token metadata (issuer, audience, expiration)
  • Non-sensitive preferences (language, timezone)

If you need to transmit sensitive data, use JWE (JSON Web Encryption) instead of plain JWT, or store sensitive data server-side and only reference it by ID in the token.

8. How to Decode a JWT Payload

Decoding a JWT payload is straightforward — it's just Base64URL decoding followed by JSON parsing:

JavaScript

const token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NSJ9.signature";
const payload = token.split('.')[1];
const decoded = JSON.parse(atob(payload));
console.log(decoded); // { sub: "12345" }

Python

import base64, json

token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NSJ9.signature"
payload = token.split('.')[1]
# Add padding if needed
payload += '=' * (4 - len(payload) % 4)
decoded = json.loads(base64.urlsafe_b64decode(payload))
print(decoded)  # {'sub': '12345'}

Ruby

require 'base64'
require 'json'

token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NSJ9.signature"
payload = token.split('.')[1]
decoded = JSON.parse(Base64.urlsafe_decode64(payload))
puts decoded  # {"sub"=>"12345"}

Important: Decoding the payload only reads the data — it does not verify the signature. Always verify the signature before trusting the payload contents. Use our JWT decoder to both decode and verify in one step.

Decode Your JWT Payload

Paste a token to instantly see the decoded payload with all claims formatted and explained.