How to fix Error: CORS preflight request failed (no 'Access-Control-Allow-Origin') in Node.js
A CORS preflight request failed because the server didn't respond with the required Access-Control-Allow-Origin header. This happens when your Express server doesn't properly configure CORS headers for complex requests (PUT, DELETE, POST with custom headers).
Quick fix
Fixes Error: CORS preflight request failed (no 'Access-Control-Allow-Origin')
npm install cors- Install the cors package
- Apply CORS globally to all routes
- Configure CORS for specific origins (production)
- Explicitly handle OPTIONS requests if using selective CORS
npm install corsError: CORS preflight request failed (no 'Access-Control-Allow-Origin')
npm install corsWhat this error means
When browsers make 'complex' HTTP requests (anything other than simple GET/HEAD/POST, or requests with custom headers), they automatically send a preflight OPTIONS request first to check if the server allows the cross-origin request. If your server doesn't respond to this OPTIONS request with the required CORS headers—specifically Access-Control-Allow-Origin—the browser blocks the actual request. This is a browser security feature to prevent unauthorized cross-origin access to your API.
Typical symptoms
- API requests fail with 'blocked by CORS policy' error in the browser console
- Preflight OPTIONS requests return 404 or 500 errors
- The error mentions missing 'Access-Control-Allow-Origin' header
- Simple requests (GET/HEAD/POST) work fine, but DELETE/PUT/PATCH fail
- Custom headers like Authorization are causing requests to fail
- The error appears only when calling API from a different origin (domain/port)
Common causes
- The Express server doesn't have CORS middleware installed or configured
- CORS middleware is installed but not applied globally with app.use(cors())
- OPTIONS requests are not being handled (missing app.options('*', cors()))
- CORS is only applied to specific routes, but you're hitting a different route
- The allowed origin list doesn't include your frontend's domain
- A reverse proxy or load balancer is stripping CORS headers from responses
How to fix "Error: CORS preflight request failed (no 'Access-Control-Allow-Origin')"
First, ensure you have the cors middleware installed in your Node.js project:
npm install corsThis is the standard package for handling CORS in Express.
Add the CORS middleware to your Express app at the top level, before defining routes:
const express = require('express');
const cors = require('cors');
const app = express();
// Apply CORS to all routes
app.use(cors());
// Your routes go here
app.get('/api/data', (req, res) => {
res.json({ message: 'Hello' });
});
app.listen(3000);This allows requests from any origin. If you only tested with GET requests and they worked, the issue is likely that you're missing CORS headers for complex requests.
For production, allow only trusted domains:
const corsOptions = {
origin: ['https://yourdomain.com', 'https://app.yourdomain.com'],
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
allowedHeaders: ['Content-Type', 'Authorization'],
optionsSuccessStatus: 200
};
app.use(cors(corsOptions));The optionsSuccessStatus: 200 is important for legacy browsers that fail on 204 responses.
If you only want CORS on specific routes, you must explicitly handle OPTIONS:
app.options('/api/data', cors(corsOptions)); // For specific route
app.post('/api/data', (req, res) => {
res.json({ message: 'Success' });
});
// Or for all routes
app.options('*', cors(corsOptions));Without this, preflight OPTIONS requests will return 404 and fail.
Check the Network tab in your browser's DevTools:
1. Look for the OPTIONS request that appears before your actual request
2. Click on it and check the Response headers
3. Verify that Access-Control-Allow-Origin is present
4. Verify Access-Control-Allow-Methods includes your HTTP method (POST, DELETE, etc.)
5. If the OPTIONS request returns 404 or 500, your middleware isn't catching it properly
The OPTIONS response should include:
- Access-Control-Allow-Origin: https://yourdomain.com (or *)
- Access-Control-Allow-Methods: GET, POST, PUT, DELETE
- Access-Control-Allow-Headers: Content-Type, Authorization
Ensure CORS middleware is applied BEFORE route handlers:
// WRONG - routes defined before cors
app.get('/api/data', handler);
app.use(cors()); // Too late!
// CORRECT - cors applied first
app.use(cors());
app.get('/api/data', handler);Middleware in Express is executed in order. CORS must be applied before your routes are defined.
Advanced notes
Preflight request behavior: Browsers automatically send OPTIONS preflight requests for 'complex' requests—anything with HTTP methods other than GET/HEAD/POST, or requests with custom headers like Authorization. You cannot disable this from client-side code; it's a browser security feature.
Credentials and wildcard origins: If you use Access-Control-Allow-Credentials: true, you cannot use Access-Control-Allow-Origin: *. You must specify exact origins.
Development vs Production: During development, you might use app.use(cors()) to allow all origins. Always restrict to specific origins in production.
Reverse proxies: If your Express app is behind Nginx or another reverse proxy, the proxy might be stripping CORS headers. Configure the proxy to pass them through.
Custom middleware conflicts: If you have other middleware that sends responses early (like authentication checks), they might bypass CORS headers. Ensure CORS is applied globally before any route-specific middleware.
Frequently asked questions
- What does "Error: CORS preflight request failed (no 'Access-Control-Allow-Origin'" mean?
- When browsers make 'complex' HTTP requests (anything other than simple GET/HEAD/POST, or requests with custom headers), they automatically send a preflight OPTIONS request first to check if the server allows the cross-origin request. If your server doesn't respond to this OPTIONS request with the required CORS headers—specifically Access-Control-Allow-Origin—the browser blocks the actual request. This is a browser security feature to prevent unauthorized cross-origin access to your API.
- How do I fix "Error: CORS preflight request failed (no 'Access-Control-Allow-Origin'"?
- A CORS preflight request failed because the server didn't respond with the required Access-Control-Allow-Origin header. This happens when your Express server doesn't properly configure CORS headers for complex requests (PUT, DELETE, POST with custom headers).
- What causes "Error: CORS preflight request failed (no 'Access-Control-Allow-Origin'"?
- The Express server doesn't have CORS middleware installed or configured CORS middleware is installed but not applied globally with app.use(cors()) OPTIONS requests are not being handled (missing app.options('*', cors()))
- Is the "Error: CORS preflight request failed (no 'Access-Control-Allow-Origin'" error serious?
- Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.
Official resources & further reading
- 📚Node.js Official Documentation
- 📖Cross-Origin Resource Sharing (CORS) - MDN(Official Docs)
- 📖Express cors middleware - Express.js(Official Docs)