Table of Contents
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
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:
| Aspect | Header | Payload |
|---|---|---|
| Purpose | Metadata about the token | The actual data (claims) |
| Typical fields | alg, typ, kid | sub, exp, iat, custom claims |
| Size | Small (2-3 fields) | Variable (5-20+ fields) |
| Who reads it | JWT 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
| Field | Name | Type | Description |
|---|---|---|---|
| iss | Issuer | String | Who issued the token |
| sub | Subject | String | Who the token is about (usually user ID) |
| aud | Audience | String/Array | Who the token is intended for |
| exp | Expiration | Number | Unix timestamp when the token expires |
| nbf | Not Before | Number | Unix timestamp when the token becomes valid |
| iat | Issued At | Number | Unix timestamp when the token was created |
| jti | JWT ID | String | Unique identifier to prevent replay |
| name | Full Name | String | User's display name (OpenID Connect) |
| String | User's email address (OpenID Connect) | ||
| scope | Scope | String | Space-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.