DEV Community

Neural Download
Neural Download

Posted on

The CORS Error, Explained

https://www.youtube.com/watch?v=1P84YeTrjs4

Every web developer has seen this. You make a fetch request from your frontend. The browser blocks it. Big red error: Access to fetch from origin localhost:3000 has been blocked by CORS policy.

You open your terminal, run the exact same request with curl, and it works perfectly. Same URL. Same headers. Same server.

So what's going on?

The Same-Origin Policy

To understand CORS, you first need to understand the Same-Origin Policy. It's a security rule built into every browser. Two URLs share the same origin only if they have the same protocol, host, and port.

localhost:3000 and localhost:3000/api? Same origin. But localhost:3000 and localhost:8080? Different origins — the port changed.

Here's the key: browsers block JavaScript from reading responses across different origins. Not the server. The browser.

This exists because without it, any malicious website could make requests to your bank's API using your cookies and read your account data. The Same-Origin Policy prevents that by default.

CORS Is Not a Security Wall

CORS — Cross-Origin Resource Sharing — is not a wall. It's the opposite. It's a way for servers to opt out of the Same-Origin Policy.

Think of it as a permission slip. The server says: "Hey browser, it's okay. Let this other origin read my response."

It does this with one special header:

Access-Control-Allow-Origin: https://myapp.com
Enter fullscreen mode Exit fullscreen mode

When the browser gets a response, it checks for this header. If your origin is listed, you're allowed through. If it says *, everyone's allowed. If the header is missing, the browser blocks you.

Here's what most people miss: the request actually reached the server. The server actually sent a response. But the browser threw it away because it didn't have permission to show it to your JavaScript.

Preflight Requests

Some requests are more dangerous than others. A simple GET with standard headers? The browser sends it directly and checks the response headers.

But a POST with a JSON content type? A request with custom headers? The browser does something extra first. It sends a preflight request — an OPTIONS request to the same URL.

It's the browser asking: "Hey server, am I allowed to send a POST with these headers from this origin?"

The server responds with:

Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Enter fullscreen mode Exit fullscreen mode

Only if all of those match does the browser send the actual request. Two requests for the price of one.

The Middleware Fix

When you add CORS middleware to your server, all it does is set these headers on every response.

In Express, it's one line:

app.use(cors());
Enter fullscreen mode Exit fullscreen mode

That adds Access-Control-Allow-Origin: * to every response.

In Python with FastAPI:

app.add_middleware(CORSMiddleware, allow_origins=["*"])
Enter fullscreen mode Exit fullscreen mode

That's all the mystery is. Your server was always getting the requests. It was always sending responses. The browser was just throwing them away because these headers were missing. The middleware stamps every response with the permission slip.

Why Curl Works

And now the final puzzle piece. Why does curl work?

Because curl is not a browser. It doesn't implement the Same-Origin Policy. It doesn't check for CORS headers. It just sends the request and gives you the response.

CORS is not a server-side security mechanism. It's a browser-enforced policy. The server doesn't block anything. The browser does.

That's why Postman works. That's why your backend can call any API it wants. That's why server-to-server requests never hit CORS errors. Only browsers enforce this.

Once you understand that, CORS stops being mysterious. It's just the browser asking for permission, and the server saying yes or no through headers.

Watch the full animated breakdown: The CORS Error, Explained (in 4 mins)


Neural Download — visual mental models for the systems you use but don't fully understand.

Top comments (0)