Install & Compatibility
Where this runs
tested against v4.7.4 · 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.95 runs
installs and imports cleanly · install 0.0s · import 0.534s · 23.3MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 2.4s · import 0.498s · 24MB
22MB installed
● package 22MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
JWTManager
✓ from flask_jwt_extended import JWTManager
jwt_required
✓ from flask_jwt_extended import jwt_required
create_access_token
✓ from flask_jwt_extended import create_access_token
get_jwt_identity
✓ from flask_jwt_extended import get_jwt_identity
This quickstart demonstrates how to initialize Flask-JWT-Extended, create a login endpoint to issue an access token, and protect another endpoint using the `@jwt_required()` decorator. It shows how to retrieve the identity of the authenticated user within a protected route. Remember to set the `FLASK_JWT_SECRET_KEY` environment variable for production environments.
import os
from flask import Flask, jsonify, request
from flask_jwt_extended import create_access_token, jwt_required, JWTManager, get_jwt_identity
app = Flask(__name__)
# Set a secret key for JWT signing. For production, use a strong, unique key.
app.config["JWT_SECRET_KEY"] = os.environ.get("FLASK_JWT_SECRET_KEY", "super-secret-dev-key")
# Initialize the Flask-JWT-Extended extension
jwt = JWTManager(app)
# A simple login route to get an access token
@app.route("/login", methods=["POST"])
def login():
username = request.json.get("username", None)
password = request.json.get("password", None)
# In a real application, you'd verify these credentials against a database
if username != "testuser" or password != "testpass":
return jsonify({"msg": "Bad username or password"}), 401
access_token = create_access_token(identity=username)
return jsonify(access_token=access_token)
# A protected route that requires a valid JWT access token
@app.route("/protected", methods=["GET"])
@jwt_required()
def protected():
# Access the identity of the current user with get_jwt_identity
current_user = get_jwt_identity()
return jsonify(logged_in_as=current_user), 200
if __name__ == "__main__":
# To run:
# 1. Set FLASK_JWT_SECRET_KEY environment variable (or it will use 'super-secret-dev-key')
# e.g., export FLASK_JWT_SECRET_KEY="your-strong-secret"
# 2. Run this script: python your_app.py
# 3. Test with curl:
# curl -X POST -H "Content-Type: application/json" -d '{"username":"testuser", "password":"testpass"}' http://127.0.0.1:5000/login
# (Copy the access_token from the response)
# curl -H "Authorization: Bearer <your_access_token>" http://127.0.0.1:5000/protected
app.run(debug=True)
Debug
Known issues
breakingPython 3.7 and 3.8 support was dropped in Flask-JWT-Extended 4.7.0. If you are on these Python versions, you must upgrade your Python environment or use a version of Flask-JWT-Extended older than 4.7.0.fixUpgrade your Python version to 3.9 or newer. If not possible, pin `Flask-JWT-Extended<4.7.0`.
affects: >=4.7.0
breakingFlask 3.0 compatibility was introduced in Flask-JWT-Extended 4.5.3. Applications using Flask 3.x must ensure they are using `flask-jwt-extended>=4.5.3` to avoid compatibility issues.fixUpgrade `Flask-JWT-Extended` to version 4.5.3 or newer if using Flask 3.x. Pin `Flask-JWT-Extended<4.5.3` if using Flask <3.0.
affects: <4.5.3
breakingMigrating from Flask-JWT-Extended v3.x to v4.x involved significant breaking changes, including how tokens are returned (no longer a dict by default), changes to decorators, and more explicit configuration requirements.fixConsult the official migration guide for detailed steps. Be prepared to update token return formats, decorator usage, and configuration settings (e.g., `JWT_SECRET_KEY`).
affects: 3.x to 4.x
gotchaFlask-JWT-Extended uses `app.config["JWT_SECRET_KEY"]` for signing JWTs, which is distinct from Flask's `app.secret_key` or `app.config["SECRET_KEY"]`. Using Flask's secret key for JWT signing is a common mistake and can lead to unexpected behavior or security vulnerabilities.fixAlways set `app.config["JWT_SECRET_KEY"]` explicitly and ensure it is a strong, unique secret key separate from Flask's `SECRET_KEY`.
affects: All versions
gotchaThe `identity` argument passed to `create_access_token()` (and `create_refresh_token()`) should ideally be a string or a value that can be easily serialized to JSON and uniquely identifies the user. While it may accept other types, the documentation strongly encourages string identities for clarity and consistent behavior.fixEnsure the value passed as `identity` is a unique string representing the user (e.g., user ID, username). If using an object, ensure it can be reliably serialized and deserialized to retrieve the identity later.
affects: All versions
breakingThe library failed to install or run basic tests within the allocated time limit on Python 3.9, indicating a potential issue with dependency resolution, resource utilization, or an unexpected hang during the setup process specific to this environment.fixReview system logs for installation errors. Consider allocating more resources to the build environment or troubleshooting dependency conflicts. Pinning to an older, stable version of `Flask-JWT-Extended` known to work on Python 3.9 might also help.
affects: All versions (when running on Python 3.9)
breakingFlask-JWT-Extended appears to be incompatible with Python 3.13, resulting in a timeout during installation or execution. This indicates a potential lack of official support or a critical compatibility issue with this Python version.fixAvoid using Flask-JWT-Extended with Python 3.13 until official compatibility is announced and verified. Consider using Python versions up to 3.12.
affects: All versions (on Python 3.13)
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'flask_jwt_extended'
The 'flask-jwt-extended' package is not installed in the Python environment or the environment where the Flask application is running.
fixpip install flask-jwt-extended
AttributeError: 'JWTManager' object has no attribute 'token_in_blacklist_loader'
This error occurs in Flask-JWT-Extended v4.0.0 and above because the 'blacklist' terminology was changed to 'blocklist'. The 'token_in_blacklist_loader' decorator no longer exists.
fixReplace `@jwt.token_in_blacklist_loader` with `@jwt.token_in_blocklist_loader`. Also, rename related configuration options like `JWT_BLACKLIST_ENABLED` to their `_BLOCKLIST_` equivalents.
ImportError: cannot import name 'DecodeError' from 'jwt'
This typically occurs due to a conflict with an older or incorrect 'jwt' package, or an incompatible version of 'PyJWT' (Flask-JWT-Extended requires PyJWT >= 2.0.0).
fixUninstall any conflicting 'jwt' or 'PyJWT' packages and then reinstall 'PyJWT' and 'flask-jwt-extended': `pip uninstall jwt PyJWT && pip install PyJWT flask-jwt-extended`.
Error: Initialize a JWTManager with this flask application before using this method
The JWTManager instance was created but not initialized with the Flask application instance using `jwt.init_app(app)` before JWT-related operations (like decorators) are attempted.
fixEnsure `jwt.init_app(app)` is called after creating your Flask app and JWTManager instance, typically in your application factory or main app file, or pass the app directly to the constructor: `jwt = JWTManager(app)`.
Upgrade
Version history
4.7.4latest on PyPI · released May 13, 2026
Audit
Dependencies
FlaskrequiredCore web framework integration.
PyJWTrequiredHandles the underlying JWT encoding and decoding.
cryptographyrequiredProvides cryptographic primitives for PyJWT's algorithms.