Short answer
Make the API answer with Access-Control-Allow-Origin set to your site’s origin, for example https://yourapp.com, and answer OPTIONS preflight requests with the methods and headers you send. Do not use * for an API that uses cookies or auth. If you don’t control the API, call it from your own backend or a serverless function and have that return the data to your page.
Why the browser blocks the response, and the fix
01
The API doesn’t send Access-Control-Allow-Origin
“If the server is under your control, add the origin of the requesting site to the set of domains permitted access by adding it to the Access-Control-Allow-Origin header's value.” MDN, Reason: CORS header 'Access-Control-Allow-Origin' missing
The request reached the server, but the response did not list your site as allowed, so the browser hides it from your code. Add the header on the server for the exact origin of your front end, including the scheme and port, and answer the OPTIONS preflight in the same place. Localhost and production are different origins, so allow each one you use. Put this before your routes and auth middleware, or a 401 on OPTIONS brings the error back. An API error or redirect without the header also shows up as a CORS error, so check the status code too.
// Express example: before routes and auth const allowed = new Set(['https://yourapp.com', 'http://localhost:3000']); app.use((req, res, next) => { const origin = req.headers.origin; if (origin && allowed.has(origin)) { res.setHeader('Access-Control-Allow-Origin', origin); res.setHeader('Vary', 'Origin'); res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); } if (req.method === 'OPTIONS') return res.sendStatus(204); next(); });02
The preflight OPTIONS request fails
“for "preflighted" requests the browser first sends an HTTP request using the OPTIONS method to the resource on the other origin” MDN, Cross-Origin Resource Sharing (CORS)
A request with JSON, an Authorization header, or a method like PUT or DELETE makes the browser send an OPTIONS request first. If the server or a gateway returns 404, 401 or no CORS headers for OPTIONS, the real request never goes out. Answer OPTIONS with 204 and Access-Control-Allow-Methods and Access-Control-Allow-Headers listing what you send.
03
A wildcard on a private API
“Warning: Using the wildcard to allow all sites to access a private API is a bad idea.” MDN, Reason: CORS header 'Access-Control-Allow-Origin' missing
Access-Control-Allow-Origin: * may look like a quick fix. It does not work with cookies or credentials, and it lets any website call the API from a visitor’s browser. List your own origins, or echo back the request’s Origin only when it is on your allowlist, together with Vary: Origin. Requests sent with cookies (credentials: 'include') also need Access-Control-Allow-Credentials: true and an exact origin.
04
You don’t control the API
“Route the request through a proxy server you control, which fetches the resource and returns it with appropriate CORS headers.” MDN, Reason: CORS header 'Access-Control-Allow-Origin' missing
A third-party API that sends no CORS headers can’t be fixed from the browser. Call it from your own backend, an API route or a serverless function, keep any secret key there, and return the result to the page. In local development, a dev proxy (Vite server.proxy or Next.js rewrites) lets the browser call your own origin. Browser extensions or turning off security in the browser only hide the problem on your machine.
Checked against the vendor’s docs on : MDN: Reason: CORS header ‘Access-Control-Allow-Origin’ missing; MDN: CORS errors; MDN: Cross-Origin Resource Sharing (preflighted requests).
Rather hand it over?
Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.
- from $450App Fix TicketOne reproducible bug in an existing mobile or web app, diagnosed and fixed.See scope and start
- from $450AI-Built App RescueA Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.See scope and start
Related: Supabase Edge Function CORS error · Firebase Functions CORS error · Mixed Content: HTTPS page blocks an http:// request