CORS Explained — and Why It Breaks Your API
CORS (Cross-Origin Resource Sharing) is a browser security mechanism that blocks requests from one domain to another unless the server explicitly allows it. One wrong header ruins everything.
What triggers a CORS error?
Any browser request to a different origin (protocol + domain + port). https://app.com → https://api.com is cross-origin. Your JS fetch/XHR gets blocked before it even reaches your code.
What is a preflight request?
Browsers send an OPTIONS request before POST/PUT/DELETE or custom headers. Your server must respond with correct CORS headers, or the real request is blocked. Enable OPTIONS in Allowed Methods.
Why can't I use * with credentials?
The spec forbids it. If Access-Control-Allow-Credentials: true is set, you must specify an exact origin. Wildcard + credentials = browser will block the response.
Max-Age — why bother?
Without it, browsers re-check preflight on every single request. Set 86400 (24h) and browsers cache the permission — fewer round trips, faster API calls for your users.
Multiple allowed origins
CORS only allows one value in Allow-Origin. For multiple origins, use server-side logic: check if the request Origin header is in your whitelist, then reflect it dynamically. This generator handles that pattern.
Exposed vs Allowed Headers
Allowed = headers the browser can send. Exposed = headers your API returns that JS can actually read. Non-exposed response headers are invisible to response.headers.get().