State and browser security

Origins and CORS

Understand the browser same-origin policy, what makes two URLs different origins, and how servers opt in to cross-origin reads with CORS.

An origin is the combination of scheme, host, and port. Change any one of those and the browser treats it as a different origin:

https://flaviocopes.com
https://api.flaviocopes.com
http://flaviocopes.com
https://flaviocopes.com:8443

The same-origin policy stops JavaScript on one origin from freely reading responses from another. Your page at https://app.example.com cannot fetch https://api.example.com/user and inspect the JSON unless the API explicitly allows it.

CORS (Cross-Origin Resource Sharing) is how a server opts in. It sends response headers like:

Access-Control-Allow-Origin: https://app.example.com

That tells the browser: JavaScript on app.example.com may read this response.

For some requests, the browser sends an OPTIONS preflight first. It asks whether the server permits the intended method and headers before sending the real request. POST with a custom header often triggers a preflight. A simple GET usually does not.

CORS is enforced by browsers only. It does not stop another server or curl from calling your API:

curl https://api.example.com/user

curl ignores CORS because there is no same-origin policy in the terminal. CORS also does not replace authentication. It controls which frontends may read responses, not who may call your API at all.

Be careful with Access-Control-Allow-Origin: *. It allows any site to read the response in a browser. That is fine for public data. It is dangerous for responses that include private user data unless you also require credentials and list specific origins.

When a fetch fails with a CORS error in the console, the request often reached the server. The browser blocked your JavaScript from seeing the response because the CORS headers were missing or wrong. Check the Network panel response headers before you blame the API logic.

Try this: open your site, fetch your own API from the browser console, and read the CORS headers on the response. Then run the same URL with curl and compare.

Lesson completed