CORS in FastAPI
Cross-Origin Resource Sharing (CORS) is a security feature implemented by web browsers to prevent malicious websites from accessing resources from other domains without permission. When building APIs with FastAPI, you'll often need to configure CORS to allow your frontend applications to communicate with your backend.
Basic CORS Configuration
The most common approach to enable CORS in FastAPI is using the built-in CORSMiddleware
. Here's a minimal working example:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# Configure CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Allow all origins
allow_credentials=True,
allow_methods=["*"], # Allow all methods
allow_headers=["*"], # Allow all headers
)
@app.get("/")
async def main():
return {"message": "Hello World"}
WARNING
Allowing "*"
for allow_origins
when allow_credentials=True
is not permitted by browsers. For production applications, always specify the exact origins you want to allow.
Recommended Production Configuration
For production applications, you should be more restrictive with your CORS settings:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# List of allowed origins
origins = [
"http://localhost:3000", # React development server
"https://yourdomain.com", # Production domain
"https://www.yourdomain.com",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["Authorization", "Content-Type"],
)
Common Issues and Solutions
CORS Not Working with Errors
INFO
CORS middleware only handles CORS headers. If your server returns an error (like 500 Internal Server Error), the CORS headers might not be included in the response.
# This will return a 500 error without CORS headers
@app.get("/error")
async def error_endpoint():
# Missing await causes internal server error
data = some_async_function() # Should be: await some_async_function()
return data
Always ensure your endpoints handle errors properly and return valid responses.
Multiple FastAPI Instances
If you accidentally create multiple FastAPI instances, CORS might not work as expected:
app = FastAPI()
app.add_middleware(CORSMiddleware, allow_origins=["*"])
# ... later in code ...
app = FastAPI() # This overwrites the previous instance!
Exposing Custom Headers
If your API returns custom headers that need to be accessible to the frontend:
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
expose_headers=["Custom-Header", "X-Total-Count"],
)
Local File Origin Edge Case
When testing from local files (file:// protocol), the origin becomes 'null'
:
# For local file testing (not recommended for production)
app.add_middleware(
CORSMiddleware,
allow_origins=['null'],
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*']
)
Security Warning
Allowing 'null'
origin has security implications and should only be used for development and testing purposes.
Testing CORS Configuration
You can test your CORS configuration using curl to inspect the response headers:
curl -v -H "Origin: http://localhost:3000" http://localhost:8000
Look for the following headers in the response:
Access-Control-Allow-Origin
Access-Control-Allow-Credentials
Access-Control-Expose-Headers
Best Practices
- Be specific with allowed origins: Avoid using
"*"
when possible - Limit allowed methods: Only allow HTTP methods that your API actually uses
- Restrict headers: Only allow necessary headers
- Handle errors properly: Ensure CORS headers are included even in error responses
- Test thoroughly: Verify CORS works across different browsers and environments
By following these guidelines, you can properly configure CORS in your FastAPI applications while maintaining security and functionality.