CORS 101: What It Is, Why It Matters, and How It Works

It was 2AM, the air thick with anticipation. We were finally ready to deploy our website—the gateway for users to start registering on our new portal. After days of testing everything locally, I took a deep breath and hit deploy. Moments later, I visited the production URL, filled in the registration form, and clicked Register.
And then—boom. “Some error occurred.” My heart sank.
I rushed to check the server logs, expecting a stack trace or at least something. But... nothing. No logs. No request. It was as if the request had vanished into thin air.
Puzzled, I opened Postman and sent the exact same request. It worked perfectly. Now I was more confused than ever. Why would Postman reach my servers, but the website—our actual frontend—not even trigger a server log?
Then I opened the browser console, and there it was. A barrage of errors screaming back at me: CORS errors.
That night, I learned (the hard way) about something every web developer inevitably runs into—Cross-Origin Resource Sharing, or CORS. If you’re deploying a frontend that talks to an API on a different domain or port, understanding CORS is non-negotiable
So….. What is CORS and Why is it so important ?
CORS stands for Cross Origin Resource Sharing and it is a browser security feature that controls how resources are requested across different origins.
This begs another question: What exactly is an Origin ?
Origin, as the word suggests, is used to identify the source or origination point of a request. We all know that a URL is a string used to locate resources on the internet—but the origin is just a part of that URL.
It was first introduced by Netscape and is now part of the HTML Living Standard, maintained by WHATWG (don’t ask... it’s a long story).
An origin is defined as a combination (technically, a tuple) of the following three things:
Scheme (the protocol, e.g.,
http,https)Hostname (the domain, e.g.,
example.com)Port (e.g.,
80,443, or custom ones like3000)
So two URLs might look similar, but if any one of these components differs, the browser will treat them as different origins—and that’s where CORS comes into play.
Let us take a real world example to understand origins.
https://example.comhttp://example.comhttps://example.com:8000https://api.example.com
At a glance, these might feel like the same site - but from a browser’s perspective these are four completely different origins.
Here’s why:
| URL | Scheme | Hostname | Port | Different Origin ? |
https://example.com | https | example.com | 443 | — |
http://example.com | http | example.com | 80 | ✅ (different scheme) |
https://example.com:8000 | https | example.com | 8000 | ✅ (different port) |
https://api.example.com | https | api.example.com | 443 | ✅ (different hostname) |
So even if your frontend is served from https://example.com and your backend is on https://api.example.com, that’s a cross-origin request—and that’s when CORS rules apply.
Now that we know what CORS is and how does it detect different Origins. let us understand the reason behind it.
Why is CORS important ?
Let us try to understand this with a scenario:
Imagine you are the owner of a bank and you have a website at https://bank.com; this website is the login portal for all your customers and allows them to access there account information and details. Now, there is a an evil guy, let’s call him John. John knows that if he can somehow make the user think that his website also let’s the user access the account he will be able to steal all the information.
So he comes up with an evil plan; He creates a website at https://evil.com and this website sends requests to https://bank.com on behalf of the users. Now his website is posing as the bank’s official website because it is getting all the accurate data from https://bank.com
As the owner of the bank you want to prevent this. Now if CORS weren’t present you would have to validate that the Origin of the request header matches the one of your site and this validation would have to be setup at each endpoint of your website.
CORS is this validation layer that you just implemented. CORS is important because it allows website owners to specify who and what can access the website / resource.
How does it work ?
CORS relies on the mechanisms in the browser using which they send “preflight” request to the web server hosting the cross origin resource, in order to check if the server will allow the actual request.
In that preflight, the browser sends headers that indicate the HTTP method and headers that will be used in the actual request. This preflight request can be considered a very light weight version of the original request as it contains no payload or data that the original request might transfer.
How does the server tell if they wanna allow a specific request or not ?
Well in response to the CORS preflight request. The server sends a response containing the headers that tell Who can access, What can be accessed, What methods are allowed, How to send data etc
Rules for a preflight request:
A preflight request is sent when the actual request does not meet the criteria for a “simple request”. A request is considered simple if it follows these rules:
- HTTP Methods: The request may use only simple HTTP verbs (methods)
GETPOSTHEAD
- CORS-safelisted request headers: The request can only contain certain headers that are a part of the CORS-safelisted headers.
AcceptAccept-LanguageContent-LanguageContent-TypeRange(only with a single range header value, e.g.bytes=127orbytes = 127-255)
- Content-Type restrictions: If the
Content-Typeheader is set, it can only use the following media types:
application/x-www-form-urlencodedmultipart/form-datatext/plain
If a request follows these conditions, then it is considered a simple request and does not trigger a preflight check. If the request includes an non-simple methods or headers (like custom headers), it will trigger a CORS preflight.
Let’s take a closer look at how the preflight request works in this scenario.
Let’s say we have to fetch some doc from our backend. Our frontend is hosted on foo.site and backend is on bar.site.
Imagine we want to fetch some document from our backend. Our frontend is hosted on foo.site , and the backend is located at bar.site. Here’s what the request might look like:
const request = fetch("https://bar.other/doc", {
method: "GET"
headers: {
"Accept": "application/json",
"Authorization": "Bearer 12kdlfajlfja"
}
});
request.then((response) => {
if (response.ok) {
return response.json()
}
throw new Error("invalid response")
})
.then((data) => {
console.log(data)
});
In this code, we are sending an HTTP request from foo.site to fetch the resource /doc from bar.site. Since the frontend is on foo.site and the request is going to bar.site this qualifies as a Cross-Origin Request. Additionally the above request includes an Authorization header which is not a CORS-safelisted request header. As a result, a preflight request will be sent by the browser to check if the request is allowed.

In the above exchange we can see that there is an OPTIONS request that is sent before the actual GET request. This OPTIONS request is the preflight request that is sent by the browser. We can also see that the in response to the OPTIONS request, the server sent some headers:
Access-Control-Allow-Origin- This tells the browser who can access ( here*means all)Access-Control-Allow-Methods- This tells the browser what methods are allowedAccess-Control-Allow-Headers- This tells the browser what headers are allowed
In summary, the preflight OPTIONS request serves as a security measure enforced by the browser to verify that the actual request is safe to send. By examining the server's response headers—such as Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers—the browser ensures that the cross-origin request complies with the server's policies. If the headers meet the browser's requirements, the actual request proceeds; otherwise, it is blocked. This mechanism is a key part of Cross-Origin Resource Sharing (CORS) and helps protect both servers and clients from unauthorized access and potential security risks.
TL;DR
CORS might feel a bit mysterious at first, but it’s essentially a browser-enforced security measure that helps protect users from cross-site attacks. The preflight request is a key part of that system—it’s the browser’s way of asking the server, “Hey, is it okay if I send this kind of request?”
By understanding what triggers a preflight and how the server should respond, you can confidently build cross-origin applications without running into the dreaded “CORS error” wall. Whether you're sending custom headers, using different HTTP methods, or handling third-party APIs, knowing how CORS works behind the scenes will help you troubleshoot faster and design better APIs.
In the end, it’s all about communication—between browser and server—just a polite check-in before doing something a little out of the ordinary.




