🛡️ FastAPI Security Headers
The missing security headers middleware for FastAPI. Protect your API against XSS, clickjacking, MIME sniffing, and OWASP Top 10 web vulnerabilities with secure-by-default configurations and zero overhead.
⚡ Highlights
- 🚀 Zero Performance Overhead (Pure ASGI): Bypasses heavy Starlette wrappers. Injects headers directly into ASGI raw message streams without body buffering.
- 📦 Zero Dependencies: Uses only Python's standard library (
dataclasses,typing). Zero bloat in your dependency tree. - ⚡ Pre-compiled Bytes: Header tuples are encoded to
(bytes, bytes)once at application startup, running in nanoseconds per request. - 🎛️ Out-of-the-box Presets: Ready-made configurations for APIs, high-compliance environments, and mixed apps.
- 📖 Swagger / ReDoc Friendly: Includes a dedicated preset that won't break your interactive
/docsdocumentation. - 🔄 Route-Aware: Intelligently respects custom headers set by individual route handlers unless explicitly configured to override.
- 🌐 WebSockets & Streaming Safe: Passes WebSockets and large streaming responses (
StreamingResponse) seamlessly.
📦 Installation
pip install fastapi-security-headers
🚀 Quickstart (30 Seconds)
Add the middleware to your FastAPI application in just 2 lines of code:
from fastapi import FastAPI
from fastapi_security_headers import SecurityHeadersMiddleware
app = FastAPI()
# Enable OWASP recommended security headers with secure defaults
app.add_middleware(SecurityHeadersMiddleware)
@app.get("/")
async def root():
return {"message": "Protected by fastapi-security-headers"}
🛡️ The Security Headers Matrix
By default, fastapi-security-headers turns an F score on security scanners into an A+:
| HTTP Header | Default Value | Attack Vector Mitigated |
|---|---|---|
X-Content-Type-Options |
nosniff |
MIME-Sniffing: Prevents browsers from guessing content types, blocking malicious scripts disguised as images or JSON. |
X-Frame-Options |
DENY |
Clickjacking: Prevents external sites from embedding your API inside hidden <iframe> overlays. |
X-XSS-Protection |
0 |
Audit Vulnerabilities: Disables legacy buggy XSS filters as recommended by OWASP. |
Strict-Transport-Security |
max-age=31536000; includeSubDomains |
SSL Stripping / MitM: Enforces HTTPS for all future visits over the next 365 days. |
Referrer-Policy |
strict-origin-when-cross-origin |
Data Leakage: Prevents leaking sensitive URL query parameters to third-party domains. |
Permissions-Policy |
geolocation=(), microphone=(), camera=() |
Feature Abuse: Disables unused device APIs (GPS, camera, microphone). |
Cross-Origin-Opener-Policy |
same-origin |
Side-Channel Attacks: Isolates browsing context against Spectre-style attacks. |
Cross-Origin-Resource-Policy |
same-origin |
Cross-Origin Reads: Blocks external origins from reading your API responses. |
🎛️ Built-in Presets
1. Presets.swagger_friendly() (Recommended for FastAPI)
Enforces strict Content Security Policy (CSP) while allowing necessary CDNs (cdn.jsdelivr.net) and assets for Swagger UI (/docs) and ReDoc (/redoc).
from fastapi import FastAPI
from fastapi_security_headers import SecurityHeadersMiddleware, Presets
app = FastAPI()
app.add_middleware(SecurityHeadersMiddleware, config=Presets.swagger_friendly())
2. Presets.api() (For Headless JSON APIs)
Hardened specifically for pure JSON microservices. Disallows all frames, scripts, and media loading:
app.add_middleware(SecurityHeadersMiddleware, config=Presets.api())
3. Presets.strict() (High-Compliance / Banking)
Maximum security posture for financial, health, and enterprise apps. Enforces 2-year HSTS with preload, require-corp, and strict CSP:
app.add_middleware(SecurityHeadersMiddleware, config=Presets.strict())
4. Presets.default()
Balanced baseline for general web applications.
🔧 Custom Configuration
You can fully customize headers or disable any specific header by setting it to None:
from fastapi import FastAPI
from fastapi_security_headers import SecurityHeadersMiddleware, SecurityHeadersConfig, HSTSConfig
config = SecurityHeadersConfig(
# Customize HSTS (e.g. disable on localhost or enable preload)
strict_transport_security=HSTSConfig(max_age=63072000, include_subdomains=True, preload=True),
# Allow iframes from the same origin
x_frame_options="SAMEORIGIN",
# Add custom enterprise security headers
custom_headers={
"X-Permitted-Cross-Domain-Policies": "none",
}
)
app = FastAPI()
app.add_middleware(SecurityHeadersMiddleware, config=config)
Route-Level Overrides
By default (override=False), if a specific endpoint returns its own custom header, the middleware respects it and does not duplicate it:
from fastapi.responses import JSONResponse
@app.get("/embeddable-widget")
async def widget():
# This endpoint specifically permits embedding
return JSONResponse(
content={"data": "widget"},
headers={"x-frame-options": "SAMEORIGIN"}
)
To force middleware headers across all endpoints regardless of route return values, set override=True:
app.add_middleware(SecurityHeadersMiddleware, override=True)
🧪 Testing
Run the test suite locally with pytest:
pip install -e ".[dev]"
pytest -v
🤝 Contributing
Contributions, issues, and feature requests are welcome! Feel free to check the issues page.
👤 Author
Alejandro Tacoronte González
- GitHub: @aletgdev
- LinkedIn: Alejandro Tacoronte
- Portfolio: portfolio.alejandrotg.es
If this project helps you secure your FastAPI applications, consider buying a coffee! ☕
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
Metadata
Release files for fastapi-security-headers 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| fastapi_security_headers-0.1.1.tar.gz | 15.4 kB | Without provenance | Details for fastapi_security_headers-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| fastapi_security_headers-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for fastapi_security_headers-0.1.1-py3-none-any.whl |
Total release size: 27.4 kB
Release files / fastapi_security_headers-0.1.1.tar.gz
| Download URL | fastapi_security_headers-0.1.1.tar.gz |
|---|---|
| Size | 15.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f8fd32889323cfe9ff5c7b32ea4f06b6f6199b842b7c9be13e17fc6359127da2
|
|
BLAKE2b-256 checksum How to use checksums |
a741c8e0cdced4ed112cfbbd785e77f4736a5811f794ac5becf9286f5e90646a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / fastapi_security_headers-0.1.1-py3-none-any.whl
| Download URL | fastapi_security_headers-0.1.1-py3-none-any.whl |
|---|---|
| Size | 12.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cde26a1a649d33751f2ac9f30c7317d6322c30ab19ed679b2220b28ba48f0023
|
|
BLAKE2b-256 checksum How to use checksums |
594ec44433077763141de46f7d6a424372f536dfb3e9f6bebb4e70464c62f528
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Security for fastapi-security-headers 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.