What is a Preflight Request
Grace Collins
Solutions Engineer · Leapcell
What is a Preflight Request?
We all know that common browser requests include POST, GET, PUT, DELETE, etc. However, have you ever noticed that there is another request type called OPTIONS?
Generally speaking, a preflight request refers to an OPTIONS request. It is automatically sent by the browser when it determines that an upcoming request might have an unpredictable impact on the server. Through the preflight request, the browser can determine whether the server allows the upcoming request to proceed. Only if permission is granted will the browser execute the actual request.
Usually, preflight requests do not require user management or intervention—they are automatically handled by the browser and the server.
A preflight request typically looks like this:
Access-Control-Request-Headers: x-requested-with
Access-Control-Request-Method: POST
Origin: http://preflight.example.com
The three key fields in this request are:
- Origin – Represents the request's source.
- Access-Control-Request-Method – Specifies the actual HTTP method being requested.
- Access-Control-Request-Headers – Lists the actual request headers.
The response to a preflight request usually looks like this:
Access-Control-Allow-Headers: Content-Type, Content-Length, Authorization, Accept, X-Requested-With
Access-Control-Allow-Origin: http://preflight.example.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Access-Control-Max-Age: 86400
The most important fields in the response are:
- Access-Control-Allow-Origin – Specifies which origins are allowed to access the resource.
- Access-Control-Allow-Headers – Lists the allowed custom request headers.
- Access-Control-Allow-Methods – Specifies the permitted HTTP methods.
If any aspect of the actual request does not fall within the allowed range, the browser will automatically cancel the request and throw a CORS error.
The last field, Access-Control-Max-Age, defines the lifespan of the preflight request. During this period, the browser will not send another preflight request for the same request.
When is a Preflight Request Triggered?
A preflight request is part of the CORS (Cross-Origin Resource Sharing) specification, and all modern browsers implement it. However, some browsers extend the standard with additional features.
According to MDN, there are five conditions that must all be satisfied to avoid triggering a preflight request. If any of these conditions is not met, the browser will send a preflight request before executing the actual request to prevent unpredictable server behavior.
The five conditions are:
- Request Method Restriction – The request method must be GET, POST, or HEAD.
- Request Header Restriction – Only the following nine headers are allowed:
Accept
Accept-Language
Content-Language
Content-Type
DPR
Downlink
Save-Data
Viewport-Width
Width
- Content-Type Restriction – The
Content-Type
can only be one of:text/plain
multipart/form-data
application/x-www-form-urlencoded
- XMLHttpRequestUpload Object Restriction – No event listeners should be registered on the
XMLHttpRequestUpload
object. - ReadableStream Object Restriction – The request must not include a
ReadableStream
object.
For most developers, the main constraints are the first three rules. The most common triggers for preflight requests are:
- Using custom request headers
- Using a
Content-Type
that is not among the allowed types
Why Do Preflight Requests Exist?
Now that we understand what a preflight request is and when it is triggered, let’s explore why it was designed.
The preflight request is an essential part of CORS and serves to enhance web security by restricting cross-origin access.
Without CORS, all web resources would be accessible by any website unless explicitly restricted. For example:
- Website A could use JavaScript to access Website B's cookies and private data.
- Website B could do the same to Website A.
CORS prevents unauthorized cross-origin requests by default. Only whitelisted origins, methods, and headers can access protected resources. This security model ensures that websites requiring protection can control access while maintaining flexibility when cross-origin access is needed.
Preflight requests help prevent security risks by:
- Ensuring that the server explicitly allows cross-origin requests before executing them.
- Allowing older servers that do not support CORS to block unauthorized requests before any sensitive data is exposed.
If you’re interested in CORS security mechanisms, you can refer to MDN’s documentation for a deeper dive.
How to Properly Support Preflight Requests
If you’re a backend developer, you may need to configure your server to handle preflight requests properly.
To support preflight requests, focus on three key response headers:
-
Access-Control-Allow-Origin
- This specifies which origins are allowed to access the resource.
- If the API is public (e.g., an image upload service), you may set this to
"*"
(allowing all origins). - However, using
"*"
reduces security, so it is generally not recommended.
-
Access-Control-Allow-Headers
- This specifies which custom request headers are permitted.
- Servers should explicitly list only the headers they support.
-
Access-Control-Allow-Methods
- This specifies which HTTP methods are allowed.
- Instead of
"*"
, it's safer to list only the required methods.
Recommended Configuration:
ctx.set('Access-Control-Allow-Origin', '<allowed-origin>'); ctx.set('Access-Control-Allow-Credentials', true); ctx.set('Access-Control-Max-Age', 86400000); ctx.set('Access-Control-Allow-Methods', 'OPTIONS, HEAD, <actual-method>'); ctx.set( 'Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With' );
Additionally, if you are using router.post()
or other shorthand methods in your backend framework, you must explicitly handle OPTIONS requests to ensure the browser can process them correctly.
A common approach is to return HTTP 200 (OK) or HTTP 204 (No Content) for OPTIONS requests:
if (ctx.request.method === 'OPTIONS') { ctx.response.status = 204; }
Note: While any 2xx status code is acceptable, 204 No Content
is the most common choice.
The Relationship Between Preflight Requests and CORS
According to MDN, preflight requests are part of the CORS standard. They only occur when a request is cross-origin.
This means:
- Cross-origin requests do not always trigger a preflight request.
- If a preflight request occurs, the request is definitely cross-origin.
This makes sense because preflight requests exist to secure cross-origin interactions. Within the same origin, backend and frontend developers usually have a mutual understanding of API security, making preflight checks unnecessary.
This is a classic example of balancing security and convenience—choosing a compromise that improves security without making development too restrictive.
We are Leapcell, your top choice for hosting backend projects.
Leapcell is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:
Multi-Language Support
- Develop with Node.js, Python, Go, or Rust.
Deploy unlimited projects for free
- pay only for usage — no requests, no charges.
Unbeatable Cost Efficiency
- Pay-as-you-go with no idle charges.
- Example: $25 supports 6.94M requests at a 60ms average response time.
Streamlined Developer Experience
- Intuitive UI for effortless setup.
- Fully automated CI/CD pipelines and GitOps integration.
- Real-time metrics and logging for actionable insights.
Effortless Scalability and High Performance
- Auto-scaling to handle high concurrency with ease.
- Zero operational overhead — just focus on building.
Explore more in the Documentation!
Follow us on X: @LeapcellHQ