You've seen it: "Access to XMLHttpRequest at X from origin Y has been blocked by CORS policy." CORS errors are cryptic and frustrating, but they exist for good reason. Here's how to understand and fix them.
What Is CORS?
CORS (Cross-Origin Resource Sharing) is a security mechanism that controls which websites can access resources from another website. It prevents malicious scripts from stealing data.
Example Scenario
You're on bank.com (origin A). A malicious script tries to fetch your bank data from your-bank.com/api/accounts (origin B). CORS blocks this — the bank's API didn't give bank.com permission to access it.
Same-Origin vs Cross-Origin
Two URLs are same-origin if they share protocol, domain, and port:
https://example.com (origin A)
https://example.com/page ✓ Same origin
https://example.com:3000 ✗ Different port
http://example.com ✗ Different protocol
https://example.co.uk ✗ Different domain
https://api.example.com ✗ Subdomain
How CORS Works
1. Preflight Request (OPTIONS)
Browser sends OPTIONS request to check if cross-origin request is allowed:
OPTIONS /api/data HTTP/1.1
Origin: https://myapp.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
2. Server Response
Server responds with CORS headers:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 3600
3. Actual Request
If allowed, browser sends the real request.
Common CORS Headers
From Server (Response Headers)
- Access-Control-Allow-Origin: Which origins can access
- Access-Control-Allow-Methods: Allowed HTTP methods
- Access-Control-Allow-Headers: Allowed request headers
- Access-Control-Max-Age: Cache preflight response (seconds)
- Access-Control-Allow-Credentials: Allow cookies/auth
From Browser (Request Headers)
- Origin: The origin making the request
- Access-Control-Request-Method: Method the request will use
- Access-Control-Request-Headers: Headers the request will include
Fixing CORS Errors
1. Allow Specific Origin
# Server-side (Express.js)
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'https://myapp.com');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
next();
});
2. Allow All Origins (Development Only)
res.setHeader('Access-Control-Allow-Origin', '*');
⚠️ WARNING: Never use `*` in production. Any website can access your API.
3. Using Middleware
Node.js with CORS Package
const cors = require('cors');
const whitelist = ['https://myapp.com', 'https://example.com'];
app.use(cors({
origin: whitelist,
credentials: true
}));
Python/Flask
from flask_cors import CORS
CORS(app, resources={r"/api/*": {"origins": ["https://myapp.com"]}})
PHP
header('Access-Control-Allow-Origin: https://myapp.com');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
Testing CORS
Use our CORS Tester to validate cross-origin requests:
- Enter your API endpoint
- Specify origin to test from
- Select method and headers
- See if CORS allows it
Common CORS Mistakes
1. Allowing All Origins
`Access-Control-Allow-Origin: *` + credentials = security hole.
2. Forgetting to Allow Credentials
// Doesn't work: cookies aren't sent
fetch('https://api.example.com', {
credentials: 'include'
});
Server needs:
Access-Control-Allow-Credentials: true
3. Not Handling Preflight (OPTIONS)
Server must respond to OPTIONS requests with 200. If it returns 404, CORS fails.
4. Wrong Origin Format
Use full URL: `https://example.com`, not `example.com` or `https://example.com/`
CORS Doesn't Exist in Real Browsers
CORS is a browser security feature. Server-to-server requests don't have CORS issues:
// Browser request - CORS applies
fetch('https://api.example.com/data');
// Server-to-server - CORS doesn't apply
curl https://api.example.com/data
Troubleshooting CORS in DevTools
- Open DevTools (F12)
- Go to Network tab
- Find the failed request
- Check Response Headers for `Access-Control-Allow-Origin`
- If missing, server needs to add it
Pro Tips
- Whitelist specific origins, not `*`
- Test CORS before deployment
- Cache preflight responses (higher Max-Age)
- Use HTTPS in production (required for credentials)
- Monitor CORS errors in logs
Conclusion
CORS isn't a bug — it's security. Once you understand the handshake, fixing CORS errors is straightforward. Whitelist your trusted origins, allow the right headers, and test thoroughly. Your API will be both secure and accessible.
Comments
Leave a Comment
No comments yet. Be the first to comment!