DEV Community

Cover image for CORS, Preflight Requests, and Common Cross-Origin Issues
Sanjeev Sharma
Sanjeev Sharma Subscriber

Posted on

CORS, Preflight Requests, and Common Cross-Origin Issues

If you've been developing web apps for a while, there's a 99% chance you've encountered a CORS issue at least once. If you're a beginner, you probably found a one-line fix by Googling the exact error and moved on with your task. Today, with AI tools, you don’t even have to leave your IDE to get a solution.

But did you truly understand what the fix did? Why did the issue occur in the first place? If not, I promise that by the end of this post, you will.

Let’s dive in! 💪


What is CORS?

CORS, or Cross-Origin Resource Sharing, is a browser mechanism that restricts frontend code from making cross-origin requests. It’s not an issue per se but a security feature designed to protect users and websites.

The error you encounter typically occurs when your frontend and backend are deployed on separate domains (or subdomains).

CORS

In the example above, frontendcamp.in makes a request to api.dev.to. If api.dev.to doesn’t explicitly allow requests from other origins, the browser will block the request.

Why do browsers do that?
Browsers enforce the SOP or Same-Origin Policy, which dictates how a document or script from one origin can interact with resources on another. This prevents malicious websites from executing code on your site.

Two origins are considered the same if the protocol, port (if specified), and host match.

How to fix this issue?
To resolve this, the server must explicitly allow requests from the frontend’s origin.

For example, in the illustration above, api.dev.to should permit www.frontend.in to access its resources.

This can done by adding the following response header.

Access-Control-Allow-Origin: https://www.frontendcamp.in
Enter fullscreen mode Exit fullscreen mode

This header informs the browser that www.frontendcamp.in is authorized to access the resource.

Some developers use * as the header value, allowing requests from any origin. Avoid this unless you have a valid reason for doing so.

An alternate solution
You can’t always modify response headers. For instance, when requesting data from an external service, the above solution won’t work.

In such cases, a proxy server can be used.

CORS with Proxy server

This works because CORS is enforced only by browsers. With a proxy server in place, the browser perceives the request as originating from the same domain.


Preflight Requests

A preflight request is a CORS request that the browser automatically sends before the actual request when a cross-origin request is not simple.

It uses the OPTIONS method and includes up to three headers: Access-Control-Request-Method, Origin, and optionally, Access-Control-Request-Headers.

What kind of requests are not considered simple?
A request requires a preflight if it meets any of the following conditions:

  1. It uses an HTTP method other than GET, POST, or HEAD.
  2. It includes custom headers, such as Authorization or X-Registered-With.
  3. It sends data in formats other than application/x-www-form-urlencoded, multipart/form-data, or text/plain.

For example, if frontendcamp.in makes a DELETE request to api.dev.to, the request flow would be:

  • A preflight request is sent.
OPTIONS /v1/posts/224
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: x-requested-with
Origin: https://frontendcamp.in
Enter fullscreen mode Exit fullscreen mode
  • The server responds with the applicable CORS policy.
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://frontendcamp.in
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, X-Registered-With
Access-Control-Max-Age: 86400
Enter fullscreen mode Exit fullscreen mode

Access-Control-Allow-Origin: Allows requests from frontendcamp.in
Access-Control-Allow-Methods: Specifies allowed HTTP methods
Access-Control-Allow-Headers: Lists allowed custom headers
Access-Control-Max-Age: Tells the browser how long to cache the preflight response (in seconds)

  • The actual request is made.

Preflight requests can introduce performance overhead. To mitigate this, it's important to set the Access-Control-Max-Age header to leverage browser caching.


Common CORS Issues

The knowledge you've gained so far should be enough to debug most CORS-related issues.

Now, let's go through some common scenarios.

❗ No 'Access-Control-Allow-Origin' header in response

Access to fetch at 'https://api.dev.to/data' from origin 'https://frontendcamp.in' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Enter fullscreen mode Exit fullscreen mode

Cause

  1. The API does not send the Access-Control-Allow-Origin header.
  2. The browser blocks the request because it doesn't see explicit permission.

Fix
Modify the API response to include Access-Control-Allow-Origin header.


❗ The Request requires Preflight, but the Server doesn’t handle OPTIONS
Access to fetch at 'https://api.dev.to/data' from origin 'https://frontendcamp.in' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: The server does not respond to OPTIONS requests.
Enter fullscreen mode Exit fullscreen mode

Cause

  1. The API does not handle OPTIONS requests, which are sent as preflight before the actual request.
  2. This happens when using PUT, DELETE, or custom headers (Authorization, X-Requested-With).

Fix
Enable handling for OPTIONS requests on the server.


❗ The API allows a specific Origin, but the Frontend uses a different one
Access to fetch at 'https://api.dev.to/data' from origin 'https://sub.frontendcamp.in' has been blocked by CORS policy:
The 'Access-Control-Allow-Origin' header does not match the request origin.
Enter fullscreen mode Exit fullscreen mode

Cause

  1. The backend only allows https://frontendcamp.in, but the request comes from https://sub.frontendcamp.in.
  2. Many sites use subdomains, and they are treated as separate origins.

Fix
Whitelist the subdomain too.


❗ Credentialed requests (withCredentials: true) not working
Access to fetch at 'https://api.dev.to/data' from origin 'https://frontendcamp.in' has been blocked by CORS policy:
The value of the 'Access-Control-Allow-Origin' header in the response must not be '*'
when the request’s credentials mode is 'include'.
Enter fullscreen mode Exit fullscreen mode

Cause

  1. The request includes credentials (cookies, authentication tokens, etc.), but the server is allowing * as Access-Control-Allow-Origin.
  2. When using credentials, * is not allowed — the API must explicitly list allowed origins.

Fix
Allow credentials & set a specific origin.


Summary

  1. Cross-Origin Resource Sharing (CORS) is a browser security mechanism that restricts frontend code from making cross-origin requests. It’s not an error but a safeguard.
  2. Browsers enforce the Same-Origin Policy (SOP) to prevent malicious websites from accessing resources on other domains.
  3. The server must explicitly allow cross-origin requests by setting the Access-Control-Allow-Origin header with the frontend’s origin.
  4. Using * allows any website to access the resource, which can be a security risk. It should only be used when absolutely necessary.
  5. If you're requesting data from a third-party API and can’t modify its response headers, a proxy server can bypass CORS restrictions.
  6. When a request is not simple, the browser sends an OPTIONS request before the actual request to check if the server allows it.
  7. Requests that use methods other than GET, POST, or HEAD, include custom headers (e.g., Authorization), or send non-standard content types are said to be not "simple".
  8. Frequent preflight requests can cause overhead. Setting the Access-Control-Max-Age header allows the browser to cache the response and improve performance.

Thank you for reading my post. 🙏 I hope you liked it.

Preparing for Frontend interviews?

👉 Check out Frontend Camp

  • Popular interview questions
  • Popular frontend system design questions (upcoming)
  • All for free! ✨

Join now! 🚀

Top comments (0)