GuidesDIAGNOSE
Fix a CORS preflight failure
Browsers fire an automatic OPTIONS probe before sending complex cross-origin requests. When that handshake fails, the browser blocks the real request before any data transmits over the wire. Pinpointing the missing header or status code in the Network tab clarifies the required fix.
Requests that trigger a preflight
Browsers skip the preflight check only for safelisted requests. A cross-origin request qualifies when it uses GET, HEAD, or a POST with safelisted headers and a content type of application/x-www-form-urlencoded, multipart/form-data, or text/plain.
- HTTP methods outside the safelist, including
PUT,DELETE, andPATCH. - Headers outside the safelist, such as
AuthorizationorX-Api-Key. - A
Content-Typeheader set toapplication/json. - Streaming request bodies created with a
ReadableStream.
Standard JSON payloads trigger this probe immediately. Sending an application/json body requires the browser to verify server permissions before transmitting the payload.
Inspect the OPTIONS probe in developer tools
Open the browser developer tools and inspect the Network panel for the failing OPTIONS entry. A passing options preflight returns a 2xx status code alongside Access-Control-Allow-Origin, an Access-Control-Allow-Methods header listing the requested method, and Access-Control-Allow-Headers matching any custom request headers.
> OPTIONS /data HTTP/2
> origin: https://your-site.com
> access-control-request-method: PUT
> access-control-request-headers: x-api-key
< HTTP/2 204
< access-control-allow-origin: https://your-site.com
< access-control-allow-methods: PUT
< access-control-allow-headers: x-api-key
< access-control-max-age: 600
# Any of the four response headers missing or wrong = preflight failed,
# and the browser never sends the PUT.Browsers drop the subsequent operation whenever this handshake fails. If the probe yields a non-2xx code, the console reports that it does not have HTTP ok status. When headers mismatch, the console states that the response to preflight request doesn't pass access control check, and the real request never leaves the client.
Common causes of preflight failures
Preflight failures stem from server-side routing, authentication policies, or network intermediaries. Inspecting the raw OPTIONS response reveals which condition aborted the exchange.
- Missing
OPTIONShandlers return a404 Not Foundor405 Method Not Allowedresponse. - Authentication middleware rejects the probe with
401or403because preflight requests do not carry credentials. - The
Access-Control-Allow-Headersheader omits a requested client header likeAuthorization. - Redirect responses on
OPTIONScalls fail immediately under the Fetch specification. - Omitting
Access-Control-Max-Ageleaves only the five-second browser default, so theOPTIONSprobe repeats before nearly every request. - Edge proxies or CDNs strip the outgoing
Access-Control-*headers before transmission.
Handle the OPTIONS probe on your server
Configure your backend router to handle OPTIONS requests explicitly by returning an HTTP 204 No Content status. Exempt all OPTIONS routes from authentication middleware so unauthenticated probes succeed. Set Access-Control-Allow-Origin, provide explicit method names in Access-Control-Allow-Methods, and enumerate all custom client headers inside Access-Control-Allow-Headers. Add Access-Control-Max-Age: 86400 to allow browsers to cache the preflight verdict across subsequent calls.
Handling preflight errors on third-party endpoints
Client-side code cannot alter or bypass preflight checks mandated by third-party APIs. For public resources, route requests through cors.dev using GET or HEAD methods to keep the call safelisted and skip the preflight probe. Because the proxy operator can observe traffic routed through it, use this approach for public data only. Test upstream server responses with the header checker to evaluate their CORS configuration.
Good questions.
Can I turn the preflight off?
Browser engines enforce preflight checks automatically whenever a cross-origin call includes non-safelisted methods, headers, or body types. You cannot disable this mechanism via client JavaScript or fetch flags. Structuring the call to use GET or standard form encodings avoids triggering the check.
Does the browser cache preflights?
Browsers cache preflight results only when the server returns an Access-Control-Max-Age header specifying the duration in seconds. WebKit caps this value at 600 seconds, while Chromium engines permit values up to 7200 seconds. If this header is absent, the browser applies a five-second default cache, so effectively every non-safelisted request issues a fresh OPTIONS probe.
Why is there no preflight in Postman?
Postman acts as a direct HTTP client outside the browser security sandbox. Preflight probes are browser-specific requirements defined by the Fetch specification to protect web sessions from cross-origin exploits. Direct backend tools like Postman and curl send HTTP methods directly without origin checks, as explained in the Postman comparison.