Install & Compatibility
Where this runs
tested against v2.13.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.910 runs
installs and imports cleanly · install 0.0s · import 0.121s · 18.3MB
glibcpy 3.10–3.910 runs
installs and imports cleanly · install 1.7s · import 0.114s · 19MB
16MB installed
● package 16MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
jwt (module)
✓ import jwt
Top-level module exposes encode(), decode(), get_unverified_header(), and all exception classes.
PyJWKClient
✓ from jwt import PyJWKClient
Used for automatic JWKS endpoint fetching and key resolution (e.g. Auth0, Cognito).
PyJWK
✓ from jwt import PyJWK
Wraps a single JSON Web Key; returned by PyJWKClient.get_signing_key_from_jwt().
ExpiredSignatureError
✓ from jwt.exceptions import ExpiredSignatureError
✗ from jwt.exceptions import ExpiredSignature
ExpiredSignature (no 'Error' suffix) was removed in 2.0. Use ExpiredSignatureError, InvalidAudienceError, InvalidIssuerError.
InvalidAudienceError
✓ from jwt.exceptions import InvalidAudienceError
✗ from jwt.exceptions import InvalidAudience
InvalidAudience (no 'Error' suffix) was removed in 2.0.
PyJWKClientConnectionError
✓ from jwt import PyJWKClientConnectionError
Raised when PyJWKClient cannot reach the JWKS endpoint; exported at top level since 2.8.0.
Encode and decode a signed JWT with HS256, validating exp/aud/iss claims. token is a str in PyJWT 2.x.
import os
import jwt
from datetime import datetime, timezone, timedelta
SECRET = os.environ.get('JWT_SECRET', 'change-me-use-32-plus-chars-prod!')
# Encode
payload = {
"sub": "user-123",
"iss": "my-service",
"aud": "my-api",
"exp": datetime.now(tz=timezone.utc) + timedelta(hours=1),
"iat": datetime.now(tz=timezone.utc),
}
token: str = jwt.encode(payload, SECRET, algorithm="HS256")
print("token type:", type(token)) # <class 'str'> in 2.x
# Decode — always pass algorithms= to prevent alg confusion attacks
try:
decoded = jwt.decode(
token,
SECRET,
algorithms=["HS256"], # required; never omit
audience="my-api", # validates 'aud' claim
issuer="my-service", # validates 'iss' claim
options={"require": ["exp", "iat", "sub"]},
)
print(decoded)
except jwt.ExpiredSignatureError:
print("token expired")
except jwt.InvalidTokenError as e:
print("invalid token:", e)
Debug
Known issues
breakingjwt.encode() returns str in 2.x, not bytes. Calling .decode('utf-8') on the result raises AttributeError.fixRemove any .decode('utf-8') calls on the encode() return value. It is already a str in 2.0+. affects: <2.0
breakingException aliases ExpiredSignature, InvalidAudience, and InvalidIssuer were removed in 2.0. Code catching these names will silently fail to catch the exception.fixCatch jwt.ExpiredSignatureError, jwt.InvalidAudienceError, and jwt.InvalidIssuerError respectively.
affects: <2.0
breakingjwt.decode(token, key, verify=False) does nothing in 2.x and raises a deprecation warning. Passing extra kwargs to decode() is flagged RemovedInPyjwt3Warning.fixUse options={"verify_signature": False} to skip verification, e.g. jwt.decode(token, options={"verify_signature": False}). affects: 1.x pattern used in 2.x
breakingCVE-2026-32597 (GHSA-752w-5fwx-jx9f, CVSS 7.5 HIGH): versions < 2.12.0 silently accept JWS tokens with unknown crit header extensions, violating RFC 7515 §4.1.11.fixUpgrade to pyjwt>=2.12.0 immediately.
affects: <2.12.0
gotchaalgorithms= parameter is required in jwt.decode(). Omitting it accepts any algorithm, enabling alg:none and key-confusion attacks (CVE-2022-29217).fixAlways pass a hard-coded allowlist: jwt.decode(token, key, algorithms=["HS256"]). Never derive the list from the token header.
affects: all 2.x
gotchaOptional claims (exp, iat, nbf, sub, jti) are only validated when present. A token missing exp is accepted even if you call decode() without options.fixPass options={"require": ["exp", "iat", "sub"]} to enforce presence and validation of critical claims. affects: all 2.x
gotchaRSA/EC/PS*/EdDSA algorithms silently fail with an unhelpful ImportError or InvalidAlgorithmError if the cryptography package is not installed.fixInstall pyjwt[cryptography] when using any non-HMAC algorithm.
affects: all 2.x
Errors
Common errors & fixes
jwt.exceptions.InvalidAlgorithmError: The specified alg value is not allowed
The `algorithms` parameter was either not provided or did not include the algorithm used to sign the token when calling `jwt.decode()`. PyJWT requires explicit declaration of allowed algorithms for security reasons.
fixPass a list of explicitly allowed algorithms, matching the token's 'alg' header, to the `algorithms` parameter in `jwt.decode()`. Example: `jwt.decode(token, secret, algorithms=['HS256'])`
NotImplementedError: Algorithm 'RS256' could not be found. Do you have cryptography installed?
You are attempting to use an asymmetric algorithm (such as RS*, ES*, PS*, or EdDSA) but the optional `cryptography` dependency for PyJWT is not installed.
fixInstall PyJWT with the `crypto` extra to include the `cryptography` dependency: `pip install "pyjwt[crypto]"` (note the quotes for shell compatibility).
jwt.exceptions.InvalidSignatureError: Signature verification failed
The secret key or public key provided to `jwt.decode()` does not match the key used to sign the token, or the token itself is malformed or has been tampered with.
fixEnsure the `key` parameter passed to `jwt.decode()` is the correct secret (for symmetric algorithms like HS256) or the correct public key (for asymmetric algorithms like RS256) that was used during the token's encoding.
AttributeError: 'module' object has no attribute 'encode'
This error often occurs due to a naming conflict when both the `PyJWT` library (which provides the `jwt` module) and an older, incompatible `jwt` package are installed simultaneously.
fixUninstall both packages (`pip uninstall jwt pyjwt`) to remove any conflicting installations, then reinstall only PyJWT (`pip install pyjwt`).
Upgrade
Version history
2.13.0latest on PyPI · released May 21, 2026
Audit
Dependencies
cryptographyoptionalRequired for RSA, EC, PS*, and EdDSA algorithms. Not needed for HMAC-only usage.
typing_extensionsrequiredRequired on Python < 3.11 (added in 2.12.1).