Flask

raw JSON →
3.1.3 verified Tue May 12 auth: no python install: verified quickstart: verified

Lightweight WSGI web framework. Current version is 3.1.3 (Feb 2026). Flask 3.0 (Sep 2023) removed a large set of APIs that had been deprecated since 2.x — before_first_request, FLASK_ENV, JSON config keys, and custom json_encoder/decoder. LLMs still generate these removed patterns.

pip install Flask
error ImportError: cannot import name 'FlaskForm' from 'flask'
cause The 'FlaskForm' class is part of the 'flask_wtf' extension, not the core 'flask' module.
fix
Use 'from flask_wtf import FlaskForm' instead of 'from flask import FlaskForm'.
error ImportError: cannot import name 'url_quote' from 'werkzeug.urls'
cause The 'url_quote' function was removed in Werkzeug 3.0.0.
fix
Downgrade Werkzeug to a version before 3.0.0 by adding 'Werkzeug==2.3.7' to your 'requirements.txt' file and reinstalling dependencies.
error ImportError: cannot import name 'escape' from 'jinja2'
cause The 'escape' function was removed from Jinja2 in version 3.1.0.
fix
Import 'escape' from 'markupsafe' instead: 'from markupsafe import escape'.
error ImportError: cannot import name 'Flask' from 'flask'
cause This error often occurs due to a circular import or incorrect project structure.
fix
Ensure that your project structure does not have circular imports and that 'flask' is installed correctly.
error ImportError: cannot import name 'json' from 'flask'
cause The 'json' module was removed from Flask in version 3.0.0.
fix
Use Python's built-in 'json' module instead: 'import json'.
breaking @app.before_first_request and @bp.before_app_first_request decorators removed in Flask 3.0. Extremely common in older tutorials and LLM-generated code.
fix Run initialization code in the app factory, in a CLI command, or using with app.app_context(): at startup. For teardown-based patterns use @app.teardown_appcontext.
breaking FLASK_ENV environment variable, ENV config key, and app.env property removed in Flask 3.0. Using FLASK_ENV=development no longer enables debug mode.
fix Use FLASK_DEBUG=1 or flask run --debug for debug mode. Set app.config['TESTING'] = True for test mode.
breaking JSON config keys removed in Flask 3.0: JSON_AS_ASCII, JSON_SORT_KEYS, JSONIFY_MIMETYPE, JSONIFY_PRETTYPRINT_REGULAR. LLMs still generate these in config blocks.
fix Use app.json.sort_keys = False, app.json.mimetype = 'application/json', app.json.ensure_ascii = False on the app.json provider instead.
breaking app.json_encoder and app.json_decoder class attributes removed in Flask 3.0. Custom JSON serialization using these was a common pattern.
fix Subclass flask.json.provider.DefaultJSONProvider and assign: app.json_provider_class = MyProvider, then app = Flask(__name__).
breaking send_file() parameter names changed in Flask 2.0 and finalised in 3.0: attachment_filename → download_name, cache_timeout → max_age, add_etags → etag. Old names raise TypeError.
fix Update send_file calls: send_file(path, download_name='file.csv', max_age=3600, etag=True).
deprecated flask.Markup imported from flask is deprecated. Markup was moved to MarkupSafe.
fix from markupsafe import Markup
gotcha flask run requires the app to be discoverable. By default looks for app.py or wsgi.py with an app variable. Use FLASK_APP env var or --app flag for other module names.
fix flask --app mymodule:app run or export FLASK_APP=mymodule:app
gotcha Async views require Flask[async] (installs asgiref). Defining async def routes without this raises RuntimeError or silently runs synchronously depending on version.
fix pip install 'Flask[async]' to enable async view support.
pip install "Flask[async]"
pip install "Flask[dotenv]"
python os / libc variant status wheel install import disk
3.10 alpine (musl) async - - 0.43s 22.9M
3.10 alpine (musl) dotenv - - 0.43s 22.5M
3.10 alpine (musl) Flask - - 0.45s 22.3M
3.10 slim (glibc) async - - 0.33s 23M
3.10 slim (glibc) dotenv - - 0.33s 23M
3.10 slim (glibc) Flask - - 0.34s 23M
3.11 alpine (musl) async - - 0.60s 25.3M
3.11 alpine (musl) dotenv - - 0.59s 25.2M
3.11 alpine (musl) Flask - - 0.60s 25.0M
3.11 slim (glibc) async - - 0.49s 26M
3.11 slim (glibc) dotenv - - 0.52s 26M
3.11 slim (glibc) Flask - - 0.49s 26M
3.12 alpine (musl) async - - 0.50s 16.9M
3.12 alpine (musl) dotenv - - 0.52s 16.9M
3.12 alpine (musl) Flask - - 0.51s 16.7M
3.12 slim (glibc) async - - 0.53s 17M
3.12 slim (glibc) dotenv - - 0.51s 17M
3.12 slim (glibc) Flask - - 0.51s 17M
3.13 alpine (musl) async - - 0.48s 16.6M
3.13 alpine (musl) dotenv - - 0.48s 16.5M
3.13 alpine (musl) Flask - - 0.49s 16.3M
3.13 slim (glibc) async - - 0.52s 17M
3.13 slim (glibc) dotenv - - 0.48s 17M
3.13 slim (glibc) Flask - - 0.48s 17M
3.9 alpine (musl) async - - 0.39s 22.6M
3.9 alpine (musl) dotenv - - 0.38s 22.3M
3.9 alpine (musl) Flask - - 0.39s 22.1M
3.9 slim (glibc) async - - 0.35s 23M
3.9 slim (glibc) dotenv - - 0.34s 23M
3.9 slim (glibc) Flask - - 0.38s 23M

Minimal Flask 3.x app with JSON responses and error handler.

from flask import Flask, jsonify, request

app = Flask(__name__)

@app.get('/')
def index():
    return jsonify({'status': 'ok'})

@app.post('/items')
def create_item():
    data = request.get_json()
    return jsonify(data), 201

@app.errorhandler(404)
def not_found(e):
    return jsonify({'error': 'not found'}), 404

# Run: flask --app app run --debug