Skip to content

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:

python
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.

For production applications, you should be more restrictive with your CORS settings:

python
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.

python
# 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:

python
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:

python
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':

python
# 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:

bash
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

  1. Be specific with allowed origins: Avoid using "*" when possible
  2. Limit allowed methods: Only allow HTTP methods that your API actually uses
  3. Restrict headers: Only allow necessary headers
  4. Handle errors properly: Ensure CORS headers are included even in error responses
  5. 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.