Decoding a JWT reveals the header and payload as JSON. No key needed — JWT payloads are base64-encoded, not encrypted. Anyone can decode.
Prerequisites
- The JWT token string (typically the value of an
Authorization: Bearerheader)
Method 1 — Use the JWT Decoder
Paste the token into the JWT decoder. Get:
- Decoded header (algorithm, key ID, token type)
- Decoded payload (claims: sub, iss, aud, exp, iat, custom claims)
- Signature format (not verified — decoding ≠ verifying)
Method 2 — Command Line
Split the token on dots into three segments:
TOKEN="eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMifQ.abc..."
HEADER=$(echo $TOKEN | cut -d. -f1)
PAYLOAD=$(echo $TOKEN | cut -d. -f2)
echo $HEADER | base64 -d
echo $PAYLOAD | base64 -d
Note: base64url uses - and _ instead of + and /, and drops padding. Add padding to make it valid classic base64:
pad() { local a=$1; while [ $(( ${#a} % 4 )) -ne 0 ]; do a="${a}="; done; echo $a; }
echo $(pad $HEADER) | tr '_-' '/+' | base64 -d
Convert with the Base64 converter for a UI approach.
Method 3 — Python
import base64, json
def decode_jwt_segment(seg):
# Add padding
seg += '=' * (4 - len(seg) % 4)
# Base64url → base64
seg = seg.replace('-', '+').replace('_', '/')
return json.loads(base64.b64decode(seg))
token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMifQ.abc..."
header, payload, _ = token.split('.')
print(decode_jwt_segment(header))
print(decode_jwt_segment(payload))
What You Get
Header — always metadata:
{
"alg": "HS256",
"typ": "JWT",
"kid": "2024-key-1"
}
Payload — claims:
{
"sub": "user-42",
"iss": "https://auth.example.com",
"aud": "https://api.example.com",
"exp": 1735689600,
"iat": 1735686000,
"role": "admin"
}
Decoding ≠ Verifying
Decoding reveals the payload. It does not verify the signature. A tampered token decodes fine but has an invalid signature. See how to verify a JWT signature for the verification step.
Common Miss
- Assuming decoded payload is safe — anyone can craft a valid-looking payload; always verify signature server-side
- Trying to decode the third segment (signature) as base64 → it’s a binary signature, not JSON
- Confusing base64url with classic base64 — the
-/_substitutions matter
Read what a JWT is for the full structure explanation.
Related
Read what a JWT is, check the JWT glossary entry, and see the JWS entry for signature-format details.