DEV Community

Alireza Hassankhani
Alireza Hassankhani

Posted on

What Is a Simple Request and When Does the Browser Send a Preflight Request?

In the previous article, we learned that browsers sometimes send an OPTIONS request before the actual Cross-Origin request. This process is known as a CORS Preflight Request.

But does this happen for every request?

The answer is no.

Browsers only perform a Preflight Request when the request does not qualify as a Simple Request.

What Is a Simple Request?

A Simple Request is a Cross-Origin request that satisfies a specific set of conditions defined by the Fetch specification.

Since these requests are considered low risk, the browser sends them directly without performing a Preflight check.

CORS rules still apply to the response, but no preliminary OPTIONS request is needed.

Requirements for a Simple Request

A request is considered simple only if all of the following conditions are met.

1. HTTP Method

The request method must be one of:

  • GET
  • HEAD
  • POST

Methods such as PUT, PATCH, and DELETE automatically trigger a Preflight Request.

2. Request Headers

The request may only include CORS-safelisted request headers, such as:

  • Accept
  • Accept-Language
  • Content-Language

Adding headers like:

Authorization: Bearer <token>
Enter fullscreen mode Exit fullscreen mode

or

X-API-Key: 123456
Enter fullscreen mode Exit fullscreen mode

causes the browser to perform a Preflight Request.

3. Content-Type

If the request has a body, its Content-Type must be one of:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

Using a content type such as:

application/json
Enter fullscreen mode Exit fullscreen mode

makes the request non-simple and triggers a Preflight Request.

This is one of the most common reasons developers see OPTIONS requests in modern web applications.

Examples

This request is simple:

fetch("/users")
Enter fullscreen mode Exit fullscreen mode

No Preflight Request is sent.

This request is also simple:

fetch("/login", {
  method: "POST",
  headers: {
    "Content-Type": "text/plain"
  }
})
Enter fullscreen mode Exit fullscreen mode

Again, no Preflight is required.

However, this request is not simple:

fetch("/login", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  }
})
Enter fullscreen mode Exit fullscreen mode

The browser first sends an OPTIONS request.

The same happens here:

fetch("/profile", {
  headers: {
    "Authorization": "Bearer token"
  }
})
Enter fullscreen mode Exit fullscreen mode

Because the Authorization header is not CORS-safelisted, a Preflight Request is required.

Summary

A browser sends a Preflight Request only when a Cross-Origin request does not meet the requirements of a Simple Request.

The most common triggers are:

  • Using methods such as PUT, PATCH, or DELETE
  • Including non-safelisted headers such as Authorization
  • Using content types like application/json

This is why seeing an OPTIONS request before the actual request is completely normal in many modern APIs.

Top comments (0)