FastAPI CORS (Env Config)
A lightweight Python library (version 0.0.6) that provides a simplified, environment variable-driven configuration for CORS settings in FastAPI applications. It acts as a wrapper around FastAPI's native `CORSMiddleware` (from Starlette), allowing developers to manage CORS policies such as allowed origins, methods, headers, and credentials through environment variables rather than direct code configuration.
Common errors
-
Access to fetch at 'http://localhost:8000/...' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
cause The backend FastAPI application is not configured to allow requests from the origin 'http://localhost:3000' (or the specified frontend origin). This is the most common CORS error.fixEnsure the `CORS_ALLOW_ORIGINS` environment variable (or equivalent if `fastapi-cors` isn't used) correctly includes the exact origin of your frontend (e.g., `CORS_ALLOW_ORIGINS='http://localhost:3000'` ). Remember to restart your FastAPI application after changing environment variables. -
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
cause You are attempting to allow credentials (cookies, HTTP auth headers) from a frontend while simultaneously allowing requests from any origin (`*`), which is a security risk and forbidden by the CORS specification.fixIf `CORS_ALLOW_CREDENTIALS` is set to 'true', then `CORS_ALLOW_ORIGINS` must be a comma-separated list of specific origins (e.g., `'http://localhost:3000,https://app.yourdomain.com'`). Do not use `'*'`. -
Failed to load resource: net::ERR_FAILED (or similar network error on OPTIONS request)
cause This often indicates a failed CORS 'preflight' request (an `OPTIONS` HTTP method request sent by the browser before the actual request). This can be due to disallowed methods, headers, or a general network/server issue.fixCheck that `CORS_ALLOW_METHODS` includes the method being used (e.g., `POST`, `PUT`) and `CORS_ALLOW_HEADERS` includes any custom headers being sent. Also, ensure the FastAPI app is running and accessible.
Warnings
- gotcha Do not confuse `fastapi-cors.CORS` with `fastapi.middleware.cors.CORSMiddleware`. While `fastapi-cors` uses the latter internally, its API is different and relies on environment variables for configuration.
- breaking Using `allow_credentials=True` (set via `CORS_ALLOW_CREDENTIALS='true'`) with `allow_origins=['*']` (set via `CORS_ALLOW_ORIGINS='*'`) is a security violation according to the CORS specification and will be rejected by browsers.
- gotcha CORS middleware order is critical. The `CORS` instance (which adds the `CORSMiddleware`) must be added early in your FastAPI application's lifecycle, typically before any custom middleware or routers. Otherwise, some requests (especially those triggering exceptions) might bypass CORS headers.
- gotcha Browser caching can cause persistent CORS errors even after fixing your backend configuration. The browser might have cached a preflight response indicating no access.
Install
-
pip install fastapi-cors
Imports
- FastAPI
from fastapi import FastAPI
- CORS
from fastapi.middleware.cors import CORSMiddleware
from fastapi_cors import CORS
Quickstart
import os
from fastapi import FastAPI
from fastapi_cors import CORS
# Example of setting environment variables (usually done in a .env file or deployment config)
# For local testing, you can uncomment these or use python-dotenv
os.environ['CORS_ALLOW_ORIGINS'] = 'http://localhost:3000,https://example.com'
os.environ['CORS_ALLOW_METHODS'] = 'GET,POST'
os.environ['CORS_ALLOW_CREDENTIALS'] = 'true'
app = FastAPI()
# Initialize fastapi-cors. It reads settings from environment variables automatically.
# You can pass include_health_check=False if not needed.
CORS(app)
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.post("/items/")
def create_item(item: dict):
return {"item": item, "message": "Item created"}
# To run this app: uvicorn your_module_name:app --reload
# Make sure to set the environment variables before running.