Every web developer has stared at this error: "Access to fetch at 'https://api.example.com' from origin 'https://myapp.com' has been blocked by CORS policy." It's the most common API integration roadblock — and one of the most misunderstood. This guide explains what CORS actually protects, why it blocks your requests, and exactly how to fix it.
What CORS Actually Is
CORS (Cross-Origin Resource Sharing) is a browser security mechanism, not a server one. The browser blocks cross-origin requests by default to prevent malicious sites from reading your authenticated data from other sites. The server can opt in to cross-origin access by sending specific HTTP headers.
The key insight: CORS errors happen in the browser, not on the server. Your curl or Postman request works because those tools don't enforce CORS. The browser does.
The 4 CORS Headers That Matter
| Header | Purpose | Example |
|---|---|---|
Access-Control-Allow-Origin | Which origins can access | https://myapp.com or * |
Access-Control-Allow-Methods | Allowed HTTP methods | GET, POST, PUT, DELETE |
Access-Control-Allow-Headers | Allowed request headers | Content-Type, Authorization |
Access-Control-Allow-Credentials | Allow cookies/auth headers | true |
Common CORS Scenarios and Fixes
Scenario 1: Missing Allow-Origin Header
The API server doesn't include any CORS headers. Fix: Add Access-Control-Allow-Origin: * for public APIs, or specify your domain for authenticated ones.
Scenario 2: Preflight Request Fails
Browsers send an OPTIONS preflight for non-simple requests (those with custom headers, or methods other than GET/POST with standard content types). Fix: Handle OPTIONS requests on your server and return appropriate CORS headers.
Scenario 3: Credentials with Wildcard Origin
You can't use Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true. Fix: Specify the exact origin instead of the wildcard.
Scenario 4: Missing Headers in Allow-Headers
Your frontend sends Authorization or X-Custom-Header, but the server's Access-Control-Allow-Headers doesn't list them. Fix: Add the missing headers to the allow list.
Debugging with GetCodingTools
Use the browser Network panel or curl -i to inspect the response headers from the failing endpoint. Reproduce the preflight with an explicit Origin header and compare it with the real request; this reveals which CORS header is absent without pointing readers to a tool the site does not provide.
Quick Fix Reference
// Express.js middleware
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://myapp.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Credentials', 'true');
if (req.method === 'OPTIONS') return res.sendStatus(204);
next();
});
Remember: CORS is a browser feature, not a security boundary against server-to-server attacks. It protects your users, not your API. Always combine CORS with proper authentication and authorization.