Access to fetch at 'https://api.example.com/orders' from origin 'https://app.example.com' has been blocked by CORS policy

Node.js · updated 2026-11-03

Shown in the browser console, not in your server logs: the request often reached the API and even succeeded, but the browser refused to hand the response to your page. The rest of the message says which header was missing or wrong.

Access to fetch at 'https://api.example.com/orders' from origin 'https://app.example.com'
has been blocked by CORS policy: Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.

GET https://api.example.com/orders net::ERR_FAILED

Quick fix

Make the API answer with Access-Control-Allow-Origin set to the exact origin of your frontend, and answer the OPTIONS preflight with the methods and headers the request uses. mode: 'no-cors' in fetch hides the error but also hides the response body, so it doesn't fix anything.

  1. Open the Network tab, find the request and check whether an OPTIONS preflight ran before it and what it returned.
  2. Return Access-Control-Allow-Origin with the exact frontend origin (scheme, host and port) on both the preflight and the real response.
  3. If the request sends Authorization or a JSON content type, allow those in Access-Control-Allow-Headers.
  4. If the request uses cookies (credentials: include), set Access-Control-Allow-Credentials: true and a specific origin, never *.
  5. Make sure error responses (401, 500) carry the CORS headers too, or failures show up as CORS errors.
typescript
import express from 'express';
import cors from 'cors';

const app = express();
const allowed = ['https://app.example.com', 'http://localhost:3000'];

app.use(cors({
  origin: (origin, cb) => cb(null, !origin || allowed.includes(origin)),
  credentials: true,                      // only if the frontend sends cookies
  allowedHeaders: ['Content-Type', 'Authorization'],
}));
// cors() also answers the OPTIONS preflight for every route

Why it happens

The API sends no CORS headers at all

A server that works from curl or Postman can still fail in the browser. Only browsers enforce CORS, so the missing header goes unnoticed until a page on another origin calls the API.

The preflight is not handled

Requests with a JSON body, an Authorization header or a method like PUT or DELETE trigger an OPTIONS request first. If the server returns 404 or 405 for OPTIONS, the real request never runs.

Credentials with a wildcard origin

With credentials: include, the browser rejects Access-Control-Allow-Origin: *. The header must name the exact origin, and Access-Control-Allow-Credentials must be true.

An error response without CORS headers

If the CORS middleware runs after auth, or a proxy returns its own error page, a 401 or 502 arrives without the headers and the browser reports a CORS error instead of the real status.

Other fixes

  • In development, proxy API calls through the frontend dev server (Vite server.proxy or Next.js rewrites) so they are same-origin.
  • Behind nginx or a CDN, make sure it passes through or adds the CORS headers instead of stripping them.
  • Add Vary: Origin when you echo back the request origin, so caches do not serve one origin's headers to another.

Same error, other wording

  • No 'Access-Control-Allow-Origin' header is present on the requested resource.
  • The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
  • Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.

Let your coding agent catch the next one

Runheed records this error in production with the stack trace, the breadcrumbs before it and the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:

> Check the API for CORS problems: list which routes answer the OPTIONS preflight, which responses (including errors) lack Access-Control-Allow-Origin, and configure CORS for our frontend origins only.

Plans from $29/moSee what your agent readsSee the setupCancel any time from the billing portal

Related errors

References: MDN: Cross-Origin Resource Sharing (CORS), Express cors middleware