Letting Browsers From Other Origins Call Your API
CORS
CORS is the browser's same-origin policy in action. The API decides which origins (and methods, headers) it allows.
What you'll learn
- Use the `cors` middleware
- Allow specific origins, not "*"
- Handle credentials
A browser fetching api.example.com from a page at example.com
is cross-origin. By default the browser blocks the response —
unless the API tells it “this origin is allowed.”
That’s CORS: the API sets headers; the browser respects them.
Just Use the Package
npm install cors import express from "express";
import cors from "cors";
const app = express();
app.use(cors({
origin: "https://app.example.com",
credentials: true,
})); That’s 90% of CORS.
Allowing Multiple Origins
const allowed = ["https://app.example.com", "https://staging.example.com"];
app.use(cors({
origin: (origin, cb) => {
if (!origin || allowed.includes(origin)) cb(null, true);
else cb(new Error("not allowed"));
},
credentials: true,
})); Origin * Caveat
app.use(cors()); // origin: "*" — public API, no credentials * works for public APIs. The big caveat: you cannot combine *
with credentials. If your frontend sends cookies or auth headers,
you must list explicit origins.
Preflight Requests
For “non-simple” requests (custom headers, PUT/DELETE, etc.), the
browser sends an OPTIONS preflight first. The cors middleware
handles it automatically.
If you’re doing manual CORS, you need to handle OPTIONS yourself:
res.setHeader("access-control-allow-origin", origin);
res.setHeader("access-control-allow-methods", "GET, POST, PUT, DELETE");
res.setHeader("access-control-allow-headers", "content-type, authorization");
res.setHeader("access-control-max-age", "86400"); Common Mistakes
- Allowing
*then trying to send cookies (blocked by browser) - Forgetting to add a custom header to
allow-headers(x-csrf,authorization) - Treating CORS as a security feature on the server (it’s not — it protects browser users, not your API)
Your API still needs auth, rate limiting, etc. CORS just decides which sites in someone’s browser can call you.
Error Handling →