What is CORS?
CORS (Cross-Origin Resource Sharing) is a security feature implemented by web browsers that controls how web pages can request resources from a different domain (origin) than the one that served the page. It's a relaxation of the Same-Origin Policy (SOP).
The Same-Origin Policy
By default, browsers block requests to different origins for security:
| URL | Same Origin as https://example.com? |
|---|---|
https://example.com/api |
✅ Yes |
https://api.example.com |
❌ No (different subdomain) |
http://example.com |
❌ No (different protocol) |
https://example.com:8080 |
❌ No (different port) |
How CORS Works
Simple Requests
For GET, HEAD, or POST with simple headers, the browser sends the request directly:
GET /api/data HTTP/1.1
Host: api.example.com
Origin: https://myapp.com
Server responds with CORS headers:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://myapp.com
Preflight Requests
For complex requests (PUT, DELETE, custom headers), the browser first sends an OPTIONS request:
OPTIONS /api/data HTTP/1.1
Host: api.example.com
Origin: https://myapp.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, Authorization
Server responds:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
CORS Headers
| Header | Purpose |
|---|---|
Access-Control-Allow-Origin |
Allowed origins (* or specific) |
Access-Control-Allow-Methods |
Allowed HTTP methods |
Access-Control-Allow-Headers |
Allowed request headers |
Access-Control-Allow-Credentials |
Allow cookies/auth |
Access-Control-Max-Age |
Cache preflight (seconds) |
Access-Control-Expose-Headers |
Headers client can access |
Server Configuration
FastAPI (Python)
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["https://myapp.com"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
Express.js (Node)
const cors = require("cors");
app.use(cors({
origin: "https://myapp.com",
credentials: true
}));
Nginx
location /api/ {
add_header Access-Control-Allow-Origin "https://myapp.com";
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE";
add_header Access-Control-Allow-Headers "Authorization, Content-Type";
}
Common CORS Errors
Access to fetch at 'https://api.example.com' from origin
'https://myapp.com' has been blocked by CORS policy
Solutions:
- Configure server to allow the origin
- Use a proxy in development
- Ensure credentials mode matches server config
Security Best Practices
- ❌ Don't use
Access-Control-Allow-Origin: *with credentials - ✅ Whitelist specific origins in production
- ✅ Validate Origin header server-side
- ✅ Use
Access-Control-Max-Ageto reduce preflight requests