Skip to content
Back to skills

Flask

ASecurity

Working reference for Flask (pallets/flask), the Python WSGI micro web framework built on Werkzeug, Jinja and Click, distilled from the official docs in the repository. Covers routing and views, the app/request context and request lifecycle, application factories and blueprints, configuration (every built-in config key with its default), the flask CLI and dotenv, Jinja templating, error handling, logging and debugging, testing with pytest, production deployment (Gunicorn, Waitress, mod_wsgi, ...

  • 5 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 5, 2026
ai-agentsjavascriptpythonrustgojavashellsqlflasktestingdebugging

Works with

  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 16 files and shows the line behind each finding

Scanned October 5, 2026

npx -y skills add michalstrnadel/source-to-skill --skill flask --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Flask?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Flask
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/michalstrnadel-flask/badge)](https://www.skillsdirectory.com/skills/michalstrnadel-flask)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: flask
description: Working reference for Flask (pallets/flask), the Python WSGI micro web framework built on Werkzeug, Jinja and Click, distilled from the official docs in the repository. Covers routing and views, the app/request context and request lifecycle, application factories and blueprints, configuration (every built-in config key with its default), the flask CLI and dotenv, Jinja templating, error handling, logging and debugging, testing with pytest, production deployment (Gunicorn, Waitress, mod_wsgi, uWSGI, gevent, ASGI, nginx/Apache with ProxyFix), security, extensions, common patterns (SQLite, SQLAlchemy, Celery, uploads) and the Flaskr tutorial. Load it when building, debugging, testing, configuring or deploying a Flask app, or when writing a Flask extension.
---

# Flask

Source: https://github.com/pallets/flask - README plus the `docs/` tree
(77 pages). Flask is a lightweight WSGI web application framework: quick to
start, able to scale to complex apps. It depends on Werkzeug (WSGI), Jinja
(templates), MarkupSafe (escaping), ItsDangerous (signing the session
cookie), Click (the `flask` command) and Blinker (signals). Supports
Python 3.10 and newer.

## Core mental model

- **"Micro" means a small, extensible core**, not a toy. Flask picks the
  template engine (Jinja) and the WSGI layer (Werkzeug) and nothing else.
  It will never ship a database layer or a form library. Extensions cover those.
- **One explicit application object.** `app = Flask(__name__)`. Flask uses
  `__name__` to find templates, static files and resources relative to your
  package. An explicit object means you can run several apps at once (useful
  for tests), subclass `Flask`, and wrap the WSGI app in middleware.
- **Setup phase vs. serving phase.** Register routes, blueprints, config,
  Jinja settings and extensions *before* the first request. WSGI servers run
  many workers, so changes made later never reach all of them. Flask raises
  an error if you call a setup method such as `route` after the app has handled a request.
- **Context-local proxies.** `current_app`, `g`, `request` and `session`
  point at the active context of the current worker (thread, greenlet,
  coroutine). An app context (CLI, `with app.app_context()`) gives
  `current_app` and `g`. A request adds `request` and `session`. Accessing them
  outside a context raises `RuntimeError: Working outside of application/request context`.
- **Return values become responses:** str, bytes or iterator → body. dict or
  list → JSON. `(body, status)`, `(body, headers)` or
  `(body, status, headers)` → body plus overrides. A `Response` passes through
  unchanged. Anything else is treated as a WSGI app.
- **Production is never `flask run`.** The development server and its
  debugger allow arbitrary code execution. Use a WSGI server, usually
  behind a reverse proxy.

## Install and first app

```
python3 -m venv .venv && . .venv/bin/activate
pip install Flask
```

```python
# hello.py  (never name it flask.py: it shadows Flask itself)
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"
```

```
flask --app hello run --debug     # reloader + interactive debugger
```

- If the file is `app.py` or `wsgi.py`, you can omit `--app`.
- The server listens on `127.0.0.1:5000` and is visible only from your
  machine. `--host=0.0.0.0` exposes it, but only do that with the debugger
  off or on a trusted network.
- On macOS Monterey and later, AirPlay Receiver occupies port 5000. Turn it
  off, or run `flask run --port 5001`.

## Core usage patterns

- **Routing:** `@app.route("/post/<int:id>")`. The converters are `string` (the
  default, no slashes), `int`, `float`, `path` (accepts slashes), `uuid`, and
  `any` (listed in the API docs). Use the method shortcuts `@app.get` and
  `@app.post`. Routes answer `GET` only by default. `HEAD` and `OPTIONS` are
  automatic.
- **Trailing slash rule:** `/projects/` redirects `/projects` to the
  canonical URL. `/about` returns 404 for `/about/`.
- **URL building:** `url_for("endpoint", **values)`. Values that don't match
  the rule become query args. Blueprint endpoints are `bp.view`, and `.view`
  refers to the same blueprint. Static files: `url_for('static', filename=...)`.
- **Request data:** `request.form` for POST/PUT form data, `request.args`
  for the query string, `request.files` for uploads, `request.json` for JSON
  bodies (415 if `Content-Type` isn't `application/json`), and
  `request.cookies`. A missing key raises a 400 unless you catch it. Use
  `.get(key, default)` instead.
- **Sessions:** a signed cookie. The user can read it but can't modify it.
  It requires `SECRET_KEY`. Generate one with
  `python -c 'import secrets; print(secrets.token_hex())'`. In-place
  mutation isn't detected, so set `session.modified = True`.
- **Escaping:** Jinja autoescapes `.html/.htm/.xml/.xhtml/.svg` templates.
  For HTML you build by hand, use `markupsafe.escape()`.
- **App factory and blueprints** are the default structure for anything
  non-trivial. Create the extension objects unbound, then call
  `ext.init_app(app)` inside `create_app()`. See guides/app-structure.md.
- **Hooks**, in request order: `url_value_preprocessor` → `before_request`
  (returning a value short-circuits the request) → view → `errorhandler` →
  `after_this_request` → `after_request` → session save → `teardown_request`
  → `teardown_appcontext`. Teardown hooks always run, even after an error,
  so don't depend on earlier hooks having run.

## Decision rules

- **Async views** (`pip install flask[async]`): use them for concurrent I/O
  inside one view. Each request still occupies one worker, async is not faster
  than sync, and background tasks get cancelled. For a mainly-async codebase
  use Quart. For many long-lived connections use gevent. For background work
  use a task queue (Celery).
- **Blueprints vs. multiple apps:** blueprints share one config and are
  separated at the Flask level. Use `DispatcherMiddleware` when apps must be
  fully isolated at the WSGI level.
- **Debug mode:** set it with `--debug`. Setting `DEBUG` in code or config is
  strongly discouraged, because `flask run` can't read it early enough.
- **ProxyFix:** apply it only when the app really runs behind a proxy, and
  set exactly as many hops as there are proxies. Getting this wrong is a
  security issue.
- **Error handlers:** register them for specific exceptions. A handler for
  `Exception` also swallows every HTTP error. Pass `HTTPException` through.
- **Form data vs. JSON from JavaScript:** prefer form data. Use JSON only
  when you need complex structures.

## Doc index

| Guide | Covers |
|---|---|
| [guides/getting-started.md](guides/getting-started.md) | Install, quickstart walkthrough, dev server, debug mode, port conflicts |
| [guides/routing-and-views.md](guides/routing-and-views.md) | Rules, converters, `url_for`, methods, request data, responses, cookies, class-based views, view decorators, URL processors |
| [guides/app-structure.md](guides/app-structure.md) | Request lifecycle, contexts, factories, packages, blueprints, dispatching, signals, design rationale |
| [guides/configuration.md](guides/configuration.md) | All built-in config keys and defaults, loading from files, objects and env vars, instance folders |
| [guides/cli.md](guides/cli.md) | `flask` command, `--app` discovery, dotenv, custom commands, plugins, shell |
| [guides/templates-and-frontend.md](guides/templates-and-frontend.md) | Jinja setup, context, autoescaping, filters, inheritance, flashing, `fetch`/JSON, streaming |
| [guides/errors-logging-debugging.md](guides/errors-logging-debugging.md) | Error handlers, JSON API errors, Sentry, logging config, debuggers |
| [guides/testing.md](guides/testing.md) | pytest fixtures, test client, sessions, CLI runner, context in tests |
| [guides/deployment.md](guides/deployment.md) | Gunicorn, Waitress, mod_wsgi, uWSGI, gevent, ASGI, nginx/Apache, ProxyFix, async and gevent |
| [guides/security.md](guides/security.md) | Resource limits, XSS, CSRF, security headers, cookie options, host validation |
| [guides/extensions.md](guides/extensions.md) | Using extensions and writing them: `init_app`, config, `g` namespacing, guidelines |
| [guides/patterns.md](guides/patterns.md) | SQLite, SQLAlchemy, MongoEngine, uploads, Celery, caching, WTForms and other recipes |
| [guides/tutorial-flaskr.md](guides/tutorial-flaskr.md) | The Flaskr blog tutorial in reading order: factory, DB, auth, blog, packaging, tests, deploy |
| [cheatsheet.md](cheatsheet.md) | Commands and code snippets from across the docs |

## Not covered by this skill

- `docs/api.rst` is mostly Sphinx `autoclass`/`autofunction` directives, so
  the full method signatures and docstrings (which live in the source) were
  not extracted. Only the hand-written parts are here: converters,
  `add_url_rule` parameters, the signal list, and view-function attributes.
- The changelog (`CHANGES.rst`) and the license text are pulled in by
  `include` directives and were not extracted.

Files in this skill

  • SKILL.md8.9 KB
  • cheatsheet.md7.4 KB
  • guides/app-structure.md10 KB
  • guides/cli.md4.4 KB
  • guides/configuration.md6.8 KB
  • guides/deployment.md6.9 KB
  • guides/errors-logging-debugging.md6.1 KB
  • guides/extensions.md4.6 KB
  • guides/getting-started.md3.3 KB
  • guides/patterns.md6.6 KB
  • guides/routing-and-views.md7.7 KB
  • guides/security.md5 KB
  • guides/templates-and-frontend.md6.6 KB
  • guides/testing.md4.7 KB
  • guides/tutorial-flaskr.md5.6 KB
  • source.json6.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.