CORS Error
Browser Security - Cross-origin request blocked
CORS Errors Explained
What is CORS?
CORS (Cross-Origin Resource Sharing) is a browser security feature that restricts web pages from making requests to a different domain than the one serving the page. When blocked, you'll see an error like:
Access to fetch at 'https://api.example.com/data' from origin
'https://myapp.com' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present.
Why Does This Happen?
Same-Origin Policy
Browsers block requests where origin (protocol + domain + port) differs between the page and the API. This prevents malicious sites from stealing data.
https://app.com→https://api.comBlockedhttp://app.com→https://app.comBlocked (different protocol)https://app.com:3000→https://app.com:8080Blocked (different port)
Common CORS Errors
Missing Access-Control-Allow-Origin
Server doesn't include the required CORS header in response.
Preflight Request Failed
OPTIONS request returned an error or wrong headers.
Credentials Not Supported
Trying to send cookies but server doesn't allow credentials.
Server-Side Fixes
Express.js
const cors = require('cors');
// Allow all origins (development only!)
app.use(cors());
// Production: specific origins
app.use(cors({
origin: ['https://myapp.com', 'https://www.myapp.com'],
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE']
}));
Nginx
location /api/ {
add_header 'Access-Control-Allow-Origin' 'https://myapp.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 86400;
return 204;
}
}
Django
# settings.py
INSTALLED_APPS = [..., 'corsheaders']
MIDDLEWARE = ['corsheaders.middleware.CorsMiddleware', ...]
CORS_ALLOWED_ORIGINS = [
'https://myapp.com',
]
CORS_ALLOW_CREDENTIALS = True
Required Headers
| Header | Purpose |
|---|---|
| Access-Control-Allow-Origin | Which origins can access |
| Access-Control-Allow-Methods | Allowed HTTP methods |
| Access-Control-Allow-Headers | Allowed request headers |
| Access-Control-Allow-Credentials | Allow cookies/auth headers |
Preflight Requests
For non-simple requests (custom headers, PUT/DELETE methods), browsers send an OPTIONS request first:
# Browser sends preflight
OPTIONS /api/users HTTP/1.1
Origin: https://myapp.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization
# Server must respond with:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
Common Mistakes
- Using * with credentials: Can't use wildcard origin with cookies
- Missing OPTIONS handler: Preflight returns 404 or 405
- Headers not exposed: Custom response headers need Access-Control-Expose-Headers
- Caching issues: Browser cached old CORS response
Debugging Tips
- Check the Network tab for the actual response headers
- Look for the preflight OPTIONS request
- Test with curl (bypasses CORS):
curl -I https://api.example.com - Server-side errors may also cause CORS to fail (fix the 500 first)
How to Monitor for CORS Issues
CORS errors are client-side but often stem from server misconfigurations. UptimeSignal monitors your API endpoints to ensure they're responding correctly. If your API returns a 500 error, the browser may show a CORS error instead of the actual server error. Monitor your API health to catch the root cause.
Frequently Asked Questions
What is a CORS error?
Access-Control-Allow-Origin header. It's a browser security feature (Same-Origin Policy) that prevents malicious sites from making requests to your API on behalf of users.How do I fix CORS errors?
Access-Control-Allow-Origin to your server response. For a specific domain: set it to https://yourfrontend.com. For all origins: use * (not recommended for authenticated APIs). In Express.js use the cors() middleware. Also handle preflight OPTIONS requests.What is a CORS preflight request?
Access-Control-Allow-Methods, Access-Control-Allow-Headers, and Access-Control-Allow-Origin headers. Return 204 No Content for OPTIONS.Why do CORS errors only happen in browsers?
How do I allow credentials with CORS?
Access-Control-Allow-Credentials: true and specify the exact origin (not *). In fetch: use credentials: 'include'. The wildcard * is not allowed with credentials -- you must echo back the specific requesting origin.