Glossary

CORS (Cross-Origin Resource Sharing)

A browser security mechanism that restricts web pages from making requests to a different origin than the one that served the page. Servers opt into cross-origin access by returning specific HTTP headers that tell the browser which origins, methods, and headers are permitted.

CORS (Cross-Origin Resource Sharing) is a browser security feature that prevents web pages from making requests to a different origin (domain, protocol, or port) than the one that loaded the page. This is called the Same-Origin Policy. CORS provides a controlled way for servers to relax this restriction by declaring which external origins are allowed.

What Is an Origin?

An origin is the combination of protocol + hostname + port:

https://app.example.com:443  ← origin
│       │               │
protocol hostname        port

These are all different origins from https://app.example.com:

  • http://app.example.com — different protocol
  • https://api.example.com — different subdomain
  • https://app.example.com:8080 — different port

Simple vs Preflight Requests

Simple requests (GET/POST with basic headers) are sent directly — the browser checks CORS on the response.

Preflighted requests (PUT/DELETE, or requests with custom headers like Authorization) trigger an automatic OPTIONS request first. The server must respond with CORS headers before the actual request is sent.

OPTIONS /api/users HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Authorization, Content-Type

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Max-Age: 86400

CORS Response Headers

Access-Control-Allow-Origin: https://app.example.com
# Or wildcard (cannot be used with credentials):
Access-Control-Allow-Origin: *

Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type, X-Api-Key
Access-Control-Allow-Credentials: true   # send cookies cross-origin
Access-Control-Max-Age: 86400            # cache preflight for 24 hours
Access-Control-Expose-Headers: X-Total-Count  # expose to JS

Express.js CORS Setup

import cors from "cors";

// Allow specific origin
app.use(cors({
  origin: "https://app.example.com",
  methods: ["GET", "POST", "PUT", "DELETE"],
  allowedHeaders: ["Authorization", "Content-Type"],
  credentials: true,       // required for cookies
  maxAge: 86400,
}));

// Allow multiple origins
const allowedOrigins = ["https://app.example.com", "https://admin.example.com"];
app.use(cors({
  origin: (origin, callback) => {
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error("Not allowed by CORS"));
    }
  },
}));

Common CORS Errors

ErrorCauseFix
"No 'Access-Control-Allow-Origin' header"Server not sending CORS headersAdd CORS middleware
"CORS policy: credential flag is 'true'"* used with credentialsUse specific origin, not *
"Method not allowed by CORS"Method not in Allow-MethodsAdd method to allowedMethods
Preflight 404No OPTIONS handlerHandle OPTIONS or use cors() middleware
  • URL Encoding — encoding used in cross-origin request URLs
  • JWT — tokens commonly sent in cross-origin Authorization headers

Tools

  • CORS Header Tester — inspect CORS headers on any URL