Skip to content

Browser error“Access to fetch has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present”

Your web app calls an API on another domain and the console says the request has been blocked by CORS policy. The API may work fine in Postman or curl. The browser only lets a page read a response from another origin if that server says it may, with an Access-Control-Allow-Origin header. The fix is almost always on the server, not in your front-end code.

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

  1. 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();
    });
  2. 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.

  3. 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.

  4. 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.

Related: Supabase Edge Function CORS error · Firebase Functions CORS error · Mixed Content: HTTPS page blocks an http:// request

Questions

More on this error

Why does it work in Postman but not in the browser?

CORS is enforced by browsers. Postman, curl and server code don’t check it, so the same request succeeds there. The server still has to send the header for your web app to read the response.

Can I fix CORS in my front-end code?

Mostly no. MDN says most CORS errors can only be resolved on the server. On the client you can avoid a preflight by keeping to a simple request (MDN’s CORS guide lists the limits), or use mode: "no-cors", which gives an opaque response: fine for a fire-and-forget ping, useless for reading JSON.

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. 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.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.