If you've ever built a frontend that talks to a backend, chances are you've seen this terrifying red message in your browser console: "Blocked by CORS policy…"

And suddenly nothing works. Your API is running. Your frontend is running. Your code looks correct.

But the browser says no. So what exactly is going on? Let's understand this properly — in simple language.

First, Let Me Ask You Something

Why can't your website just fetch data from any server on the internet? I mean… it's just an HTTP request, right?

Well, technically yes. But if browsers allowed that freely, it would be a security nightmare.

Imagine this: You are logged into your banking website in one tab. In another tab, you accidentally open a malicious website. Now if browsers had no restrictions, that malicious site could silently send a request to your bank's server — using your active login session — and transfer money without you even knowing.

That's dangerous. And this is exactly why browsers introduced something called the Same-Origin Policy (SOP).

What is Same-Origin Policy?

Same-Origin Policy is a browser security rule.

It says: A website can only make requests to the same origin it was loaded from.

Now what is an origin? An origin is made up of three things:

  • Protocol (http / https)
  • Domain (example.com)
  • Port (3000, 8080, etc.)

If even one of these changes — it becomes a different origin.

For example:

So if your frontend runs on:

http://localhost:5173

And your backend runs on:

http://localhost:8080

The browser says:

"Nope. Different origin. I'm blocking this." Even though both are on your machine.

None

Okay… But Then What is CORS?

Now here's where things get interesting. Same-Origin Policy is very strict. But in real-world development, we often want different origins to communicate.

Example:

  • Frontend hosted on Vercel
  • Backend hosted on Render
  • Or frontend on localhost and backend on cloud

They are different origins. So how do we allow them to talk safely? That's where CORS (Cross-Origin Resource Sharing) comes in. CORS is basically: A controlled way to relax the Same-Origin Policy.

It allows servers to say: "Hey browser, it's okay. I trust this other website. You can allow the request."

How CORS Actually Works

When your frontend makes a request to another origin, the browser automatically adds a header like this:

Origin: http://localhost:5173

Now the server checks this origin. If the server wants to allow it, it responds with:

Access-Control-Allow-Origin: http://localhost:5173

If that header is present and matches — the browser allows the response. If it's missing — the browser blocks it. Important thing to understand:

-> The server might actually send the response. -> But the browser blocks you from reading it.

CORS is enforced by the browser — not the server.

None

Why Do We Mostly Notice CORS During Development?

Because during development:

  • Frontend runs on one port
  • Backend runs on another port

Different ports = different origins. So your browser starts blocking requests. In production, often both frontend and backend are under the same domain, so you may not see this problem.

Simple Requests vs Preflight Requests

Now don't worry — I won't go too deep here. But you should know this one important thing.

There are two types of CORS requests:

1. Simple Requests

These are normal GET or POST requests without fancy headers. If the server allows the origin, it works immediately.

2. Preflight Requests

If your request:

  • Uses PUT, DELETE, PATCH
  • Sends Authorization headers
  • Sends custom headers
  • Sends JSON content type

Then before sending the real request. The browser first sends an OPTIONS request. This is called a preflight request. It's basically the browser asking:

"Hey server, if I send this real request, will you allow it?"

If the server responds correctly with CORS headers — the browser sends the real request. If not — blocked. That's why sometimes you see an OPTIONS request in your network tab and get confused.

One Very Important Thing

If you call your API using:

  • Postman
  • Curl
  • Command line tools

CORS will not block anything.

Why? Because CORS is a browser security feature. It does not exist outside browsers. That's why your API works perfectly in Postman. But fails in your React app.

And that's when beginners start questioning their life decisions.

So What Should we Really Remember?

Let's simplify everything:

  • Browsers protect users using Same-Origin Policy.
  • CORS is a controlled way to relax that rule.
  • Server must explicitly allow other origins
  • Browser enforces CORS — not the server.
  • Preflight requests happen for complex requests.
  • It's about security, not about annoying developers.

Once you understand this mental model, CORS errors stop being scary. They become predictable. And when something is predictable — it becomes easy to fix.

Final Thoughts

CORS is not a bug. It's not a backend failure. It's not your frontend being broken. It's a browser protecting the user. As developers, our job is to configure our servers correctly — not fight the browser. And once you truly understand that CORS is about trust between origins, everything starts making sense.

About the Author

Shrey Joshi — Breaking down complex concepts with clarity and context.

LinkedIn | Hashnode | Instagram Building learn.with.Shrey