Cross-Origin Resource Sharing (CORS) is a browser security feature that restricts how resources on a web page can be requested from another domain. While CORS is essential for security, it often leads to frustrating errors when working with APIs, microservices, or cross-domain requests in JavaScript applications.
1. CORS Policy No ‘Access-Control-Allow-Origin’ Header Present
Error Message:
Access to fetch at 'https://api.example.com/data' from origin 'http://localhost:3000'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Why This Happens:
Your browser blocks the request because the API doesn’t include the Access-Control-Allow-Origin
header in the response. Without this header, the browser assumes the resource is restricted.
How to Fix:
Solution 1: Update Server to Allow CORS
If you control the server, modify the response headers to allow the request. Here’s how you can do it in Node.js (Express.js):
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*"); // Allow all origins
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
next();
});
- The
Access-Control-Allow-Origin: *
header allows any domain to access the resource. - Replace
*
with a specific domain (http://example.com
) for better security.
Solution 2: Configure CORS Middleware in Express
const cors = require('cors');
app.use(cors());
For fine-grained control, specify allowed origins:
app.use(cors({ origin: 'http://localhost:3000' }));
2. CORS Policy Blocks Preflight Requests
Error Message:
Response to preflight request doesn’t pass access control check:
It does not have HTTP ok status.
Why This Happens:
A preflight request (OPTIONS
method) is sent before the actual request when:
- The request uses non-simple headers like
Authorization
,Content-Type: application/json
. - The request is not a GET or POST request (e.g.,
PUT
,DELETE
).
If the server doesn’t handle OPTIONS requests, it will be blocked.
How to Fix:
Solution: Enable Preflight Response on the Server
Modify your backend to handle OPTIONS
requests properly:
app.options('*', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.sendStatus(204); // No Content
});
Now, your API will respond to preflight checks correctly.
3. CORS Policy Blocks Credentials Requests
Error Message:
Access to fetch at 'https://api.example.com/data' from origin 'http://localhost:3000'
has been blocked by CORS policy: Credentials flag is ‘true’, but ‘Access-Control-Allow-Origin’ is ‘*’.
Why This Happens:
- Your frontend is making a request with
credentials: 'include'
(e.g., cookies, sessions, authentication). - The server uses
Access-Control-Allow-Origin: *
, which doesn’t support credentials.
How to Fix:
Solution: Configure CORS for Credentials
Modify your backend:
app.use(cors({
origin: 'http://localhost:3000',
credentials: true
}));
Replace *
with the actual domain that should be allowed to send credentials.
4. Mismatched Protocols (HTTP vs. HTTPS)
Error Message:
Mixed Content: The page at 'https://myapp.com' was loaded over HTTPS,
but requested an insecure resource 'http://api.example.com/data'.
This request has been blocked.
Why This Happens:
- Your website runs on
HTTPS
, but your API runs onHTTP
. - Browsers block insecure (HTTP) requests from an
HTTPS
page.
How to Fix:
- Ensure the API runs on HTTPS.
- Update API calls from
http://
tohttps://
. - If local development requires HTTP, use secure tunnels like ngrok to expose an HTTPS endpoint.
5. CORS Blocks Redirects
Error Message:
Redirect from 'https://api.example.com/data' to 'https://new-api.example.com/data'
has been blocked by CORS policy.
Why This Happens:
- The API redirects the request, but the redirect response doesn’t include CORS headers.
How to Fix:
- On the backend, set CORS headers on redirected responses:
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
- If using
fetch()
, allow redirects:
fetch('https://api.example.com/data', { redirect: 'follow' });
6. Incorrect ‘Access-Control-Allow-Headers’ Configuration
Error Message:
Request header field 'Authorization' is not allowed by Access-Control-Allow-Headers in preflight response.
Why This Happens:
- Your request includes custom headers (
Authorization
,X-Requested-With
), but the server doesn’t allow them.
How to Fix:
Modify your backend to allow the required headers:
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
next();
});
7. Incorrect ‘Access-Control-Allow-Methods’ Configuration
Error Message:
Method PUT is not allowed by Access-Control-Allow-Methods in preflight response.
Why This Happens:
- The requested HTTP method (PUT, DELETE, PATCH) isn’t allowed by the server.
How to Fix:
Add the correct methods to your backend:
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
next();
});
Final Thoughts
CORS errors can be frustrating, but understanding why they happen helps you fix them quickly. Here’s a quick recap:
CORS Error | Fix |
---|---|
No ‘Access-Control-Allow-Origin’ | Add CORS headers on the server |
Blocks Preflight Requests | Handle OPTIONS requests properly |
Blocks Credentials Requests | Allow credentials with a specific origin |
Mixed Content (HTTP/HTTPS) | Use HTTPS for APIs |
Redirect Issues | Ensure CORS headers are set on redirects |
Header Restrictions | Allow necessary headers |
Method Restrictions | Allow required HTTP methods |
You may also like:
1) 5 Common Mistakes in Backend Optimization
2) 7 Tips for Boosting Your API Performance
3) How to Identify Bottlenecks in Your Backend
4) 8 Tools for Developing Scalable Backend Solutions
5) 5 Key Components of a Scalable Backend System
6) 6 Common Mistakes in Backend Architecture Design
7) 7 Essential Tips for Scalable Backend Architecture
8) Token-Based Authentication: Choosing Between JWT and Paseto for Modern Applications
9) API Rate Limiting and Abuse Prevention Strategies in Node.js for High-Traffic APIs
10) Can You Answer This Senior-Level JavaScript Promise Interview Question?
11) 5 Reasons JWT May Not Be the Best Choice
12) 7 Productivity Hacks I Stole From a Principal Software Engineer
13) 7 Common Mistakes in package.json Configuration
Read more blogs from Here
Share your experiences in the comments, and let’s discuss how to tackle them!
Follow me on Linkedin