What Is CORS and How to Fix It
CORS explained: same-origin policy, preflight requests, headers, and how to fix cross-origin errors.
What Is CORS?
CORS (Cross-Origin Resource Sharing) is a browser mechanism that allows web pages to access resources from different domains/origins securely.
Without CORS, browser enforces same-origin policy: scripts from example.com cannot access API from api.example.com. CORS relaxes this restriction when properly configured.
Same-Origin Policy
Same origin = protocol + domain + port must match exactly.
How CORS Works
Browser sends preflight request
OPTIONS request with origin header
Server responds with CORS headers
Access-Control-Allow-Origin, Access-Control-Allow-Methods
Browser checks response
Verifies requesting origin is allowed
Browser sends actual request
Only if preflight succeeds
Common CORS Headers
Access-Control-Allow-Origin
* or https://example.com
Access-Control-Allow-Methods
GET, POST, PUT, DELETE
Access-Control-Allow-Headers
Content-Type, Authorization
Access-Control-Allow-Credentials
true (allow cookies)
CORS Headers Detailed Explanation
Access-Control-Allow-Origin
Specifies which origins can access the resource. Use '*' for public APIs. Use specific domain for sensitive operations. Can only have one value or '*'.
Access-Control-Allow-Methods
HTTP methods allowed on the resource. If omitted, browser assumes only GET and HEAD. Example: GET, POST, PUT, DELETE, PATCH.
Access-Control-Allow-Headers
Request headers the browser can send. Must include custom headers like Authorization, X-API-Key. Usually includes Content-Type, Accept.
Access-Control-Allow-Credentials
Allow credentials (cookies, auth headers) in cross-origin requests. Only works with specific origin, not '*'. Client must also set credentials: 'include'.
Access-Control-Max-Age
Seconds browser can cache preflight response. Reduces preflight requests. Example: 3600 = 1 hour. Be careful with long values when API changes frequently.
Access-Control-Expose-Headers
Which response headers are exposed to browser. By default, only CORS-safe headers exposed. Example: X-Total-Count, X-Page-Number.
Common CORS Errors and Solutions
No 'Access-Control-Allow-Origin' header
Backend must send CORS headers. Configure your server/framework to include Access-Control-Allow-Origin header in responses. Add middleware or configuration.
Credentials are included but origin is '*'
Cannot use '*' with credentials. Specify exact origin (e.g., https://example.com) and set Access-Control-Allow-Credentials: true.
Authorization header blocked
Authorization not in default safe headers. Server must include Authorization in Access-Control-Allow-Headers header.
Preflight request failed
Preflight (OPTIONS) returned error code. Check if OPTIONS method is allowed. Verify preflight responds with correct CORS headers.
Custom headers being blocked
Custom headers need explicit Access-Control-Allow-Headers. Add custom headers like X-API-Key or X-Request-ID to the list.
CORS Configuration Examples
Node.js/Express
const cors = require('cors');
// Allow all origins
app.use(cors());
// Allow specific origin
app.use(cors({
origin: 'https://example.com',
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));Python/Flask
from flask_cors import CORS, cross_origin
# Allow all origins
CORS(app)
# Allow specific origin
CORS(app, resources={
r"/api/*": {
"origins": "https://example.com",
"methods": ["GET", "POST", "PUT", "DELETE"],
"allow_headers": ["Content-Type", "Authorization"]
}
})CORS Preflight Request Deep Dive
What triggers a preflight? Browser automatically sends preflight for:
- • HTTP methods other than GET, HEAD, POST
- • Custom headers (Authorization, X-API-Key, etc.)
- • Content-Type other than form-urlencoded, form-data, text/plain
- • Credentials in requests (cookies, auth)
Preflight Flow: Browser sends OPTIONS request → Server responds with CORS headers → Browser checks if allowed → Only then sends actual request.
Example Preflight Request Headers:
OPTIONS /api/data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization, Content-Type
CORS Security Best Practices
Never use '*' with credentials
Always specify exact origin when allowing credentials. Wildcard + credentials is not allowed by browsers.
Validate origin on backend
Don't just trust the Origin header. Validate it against allowed list. Origin can be forged by attackers.
Limit exposed headers
Only expose headers clients actually need. Don't expose sensitive internal headers.
Use credentials: 'include' carefully
Sending credentials cross-origin exposes cookies to attacks. Only use when necessary and with trusted origins.
Set appropriate Max-Age
Don't cache preflight responses too long (max 1 hour recommended) as API endpoints may change.
Whitelist origins explicitly
Don't allow all origins unless API is public and has no authentication. Use specific domain list.
Audit CORS configuration
Regularly review CORS settings. Overly permissive CORS can expose APIs to unauthorized access.
CORS FAQ
Is CORS a server-side or client-side issue?
CORS is enforced by the browser. Server sends CORS headers to tell browser if request is allowed. It's not a server blocking request, but browser blocking response.
Can I bypass CORS with a proxy?
Yes, same-origin proxy works because browser only sees requests to same origin. But this is a workaround, not a solution. Fix CORS on the actual API.
Why does the browser block CORS requests?
Security: Prevents malicious websites from stealing data from other sites without permission. Protects users' sensitive information (bank data, emails, etc).
Do API calls from backend (server-to-server) need CORS?
No. CORS only applies to browser requests. Server-to-server calls bypass CORS because servers don't enforce same-origin policy.
How do I test CORS locally?
Start dev server on different ports (localhost:3000 frontend, localhost:8000 API). Browser treats different ports as different origins.
Related Concepts
Related Tools
HTTP Status Codes Guide
Understand CORS error responses.
OAuth 2.0 Guide
Authentication in cross-origin API calls.