Flask-WTF

Simple integration of Flask and WTForms with built-in CSRF, file upload, and reCAPTCHA support

Library
PyPI
v1.3.0
1,508stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
70/100Good
Development Activity60
Maintenance44
Community88
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
75/100Good
Architecture74
Code Quality80
Innovation60
Learning Curve85

Flask-WTF wires WTForms into Flask by binding form data automatically to flask.request.form/request.files, and layers on the pieces most Flask apps need but WTForms doesn’t provide out of the box: CSRF protection via CSRFProtect and generate_csrf(), secure file-upload fields, and reCAPTCHA integration.

Maintained under the Pallets ecosystem (the same organization behind Flask and Jinja), it is the de facto standard way to add HTML form handling and validation to a Flask application without hand-rolling CSRF tokens or file-upload validation yourself.

What You Get

  • FlaskForm, a WTForms Form subclass that auto-binds to flask.request.form/request.files
  • Built-in CSRF protection via CSRFProtect and generate_csrf()/validate_csrf()
  • A FileField/FileRequired/FileAllowed set of fields and validators for secure file uploads
  • reCAPTCHA field and widget integration for spam protection on public forms
  • i18n support for translating form labels/error messages via Flask-Babel

Common Use Cases

  • Adding CSRF-protected HTML forms (login, registration, contact) to a Flask app
  • Handling file upload forms with server-side validation of file type and presence
  • Protecting public-facing forms from spam using integrated reCAPTCHA fields
  • Building multi-language forms where labels and validation errors need translation

Under The Hood

Architecture - The package is a thin, focused integration layer: form.py defines FlaskForm, which overrides WTForms’ Meta class to source CSRF configuration from current_app.config and delegates CSRF validation to a _FlaskFormCSRF meta-class hook defined in csrf.py; csrf.py additionally exposes a standalone CSRFProtect Flask extension that can protect an entire app’s views (not just FlaskForm submissions) via a Flask Blueprint and before-request hook.

Tech Stack - A small, dependency-light Python package (~720 lines across src/flask_wtf/) built on pyproject.toml/hatchling, depending directly on flask, wtforms, werkzeug, markupsafe, and itsdangerous for signed CSRF tokens; no compiled extensions or heavy transitive dependencies.

Code Quality - Six test modules cover FlaskForm binding, CSRF validation (including token expiry via itsdangerous.SignatureExpired), and file-field validators; the codebase is small enough that each module maps to one concern (form.py, csrf.py, file.py, i18n.py, recaptcha/), keeping the surface easy to audit given its security-sensitive role (CSRF token generation/validation).

API Design - Subclassing FlaskForm instead of WTForms’ Form is the only change most users need to make; CSRF protection is on by default and configured entirely through Flask app config keys (WTF_CSRF_ENABLED, WTF_CSRF_SECRET_KEY), which keeps the API surface minimal and consistent with Flask’s own configuration conventions, at the cost of some “magic” for developers unfamiliar with how Flask config cascades into form behavior.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search