CORS, explained
Browsers enforce the same-origin policy: a script on https://app.example.com cannot read a response from https://api.example.com unless the API opts in. CORS is that opt-in, defined today in the WHATWG Fetch standard. It only constrains browsers; curl, servers and mobile apps ignore it.
For requests that are not "simple" (for example a PUT, a JSON Content-Type or a custom Authorization header), the browser first sends a preflight OPTIONS request, and the server answers with what it allows:
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 600A wildcard Access-Control-Allow-Origin: * cannot be combined with credentials such as cookies, and reflecting any incoming Origin back is a security hole. Keep an explicit allow-list of origins and send Vary: Origin when the response depends on it.
CORS is not authentication or a firewall: it decides which browser pages may read a response, not who may call the API. Tightening a CORS policy can still break browser clients overnight, so treat it as part of the API contract.
Related terms
- API security: API security is the practice of protecting APIs from misuse and attack with authentication, authorization, input validation, rate limits and monitoring.
- HTTP status codes: HTTP status codes are three-digit numbers a server returns with each response to signal its outcome, grouped in five classes from 1xx to 5xx.
- Breaking change: A breaking change is a change to an API that causes a correctly written client, which worked before, to fail or behave differently without modifying its code.