CORS

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.

3 min read Level 2/5 #nodejs#express#cors
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 →