So what if I want to make an AJAX request to an outside API in a browser script?

Vice versa, what if you are developing an API and you want to allow people to make AJAX (or newer web APIs like Fetch) requests to your API in the browser? Or more simply, you want to make sure anyone can access a font you are sharing from your website, regardless of their browser?

At last, we’ve arrived at CORS.

CORS allows servers to specify certain trusted ‘origins’ they are willing to permit requests from. Origins are defined as the combination of protocol (http or https), host (a domain like and port. Browsers which implement the CORS policy will include a HTTP header called ‘Origin’ in requests made with AJAX, including above information the value.

Simple requests

To instruct the browser to expose server responses to a HTTP requests from certain origin, the web server must respond to the request with an additional HTTP response header, ‘Access-Control-Allow-Origin: ’. Alternatively, the web server may expose its responses to all origins by specifying a value of ‘*’, e.g. ‘Access-Control-Allow-Origin: *’.

Simple, huh?

Preflight requests

This might be sufficient for simple GET, HEAD, or POST requests without any special http headers. However, for DELETE and PUT request, ‘unsafe’ requests which may impact the server’s data, or GET, HEAD and POST requests with customized headers, the browser will send a “preflight” request to find out the CORS result prior to sending the actual request (only if the preflight response determines access is permitted).

The preflight request is an OPTIONS request made to the same HTTP path as the actual request, with a couple of HTTP headers:

  • Origin — The origin header that would be included with the actual request being made by the website.
  • Access-Control-Request-Method — The method of the actual request being made by the website.
  • Access-Control-Request-Headers — A comma-separated list of headers that would be included in the actual request.

Web servers that wish to support CORS requests must respond to preflight requests with the following HTTP headers:

  • Access-Control-Allow-Origin — The whitelisted origin, or ‘*’
  • Access-Control-Allow-Methods — A comma-separated list of HTTP methods the web server wishes to permit for cross-origin requests
  • Access-Control-Allow-Headers — A comma-separated list of HTTP headers the web server wishes to permit for cross-origin requests

If any of the information in the response headers does not match the actual parameters of the request, the browser will not send the actual request, preventing unwanted side-effects from the server receiving the cross-origin request. (After all, including ‘Access-Control-Allow-Origin’ in the response to any of the other requests does not prevent those requests from being made to the server; it only prevents the browser from displaying the response.)

There are more CORS headers the server may respond with, including ‘Access-Control-Expose-Headers’, ‘Access-Control-Max-Age’, and ‘Access-Control-Allow-Credentials’. Rather than go into too much detail, I would encourage you to take a look at [MDN’s detailed article about CORS and the meaning of each header.