A JSON Web Token (JWT) is composed of three distinct parts: the header, the payload, and the signature. These are separated by periods (.) and are Base64Url encoded. Because the payload is simply Base64Url encoded—not encrypted—you can easily view the claims within the token without needing a heavy library.
Can You Decode a JWT Token Without a Library?
Yes. Because the header and payload are simply JSON objects serialized and then encoded using Base64Url, they can be decoded using standard language utilities.
Before you start, a critical security note: Decoding a JWT does not perform validation.
Without a library, you are merely inspecting the data. You are not verifying if the signature is valid, if the token has been tampered with, or if the token has expired. For production-grade validation, always use a reputable security library. For local debugging or frontend inspection, the following methods are perfect.
How to Decode a JWT Token Manually in JavaScript
To parse a JWT manually in the browser, you need to extract the middle portion (the payload) and decode it.
Modern browsers provide atob() for base64 decoding. However, since JWTs use the Base64Url variant, we must first replace the URL-safe characters (- and _) before decoding.
function parseJwt(token) {
try {
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
return JSON.parse(jsonPayload);
} catch (error) {
return null;
}
}This function splits the token, handles the Base64Url mapping, adds the necessary padding if needed, and decodes the Unicode string to JSON.
How to Decode a JWT Token in Python
Python makes handling Base64 and JSON trivial with the built-in base64 and json libraries. This approach is highly efficient for server-side logging or internal debugging.
import base64
import json
def decode_jwt(token):
try:
# Split the token and get the payload (middle part)
payload = token.split('.')[1]
# Add padding if necessary
# Base64Url is like Base64 but without padding
missing_padding = len(payload) % 4
if missing_padding:
payload += '=' * (4 - missing_padding)
decoded_bytes = base64.urlsafe_b64decode(payload)
return json.loads(decoded_bytes)
except Exception as e:
return None
# Example usage:
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
print(decode_jwt(token))Security Considerations
Decoding a JWT using these methods is perfectly safe for local debugging. However, if you are working in an environment where token authenticity is required, you must verify the signature.
If you find yourself needing to frequently validate tokens rather than just quickly inspect their contents, I recommend using our JWT Validator Tool for instant, secure authentication checking.
For more on managing token lifecycles, read our post on JWT Token Expiration Best Practices.