What is CORS?
Tags: javascript, react, webdev, typescript
Published: 2022-10-18 09:36:06

---
title: "What is CORS?"
published: true
description: "Article explains what is CORS, popular among web developers CORS, what are the common problems and how to fix them."
tags: [javascript, react, webdev, typescript]
cover_image: https://simplelocalize.io/blog/what-is-cors.jpg
canonical_url: https://simplelocalize.io/blog/posts/what-is-cors/
---


In this article, I will explain what CORS and CORS errors are and why you might run into them. I will present possible solutions and explain what preflight requests, CORS headers are, and why they are important in the communication between parties. The article assumes you have some basic knowledge of web development and the HTTP protocol. I tried to write the article in a way that is easy to understand for beginners and fill it with knowledge and try to avoid too many technical nuances that are not tightly connected with the CORS topic. If you spotted any mistakes or have any suggestions, do not hesitate to contact me. In some places, I made a simplification where a service means server and vice versa.

## What is CORS?

**Cross-Origin Resource Sharing (CORS) is an HTTP-based security mechanism controlled and enforced by the client (web browser).** It allows a service (API) to indicate any origin other than its own from which the client can request resources. It has been designed in response to [the same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy) (SOP) that restricts how a website (HTML document or JS script) loaded by one origin can interact with a resource from another origin. CORS is used to explicitly allow some cross-origin requests while rejecting others.

CORS is implemented primarily in web browsers, but it can also be used in API clients as an option. It's present in all popular web browsers like Google Chrome, Firefox, Opera, and Safari. The standard has been [accepted as a W3C Recommendation in January 2014](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing). Based on that, we can assume that it is implemented in all currently available and other than listed web browsers.

### How does it work?

Everything starts on the client side, before sending the main request. The client sends a CORS preflight request to a service for resources with parameters in HTTP headers (CORS headers). The service responses using the same headers with different or the same values. The client decides, based on a CORS preflight response, if he can or cannot send the main request to the service. The web browser (client) will throw an error if the response does not meet the requirements of CORS preflight.

CORS preflight requests are sent regardless of the used libraries or frameworks to send requests from web browser. That's why you won't need to conform CORS requirements when working with API from your backend application.

> CORS is not going to prevent users from requesting or downloading resources. You can still make a successful request
> for a resource using apps like [curl](https://curl.se/), [Insomnia](https://insomnia.rest/),
> or [Postman](https://www.postman.com/). CORS is only going to prevent the browser from accessing the resource if the
> CORS policy does not allow it.

## What is a CORS preflight?

When a browser sends a request to a server, it first sends an [HTTP Options request](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS). This is called a CORS preflight request. The server then responds with a list of allowed methods and headers. If the browser is allowed to make the actual request, it sends the actual request. If not, it shows an error and does not continue to send the main request.

![CORS preflight: Server-Client Requests Scheme](https://simplelocalize.io/blog/cors-preflight-scheme-server-client.jpg)

## CORS Headers

CORS headers are regular HTTP headers that are used to control the CORS policy. They are used in requests where the browser sends a CORS preflight request to the server, and the server responses with:

 - `Access-Control-Allow-Origin` indicates what origin can fetch resources. Use one or more origins, e.g.: `https://foo.io,http://bar.io`.
 - `Access-Control-Allow-Methods` indicates what HTTP methods are allowed. Use one or more comma HTTP methods, e.g.: `GET,PUT,POST`.
 - `Access-Control-Allow-Headers` indicates what request headers are allowed. Use one or more headers, e.g.: `Authorization,X-My-Token`. 
 - `Access-Control-Allow-Credentials` indicates if sending cookies is allowed. Default: `false`.
 - `Access-Control-Max-Age` - indicates how long the request result should be cached, in seconds. Default: `0`.

If you decide to use `Access-Control-Allow-Credentials=true`, then you need to be aware of the fact you cannot use  wildcards `*` in `Access-Control-Allow-*` headers. It's required to explicitly list all allowed origins, methods, and headers.


See a [full list of CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#the_http_response_headers).


![cors request and response headers](https://simplelocalize.io/blog/browser-server-preflight-request-and-response-headers.jpg)

## Why is request blocked by CORS policy?

If you are a web developer, you have probably already seen or heard about CORS errors, and you have googled it many times to find the solution. The most common problem is that the browser blocks the request because of CORS policy. The browser will throw an error and show a log in the console:

```properties
Access to XMLHttpRequest at 'http://localhost:8080/' from origin
'http://localhost:3000' 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.
```

The CORS error above notifies a user that the browser couldn't access a resource (`https://localhost:8080`) from an origin (`https://localhost:3000`) because the server didn't allow it. It happened because the server didn't respond with `Access-Control-Allow-Origin` header with the origin or with a wildcard `*` in the CORS preflight response.

A request may be blocked by CORS policy not only because of the incorrect origin, but also incorrect HTTP header, HTTP method or Cookie header.

## How to fix CORS error?

The fundamental idea of "fixing CORS" is to respond to "OPTIONS" requests sent from a client with proper headers. There are many ways to start responding with the proper CORS. You can use a proxy server, or you can use middleware in your server.

![Response to preflight request doesn't pass access control check](https://simplelocalize.io/blog/response-preflight-request-doesnt-pass-access-control-check.jpg)

Remember that `Access-Control-*` headers are cached in a web browser according to the value set in `Access-Control-Max-Age` header. Please make sure that you clear the cache before testing the changes. You can also [disable caching in your browser](https://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development).

### 1. Configure your server

By default, if you are a server owner, you need to configure CORS responses in your server and this is the only way to address the issue properly. You can achieve this in multiple ways and on multiple layers of your app. The most common way is to use reverse-proxy, API gateway, or any other routing service that offers to add headers to the responses. There are many services that you can use to do this, some of them are: HAProxy, Linkerd, Istio, Kong, nginx, Apache, Traefik. If your infrastructure contains only an application without any additional layers, then you can simply add CORS support in the application code.

![successful CORS preflight requests in Firefox Developer console](https://simplelocalize.io/blog/cors-preflight-requests-in-firefox-developer-console.png)

Here are some popular examples of enabling CORS:

- [Apache: modify .htaccess file](https://enable-cors.org/server_apache.html),
- [Nginx: modify configuration file](https://enable-cors.org/server_nginx.html),
- [Traefik: use middlewares](https://doc.traefik.io/traefik/middlewares/http/headers/#cors-headers),
- [Spring Boot: use `@EnableCORS` annotation](https://github.com/jpomykala/spring-higher-order-components),
- [ExpressJS: use `app.use(cors())`](https://expressjs.com/en/resources/middleware/cors.html),
- [NextJS: use request helpers](https://nextjs.org/docs/api-routes/api-middlewares#cors-support).

Here you can find more examples of enabling CORS in different frameworks and languages: [enable-cors.org](https://enable-cors.org/).

If you cannot enable CORS in the service, but you still want to make request to it, then you need to use one of the following solutions described below.


### 2. Install a browser extension

Using a browser extension might be a quick and easy way to solve your problems with CORS in your developer environment. The biggest advantage of using a browser extension is that you don't need to change your code or configuration. On the other hand, you need to install an extension on every web browser that you use for testing your web application.

![Use browser extension to overcome CORS error](https://simplelocalize.io/blog/cors-preflight-browser-extension-solution.jpg)

Browser extensions alter incoming preflight request by adding the necessary headers to trick the browser. It's a handy solution to work locally with the production API that accepts requests only from the production domain.

You can find extensions in [Google Web Store](https://chrome.google.com/webstore/search/cors?hl=en-US) or in [Mozilla Add-ons Library](https://addons.mozilla.org/en-US/firefox/search/?q=cors). In some cases, the default extension configuration might not be enough; make sure that the installed extension is configured properly. You should also be aware of that leaving the extension turned on indefinitely may cause problems on some websites. It's recommended to use them only for development purposes.

### 3. Disable browser CORS checks

You can disable CORS checks in your browser completely. To disable CORS checks in Google Chrome, you need to close the browser and start it with the `--disable-web-security` and `--user-data-dir` flags. By doing that, Google Chrome will not send CORS preflight requests and will not validate CORS headers.

```bash
# Windows
chrome.exe --user-data-dir="C://chrome-dev-disabled-security" --disable-web-security --disable-site-isolation-trials

# macOS
open /Applications/Google\ Chrome.app --args --user-data-dir="/var/tmp/chrome-dev-disabled-security" --disable-web-security --disable-site-isolation-trials

# Linux
google-chrome --user-data-dir="~/chrome-dev-disabled-security" --disable-web-security --disable-site-isolation-trials
```

All of those commands above start Google Chrome in an isolated sandbox. They will not affect your main Chrome profile.

![Disable security in Google Chrome to overcome CORS error](https://simplelocalize.io/blog/disabled-cors-preflight-in-web-browser.jpg)

See list of all [available flags for Google Chrome](https://peter.sh/experiments/chromium-command-line-switches/). 

### 4. Set up a proxy server

If you are looking for a solution that doesn't require you to change the browser settings, then you should look at the proxy server solution. This option helps you to overcome CORS errors without changing anything in the browser itself. The idea of using a proxy server is to send all requests to your server, and then the server will send the request to the actual service you want to use. You can build a proxy server on your own in a language and framework of your choice. You will need to configure CORS and implement a functionality to pass requests received requests to another service.

![Use proxy server to overcome CORS error](https://simplelocalize.io/blog/cors-preflight-proxy-server-solution.jpg)

Proxy server is a good solution if you don't have access to the service you intend to use. There are ready to use and open-source proxy server services, but you should always ensure that they are not trying to intercept your requests with authorization headers and pass them to any 3rd party service. Such security breaches could be catastrophic failure for you and potential users of the service.

List of open-source CORS services that you can find on the internet:
- https://github.com/Freeboard/thingproxy
- https://github.com/bulletmark/corsproxy
- https://github.com/Rob--W/cors-anywhere

Please review the code of the newest version before using any of those services.

## How to test CORS?

Using a browser to test your CORS configuration might be a tedious task. You can use a tool like [CORS Tester](https://cors-test.codehappy.dev), [test-cors.org](https://www.test-cors.org/), or, if you are familiar with the command line, you can use [curl](https://curl.se/) to test your CORS configuration.

```properties
curl -v -X OPTIONS https://simplelocalize.io/api/v1/translations
```

![free open-source web-based CORS tester](https://simplelocalize.io/blog/free-cors-tester-web-application.png)

## Beware of false CORS errors

In some cases, when a service is behind an additional layer with rate-limiter, load balancer or authorization server, you can get a false CORS error. Blocked or rejected requests by a server should respond with error status codes. E.g.,:

 - 401 unauthorized,
 - 403 forbidden,
 - 429 too many requests,
 - 500 internal server error,
 - any other than 2XX or 3XX.

You may see that the request is blocked due to failed preflight request, but in fact, a service just rejects it. You should always check the status code and response body of the response to avoid unnecessary debugging. The browser properly alerts you when a CORS preflight request fails, but the reason for the failure is not necessarily connected to the CORS configuration.

## Conclusion

In this article, I tried to explain what CORS is, and what are the most common problems with it. I suggested 4 ways to fix CORS issues and explained the advantages and disadvantages of each one. I also explained how to configure CORS responses properly and how to test them. Moreover, I showed what are the most common issues with recognizing false CORS errors. I tried to put everything in simple terms and avoid technical nuances. If you have any questions, doubts, or suggestions, please do not hesitate to contact me.

Happy coding!

## Resources
- https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors
- https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
- https://enable-cors.org/
- https://stackoverflow.com/a/42024918/1133169