Last modified: Dec 01, 2025 By Alexander Williams
Add CORS Middleware to FastAPI Apps
Modern web apps often separate frontend and backend.
The frontend runs in a browser. The backend serves data via an API.
They frequently live on different domains or ports.
This setup triggers browser security rules.
These rules block cross-origin requests by default.
You need CORS to allow these requests safely.
CORS stands for Cross-Origin Resource Sharing.
It is a security feature implemented by browsers.
It controls how web pages in one domain request resources from another.
Without CORS, your FastAPI backend will reject frontend requests.
This causes frustrating errors for developers.
This guide shows you how to fix it.
We will add CORS middleware to a FastAPI application.
You will learn to configure it for security and flexibility.
What is CORS and Why It Matters
CORS is a browser security mechanism.
It uses HTTP headers to manage cross-origin requests.
A "cross-origin" request has a different origin.
Origin means protocol, domain, and port combined.
For example, `http://localhost:3000` and `http://localhost:8000` are different origins.
The browser sends a "preflight" request for complex operations.
This preflight uses the HTTP OPTIONS method.
It asks the server if the actual request is allowed.
The server must respond with the correct CORS headers.
These headers tell the browser which origins, methods, and headers are permitted.
FastAPI does not include CORS headers by default.
You must add middleware to handle them.
This is crucial for any API consumed by a separate frontend.
It's a key step in building a production-ready API.
Setting Up a Basic FastAPI Application
First, ensure you have FastAPI installed.
If you get an error, see our guide on Fix Python ImportError: No Module Named FastAPI.
Create a new Python file, like `main.py`.
We'll start with a simple API endpoint.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello from FastAPI"}
Run the app with Uvicorn.
uvicorn main:app --reload --port 8000
Your API is now running on `http://localhost:8000`.
Try accessing it from a browser. It works fine.
Now, create a simple HTML frontend on a different port.
Save this as `index.html` and serve it on port 3000.
# A simple Python server for the frontend (optional)
import http.server
import socketserver
handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("", 3000), handler) as httpd:
print("Serving at port 3000")
httpd.serve_forever()
The HTML file tries to fetch data from the API.
It will fail due to CORS policy.
Open the browser console. You will see an error.
The error states the request was blocked.
The reason is a missing CORS header.
Let's fix this by adding the middleware.
Adding CORS Middleware to FastAPI
FastAPI provides a built-in CORS middleware class.
You need to import it from `fastapi.middleware.cors`.
Then, add it to your application using app.add_middleware.
Here is the basic implementation.
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"], # Your frontend origin
allow_credentials=True,
allow_methods=["*"], # Allows all methods
allow_headers=["*"], # Allows all headers
)
@app.get("/")
def read_root():
return {"message": "Hello from FastAPI with CORS!"}
Restart your FastAPI server.
Now, reload your frontend page on port 3000.
The request should succeed.
The browser console error will be gone.
The middleware injects the correct headers into every response.
This allows the browser to accept the data.
Understanding CORS Middleware Parameters
The CORSMiddleware class is highly configurable.
Let's break down the key parameters for security.
allow_origins: A list of origins permitted to access the resource.
You should specify exact origins in production.
Using `["*"]` is convenient but insecure for credentialed requests.
allow_origin_regex: A regex pattern for matching origins.
Useful for allowing a dynamic set of subdomains.
allow_methods: A list of HTTP methods allowed.
Default is `["GET"]`. `["*"]` allows all common methods.
allow_headers: A list of HTTP headers allowed in requests.
`["*"]` allows all headers. Specify needed ones for better security.
allow_credentials: Indicates if cookies/credentials can be included.
If `True`, `allow_origins` cannot be `["*"]`. It must be specific.
expose_headers: Headers exposed to the browser.
max_age: How long preflight response can be cached (seconds).
Example: Secure Production Configuration
Here is a more realistic, secure configuration.
It assumes your frontend is hosted on `https://myapp.com`.
You are also developing locally.
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# List of allowed origins
origins = [
"https://myapp.com",
"https://www.myapp.com",
"http://localhost:3000",
"http://127.0.0.1:3000",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["Authorization", "Content-Type", "Accept"],
expose_headers=["X-Custom-Header"],
max_age=600, # Cache preflight for 10 minutes
)
@app.get("/data")
def get_data():
return {"data": [1, 2, 3]}
This setup is specific and secure.
It only allows listed origins and explicit methods.
It defines which headers can be sent.
Always tailor these settings to your app's needs.
Never use overly permissive wildcards in production.
Testing Your CORS Configuration
Testing is vital. Use browser tools or command line.
Open your frontend and check the network tab.
Look for the `OPTIONS` preflight request.
Inspect its response headers.
You should see `Access-Control-Allow-Origin` with your origin.
You can also test with `curl`.
# Send an OPTIONS preflight request
curl -X OPTIONS http://localhost:8000/data \
-H "Origin: http://localhost:3000" \
-H "Access-Control-Request-Method: GET" \
-v
The `-v` flag shows verbose output including headers.
Look for the CORS headers in the response.
For comprehensive API testing, consider using Test FastAPI Endpoints with pytest and TestClient.
This ensures your endpoints and CORS work correctly.
Common CORS Issues and Solutions
Even with middleware, issues can arise.
Problem: Credentials not sent with request.
Solution: Set `allow_credentials=True` and specify exact origins.
Also, ensure your frontend request includes `credentials: 'include'`.
Problem: Specific headers are blocked.
Solution: Add those headers to `allow_headers` list.
Problem: Preflight cache not working.
Solution: Increase the `max_age` value appropriately.
Problem: Wildcard (`*`) origin with credentials.
Solution: This is not allowed by the specification. Use a list of origins.
Always check the browser console for detailed error messages.
They often tell you exactly which header is missing or incorrect.
Integrating CORS in a Larger Project
In a real project, your API does more.
You might have authentication, databases, and file uploads.
CORS is just one piece of the security puzzle.
For example, you might add FastAPI JWT Authentication.
The CORS middleware must allow the `Authorization` header.
Our configuration example already includes it.
Similarly, for file uploads or WebSockets, ensure methods and headers are set.
Always structure your code for clarity.
Keep middleware registration near the top of your main app file.
This makes it easy to find and modify.
Conclusion
Adding CORS middleware to FastAPI is straightforward.
It is essential for modern web development.
It allows your backend API to communicate with frontend clients securely.
Use the built-in CORSMiddleware class.
Configure it carefully for your environment.
Be specific in production. Avoid overly permissive wildcards.
Test your configuration thoroughly.
Combine CORS with other security best practices.
With CORS enabled, your FastAPI app is ready for real-world use.
You can now focus on building great features.
For your next steps, learn how to Deploy FastAPI with Docker for Production.