FastAPI CORS Settings for Frontend Apps
CORS stands for Cross-Origin Resource Sharing. When your frontend (React, Vue, or plain HTML) runs on one domain and your FastAPI backend runs on another, the browser blocks the requests by default. CORS headers tell the browser which origins are allowed to talk to your API.
Why the Browser Blocks Cross-Origin Requests
Frontend at: http://localhost:3000
Backend at: http://localhost:8000
Browser rule: a page from origin A cannot read responses
from origin B unless origin B explicitly allows it.
Without CORS setup:
Frontend makes request → Backend responds
Browser sees different origin → blocks the response
Frontend gets "CORS error" — never sees the data
With CORS setup:
Backend adds: Access-Control-Allow-Origin: http://localhost:3000
Browser allows the response through
Frontend reads the data successfully
What Counts as a Different Origin
Same origin: http://example.com/page1 http://example.com/api ← same scheme + domain + port Different origin (any of these differ): https://example.com ← different scheme (http vs https) http://api.example.com ← different subdomain http://example.com:8000 ← different port http://otherdomain.com ← different domain
Adding CORS Middleware to FastAPI
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000", "https://myfrontend.com"],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["Authorization", "Content-Type"]
)
CORS Options Explained
allow_origins → list of allowed frontend domains allow_credentials → allow cookies and auth headers (set True for JWT) allow_methods → which HTTP methods are permitted allow_headers → which request headers the frontend can send
Allowing All Origins (Development Only)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], ← any domain allowed
allow_methods=["*"],
allow_headers=["*"]
)
Use "*" only during local development. In production, list only the domains your frontend actually uses. An open wildcard means anyone's website can call your API with your users' credentials.
The Preflight Request
Before sending a real request, the browser sends a preflight OPTIONS request to check if the server allows it:
Browser checks before every "complex" request:
Step 1: Browser sends OPTIONS /users
Origin: http://localhost:3000
Access-Control-Request-Method: POST
Step 2: FastAPI CORS middleware responds:
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: POST
Step 3: Browser sees approval → sends the real POST request
FastAPI's CORSMiddleware handles preflight requests automatically.
CORS and allow_credentials
allow_credentials=True means:
→ Cookies are included in cross-origin requests
→ Authorization headers pass through
→ IMPORTANT: allow_origins cannot be ["*"] when credentials=True
You must list exact origins
Correct:
allow_origins=["https://myfrontend.com"]
allow_credentials=True
Wrong (browser will reject):
allow_origins=["*"]
allow_credentials=True
Environment-Based CORS Configuration
Use different allowed origins for development and production:
import os
ALLOWED_ORIGINS = os.getenv(
"ALLOWED_ORIGINS",
"http://localhost:3000" ← default for development
).split(",")
app.add_middleware(
CORSMiddleware,
allow_origins=ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"]
)
Set the environment variable in production to your real frontend domain.
Key Points
- CORS errors happen when a frontend on one origin requests data from a backend on a different origin.
- Add
CORSMiddlewareto your FastAPI app to allow specific origins. - List exact domains in
allow_originsfor production — never use"*"in production. - Set
allow_credentials=Trueif your frontend sends cookies or Authorization headers. - FastAPI handles browser preflight OPTIONS requests automatically through the middleware.
