CORS Preflight Requests
A CORS preflight is the OPTIONS request a browser sends before certain cross-origin calls, checking which methods, headers, and origins the server permits before risking the real request.
Definition
A preflight is an OPTIONS request the browser issues automatically before a cross-origin request that is not simple. It carries Origin, Access-Control-Request-Method, and Access-Control-Request-Headers, and the server must answer with matching allow headers or the actual request is never sent. Responses can be cached via Access-Control-Max-Age.
Context and scope
Triggered by cross-origin calls with custom headers, JSON content types, methods beyond GET, HEAD, and POST, or credentialed requests in some configurations. Every SPA calling a separate API domain deals with preflights.
Common misconceptions
- The preflight is sent by the server or the app — the browser generates and enforces it, nothing else
- Adding a custom header is free — it converts a simple request into a preflighted one, adding a round trip
- Preflight failures mean the server rejected the request — the browser blocks it before the request is ever sent
Anti-patterns
- Reflecting any requested header in Access-Control-Allow-Headers with credentials enabled
- Setting Access-Control-Max-Age to zero and forcing a preflight on every single API call
- Disabling preflight caching in production because a stale cache caused one incident
Related concepts
Related examples
Authoritative source
https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS
What it is
Before a non-simple cross-origin request, the browser asks permission: an OPTIONS call describing the method and headers the real request wants. If the answer does not allow them, the browser discards the real request without touching the network. This is enforcement in the client, not a server-side gate.
How it works
A request is simple only for classic methods with safelisted headers and form-like content types. Custom headers such as an API key, JSON bodies, or DELETE all force a preflight. Successful preflight responses are cached for the number of seconds in Access-Control-Max-Age, so the cost is amortized rather than per-call.
When to care
High-latency mobile APIs feel preflight cost most, since each cold preflight adds a full round trip before the real work starts. Keep Max-Age generous and use a stable set of allowed headers. Public read-only APIs can use simpler request shapes to skip preflight entirely.
Pitfalls
Reflection of the Origin and requested headers looks permissive but combines dangerously with credentials. A preflight failure surfaces as a CORS error even though the real request was never attempted. Debug by reading the OPTIONS exchange in devtools network logs, not by guessing at the actual request.