Fix CORS Error in Express.js
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