Fix CORS Error in Express.js
Updated April 2026
Your Express server is returning 200. The browser is blocking it anyway. That is CORS โ the server responded but did not tell the browser the request was allowed. One middleware call fixes it.
Install and apply cors middleware
npm install cors
const express = require('express');
const cors = require('cors');
const app = express();
// Development โ allows all origins (never use in production)
app.use(cors());
// Production โ lock it to your frontend domain
app.use(cors({ origin: 'https://app.example.com', credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization']
}));
app.get('/api/data', (req, res) => res.json({ ok: true }));
app.listen(3000);
Put app.use(cors()) before your route definitions. Middleware runs in declaration order โ routes defined before the cors() call will not get CORS headers.
If you are sending cookies or auth headers
When your frontend sends credentials: 'include', the wildcard origin stops working. The browser spec forbids * with credentials. You need an explicit origin.
// Breaks when frontend uses credentials: 'include'
app.use(cors({ origin: '*', credentials: true })); // โ
// Works
app.use(cors({ origin: 'https://app.example.com', credentials: true
})); // โ
If OPTIONS preflight is failing
Browsers send an OPTIONS request before POST, PUT, or DELETE when custom headers are present. Add an explicit OPTIONS handler before the main cors() call.
app.options('*', cors()); // Handle all preflight requests
app.use(cors({ origin: 'https://app.example.com' }));
Multiple allowed origins
const allowed = ['https://app.example.com', 'https://staging.example.com'];
app.use(cors({ origin: function(origin, callback) { if (!origin || allowed.includes(origin)) { callback(null, origin); } else { callback(new Error('Not allowed by CORS')); } }, credentials: true
}));
// Add Vary: Origin so CDNs cache per-origin correctly
app.use((req, res, next) => { res.vary('Origin'); next(); });
Per-route CORS
If you only need CORS on specific routes, pass the cors middleware directly to each route:
const corsOpts = { origin: 'https://app.example.com' };
app.get('/api/public', cors(corsOpts), (req, res) => res.json({ data: 'ok' }));
app.post('/api/submit', cors(corsOpts), (req, res) => res.json({ status: 'received' }));
Not sure if your CORS config is correct? CORSFixer sends a real OPTIONS preflight to your API and shows exactly what headers are missing or wrong.
Test your CORS config live โ CORSFixer