Why Is an OPTIONS Request Sent? (CORS Preflight Explained)
On This Page
In this article, you will learn why your browser sends an OPTIONS request before your actual API call, what triggers it, and how to fix it when it fails.
What Is an OPTIONS Request?
Your browser sends an OPTIONS request to ask the server: “Is this cross-origin request allowed?”
This is also called a preflight request — it’s part of the CORS (Cross-Origin Resource Sharing) mechanism. Before making the actual GET, POST, PUT, or DELETE call, the browser sends this lightweight check first.
The server responds with CORS headers that say which origins, methods, and headers are permitted. If the response is valid, the browser follows up with the real request. If not, it blocks the request entirely — and you see a CORS error in your console.
You cannot disable this from the frontend. It’s browser behavior, not something in your code.
What Triggers a Preflight Request
Not every cross-origin request triggers a preflight. The browser only sends one for “non-simple” requests — requests that go beyond what an HTML form could do natively.
A request is considered “simple” (no preflight) if all of these are true:
- Method is
GET,HEAD, orPOST - No custom headers (only CORS-safelisted headers like
Accept,Content-Language,Content-Type) Content-Typeis one of:application/x-www-form-urlencoded,multipart/form-data, ortext/plain
The moment you break any of these rules, the browser sends a preflight. The most common triggers:
- Setting
Content-Type: application/json(almost every modern API call) - Adding an
Authorizationheader - Using
PUT,PATCH, orDELETEmethods
In practice, almost every API call from a frontend app triggers a preflight.
What a Preflight Request Looks Like
The browser sends something like this:
OPTIONS /api/users HTTP/1.1Host: api.example.comOrigin: https://myapp.comAccess-Control-Request-Method: POSTAccess-Control-Request-Headers: Content-Type, AuthorizationThe server should respond with:
HTTP/1.1 204 No ContentAccess-Control-Allow-Origin: https://myapp.comAccess-Control-Allow-Methods: GET, POST, PUT, DELETEAccess-Control-Allow-Headers: Content-Type, AuthorizationAccess-Control-Max-Age: 86400That tells the browser: “Yes, https://myapp.com is allowed to make a POST with those headers.” The browser then proceeds with the actual request.
If the server returns a 405 Method Not Allowed, no CORS headers, or the wrong values — the browser kills the request before it even fires.
Can You Avoid Preflight Requests?
Sometimes, yes. If you can keep your requests “simple” (as defined above), the browser won’t send a preflight. That means using POST with Content-Type: text/plain and no custom headers.
But that’s usually impractical. You’d be warping your API design just to avoid an extra round trip.
A better approach: cache preflight responses. The Access-Control-Max-Age header tells the browser to remember the preflight result so it doesn’t ask again for a given endpoint. Set it to 86400 (24 hours) and most repeat requests skip the preflight entirely.
Why Your OPTIONS Request Is Failing
If your preflight is failing, the server either doesn’t handle OPTIONS at all (returns 404 or 405), is missing the required CORS headers, or the header values don’t match what your request actually sends.
If you control the server, configure CORS properly. If you don’t control the server, use Corsfix to fix the preflight error. Corsfix acts as a proxy — your request goes through a server that adds the correct CORS headers before returning the response to your browser.
// ❌ Direct call fails with preflight errorfetch("https://api.example.com/data");
// ✅ Corsfix handles CORS for youfetch("https://proxy.corsfix.com/?https://api.example.com/data");For local development, this works instantly without registration. For live websites, set up your domain (takes 30 seconds).
Conclusion
The browser sends an OPTIONS request as a preflight to check if a cross-origin request is allowed. Your server must respond with the correct Access-Control-Allow-* headers, or the browser blocks the real request. If you don’t control the server, use Corsfix to handle CORS for you. It’s free to get started, and you only need to upgrade when you go to production.