CORS explained: why cross-origin requests get blocked
Kort antwoord
CORS (Cross-Origin Resource Sharing) is a browser security mechanism, not a server or firewall feature. It blocks a web page on one origin from making requests to a different origin unless that other origin explicitly allows it through response headers. If your frontend works fine when you test the API with curl but breaks in the browser console, this is almost always why.
What counts as an "origin"
An origin is the combination of scheme, domain and port a page was loaded from. https://app.example.com and https://api.example.com are different origins even though they share a parent domain. So are http://example.com and https://example.com, because the scheme differs. Any time JavaScript running on one origin tries to call a URL on a different origin, that's a cross-origin request, and the browser gets involved.
Why this exists
Browsers enforce a same-origin policy by default: a script can freely call back to the origin it was loaded from, but calling a different origin is restricted unless that origin says it's fine. The reason is about protecting the user, not the server making the request. Without this restriction, a malicious site you visit could run JavaScript that silently sends requests to your bank, your email provider, or any other site you're logged into, riding on the session cookies your browser already holds for those sites. CORS is what stops a page you didn't intend to trust from quietly acting on your behalf against a site you do trust.
The symptom developers hit constantly
This is the pattern almost everyone runs into eventually: a frontend hosted on one domain calls an API hosted on a different domain. The API itself works perfectly when tested directly, with curl, Postman, or a REST client, because none of those are browsers and none of them enforce CORS. But the exact same request made from JavaScript in the browser fails, and the browser's console shows a CORS error rather than a network error. The request often did reach the server and the server often did respond. The browser just refused to hand that response to the page's JavaScript, because the API's server never sent back the headers needed to say "this origin is allowed to read my response".
The fix, conceptually
CORS is fixed on the server being called, not on the frontend making the call. The API needs to include an Access-Control-Allow-Origin header in its response, naming the origin (or origins) that are permitted to read that response. Depending on what the request needs to do, related headers cover which HTTP methods are allowed (Access-Control-Allow-Methods), which custom headers can be sent (Access-Control-Allow-Headers), and whether credentials like cookies can be included (Access-Control-Allow-Credentials). For anything beyond a simple GET request, the browser typically sends a preflight OPTIONS request first, asking the server to confirm the actual request would be allowed before sending it for real.
What CORS does not protect
It's worth being precise about what CORS actually is: a rule enforced by browsers, for browsers. It does nothing to stop a script, a server-to-server integration, or a tool like curl from calling an API directly, because none of those enforce the same-origin policy in the first place. An API that's meant to be publicly reachable is just as reachable with or without CORS headers set, from anything that isn't a browser reading a cross-origin response. If an API needs to restrict who can call it at all, that's a job for authentication, API keys, or IP allowlisting, not CORS.