CORS Preflight Request

An OPTIONS request the browser sends before a cross-origin request to check permissions.

“Simple” GET/HEAD/POST with safelisted headers skips preflight. Anything with custom headers, JSON content types, PUT/PATCH/DELETE, or credentials in certain combinations triggers a preflight: the browser sends OPTIONS with Access-Control-Request-Method and sometimes Access-Control-Request-Headers. The server answers with allowed methods and headers plus max-age for caching the result.

Why developers care

If your framework returns 404 for OPTIONS, or your gateway strips CORS on OPTIONS only, every mutating API call from the browser fails before the real request fires. Many “works in curl” bugs are missing preflight handlers. You also need Vary: Origin when responses differ by caller so CDNs do not cache one user’s CORS headers for everyone.

Example

OPTIONS /api/profile HTTP/1.1 Host: api.example.com 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, PUT, OPTIONS Access-Control-Allow-Headers: authorization, content-type Access-Control-Max-Age: 86400

Spec

Fetch — CORS-preflight fetch

Test preflight with CORSFixer →