Decode JWT in Python Without a Library (Just base64)
- A 5-line Python snippet to decode any JWT without installing anything
- How to handle base64url padding — the most common source of errors
- Extract specific claims like sub, exp, or custom fields
- When to use this vs PyJWT or python-jose
Table of Contents
Decoding a JWT in Python requires zero libraries — just the standard base64 and json modules. A JWT is three base64url-encoded segments. Reading the payload is a 5-line operation. Here is everything you need.
Decode JWT Payload in Python — No Library Needed
import base64
import json
def decode_jwt_payload(token):
payload_b64 = token.split('.')[1]
# base64url uses - and _ instead of + and /; also needs padding
padding = 4 - len(payload_b64) % 4
payload_b64 += '=' * padding
payload_bytes = base64.b64decode(payload_b64.replace('-', '+').replace('_', '/'))
return json.loads(payload_bytes)
# Usage
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTYiLCJleHAiOjE3MzU2ODk2MDB9.signature"
payload = decode_jwt_payload(token)
print(payload)
# {'sub': '1234567', 'exp': 1735689600}
To decode the header instead, change split('.')[1] to split('.')[0]. The same padding and character replacement logic applies.
The Base64url Padding Problem
The most common error when decoding JWT segments is an Incorrect padding exception. This happens because JWT uses base64url encoding, which strips the trailing = padding characters that standard base64 requires.
The fix is to calculate how many = characters are needed and add them back:
padding = 4 - len(payload_b64) % 4
payload_b64 += '=' * padding
The second issue is character substitution. Base64url uses - and _ where standard base64 uses + and /. Python's base64.b64decode expects standard base64, so you need:
payload_b64.replace('-', '+').replace('_', '/')
Python 3.4+ also has base64.urlsafe_b64decode() which handles the character substitution automatically, but still needs the padding fix.
Cleaner Version Using urlsafe_b64decode
import base64
import json
def decode_jwt_payload(token):
segment = token.split('.')[1]
# urlsafe_b64decode handles - and _ but still needs padding
segment += '=' * (4 - len(segment) % 4)
decoded = base64.urlsafe_b64decode(segment)
return json.loads(decoded)
payload = decode_jwt_payload(your_token)
# Get specific claims
print(payload.get('sub')) # user ID
print(payload.get('exp')) # expiry timestamp
print(payload.get('email')) # if present
This is slightly cleaner. Both approaches produce identical results.
When You Should Use PyJWT or python-jose
The base64 approach above only decodes — it does NOT verify the signature. That is fine for:
- Debugging and inspection during development
- Reading claims from tokens you received (where the server already validated them)
- Admin scripts or one-off data extraction tasks
You should use PyJWT or python-jose when:
- You are building a server that needs to validate incoming JWTs (verify signature + expiry)
- You need to handle JWKS (public key sets) from identity providers like Auth0 or Cognito
- You are generating JWTs yourself
Never use decoded-but-unverified claims for authorization decisions in production code. Decoding tells you what the token says — verification confirms it was signed by who you trust.
Prefer a Visual Decoder? Try the Browser Tool
Paste any JWT above — instant decode with labeled claims, no Python setup required.
Open Free JWT DecoderFrequently Asked Questions
Does this work with Python 2?
The base64.urlsafe_b64decode approach works in Python 2 as well, but Python 2 is end-of-life. Stick to Python 3.6+ for new code.
Can I decode a JWT without knowing the algorithm?
Yes — decoding does not require knowing the algorithm. The algorithm (alg) is in the header, but you do not need it to base64-decode the payload. The algorithm is only needed for signature verification.
What if the JWT has three dots instead of two?
A standard JWT has exactly two dots (header.payload.signature). If you have more dots, the token may be a nested JWT or a JWE (encrypted token). JWE cannot be decoded without the private key.

