CORS errors

Cross-Origin Resource Sharing (CORS) is a standard that allows a server to relax the same-origin policy. This is used to explicitly allow some cross-origin requests while rejecting others. For example, if a site offers an embeddable service, it may be necessary to relax certain restrictions. Setting up such a CORS configuration isn't necessarily easy and may present some challenges. In these pages, we'll look into some common CORS error messages and how to resolve them.

If the CORS configuration isn't set up correctly, the browser console will present an error like "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at [some site]" indicating that the request was blocked due to violating the CORS security rules. This might not necessarily be a set-up mistake, though. It's possible that the request is in fact intentionally being disallowed by the user's web application and remote external service. However, if the endpoint is meant to be available, some debugging is needed to succeed.

Identifying a CORS issue

To understand the underlying issue with the CORS configuration, you need to find out which request is at fault and why. These steps may help you do so:

  1. Navigate to the website or web app in question and open the Developer Tools.
  2. Now try to reproduce the failing transaction and check the console if you are seeing a CORS violation error message. It will probably look like this:

Firefox console showing CORS error

The text of the error message will be something similar to the following:

Cross-Origin Request Blocked: The Same Origin Policy disallows
reading the remote resource at https://some-url-here. (Reason:
additional information here).

Note: For security reasons, specifics about what went wrong with a CORS request are not available to JavaScript code. All the code knows is that an error occurred. The only way to determine what specifically went wrong is to look at the browser's console for details.

Client-side considerations

Most CORS errors can only be resolved on the server, because the server controls whether cross-origin access is allowed. However, there are some things you can do on the client side:

Avoid triggering a preflight

Browsers send a preflight request before the actual request when certain conditions are met (custom headers, methods other than GET/HEAD/POST, or non-simple content types). If the server does not handle preflight requests, you can restructure your request to qualify as a simple request:

Simple requests bypass the preflight step entirely, which avoids a class of CORS errors related to preflight handling.

Use no-cors mode for opaque responses

If you do not need to read the response body or headers - for example, when sending analytics beacons or loading resources into a cache via a service worker - you can set the mode to "no-cors" in a fetch() call:

js
fetch("https://api.example.com/log", {
  method: "POST",
  mode: "no-cors",
  body: data,
});

The response will be opaque: its status is 0, its headers are empty, and its body is not readable by JavaScript. This is by design - no-cors disables the CORS check, but in exchange you lose all access to the response content.

Use a proxy server

If you do not control the remote server and it does not set CORS headers, you can route requests through a server you do control. Your server fetches the resource on your behalf and returns it with appropriate CORS headers. This approach adds latency and introduces a dependency on your proxy, but it works when other options are unavailable.

CORS error messages

Firefox's console displays messages in its console when requests fail due to CORS. Part of the error text is a "reason" message that provides added insight into what went wrong. The reason messages are listed below; click the message to open an article explaining the error in more detail and offering possible solutions.

Most CORS errors can only be resolved on the server, because the server controls whether cross-origin access is allowed. However, there are some things you can do on the client side:

Avoid triggering a preflight

Browsers send a preflight request before the actual request when certain conditions are met (custom headers, methods other than GET/HEAD/POST, or non-simple content types). If the server does not handle preflight requests, you can restructure your request to qualify as a simple request:

Simple requests bypass the preflight step entirely, which avoids a class of CORS errors related to preflight handling.

Use no-cors mode for opaque responses

If you do not need to read the response body or headers — for example, when sending analytics beacons or loading resources into a cache via a service worker — you can set the mode to "no-cors" in a fetch() call:

js
fetch("https://api.example.com/log", {
  method: "POST",
  mode: "no-cors",
  body: data,
});

The response will be opaque: its status is 0, its headers are empty, and its body is not readable by JavaScript. This is by design — no-cors disables the CORS check, but in exchange you lose all access to the response content.

Use a proxy server

If you do not control the remote server and it does not set CORS headers, you can route requests through a server you do control. Your server fetches the resource on your behalf and returns it with appropriate CORS headers. This approach adds latency and introduces a dependency on your proxy, but it works when other options are unavailable.

See also