Skip to content
Commitpedia
Log in Join & edit

Fix: Access to fetch at ‘…’ from origin ‘…’ has been blocked by CORS policy

The browser refused to give your script a cross-origin response because the server did not send the right Access-Control-* headers. Fix it on the server or with a dev proxy.

Edit history of Fix: Access to fetch at ‘…’ from origin ‘…’ has been blocked by CORS policy: 1 recorded edit
Edit history · 1 edit
Type
Article
Edits
1
Editors
1
First issued
15 Oct 2026
Last edit
15 Oct 2026
Reading
3 min

You call an API from a web page and the console shows something like this (Chrome wording; Firefox says “Cross-Origin Request Blocked” instead):

Access to fetch at 'http://localhost:3000/api/items' from origin 'http://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Your page and the API live on different origins, and the API did not say the page is allowed to read its response. The browser therefore hides the response from your code. The same request works in curl because curl does not enforce CORS.

Read the end of the message

The text after the colon tells you which check failed:

  • No ‘Access-Control-Allow-Origin’ header is present: the server sent no CORS headers at all, or an error page (a 404 or 500 from a proxy often lacks them).
  • Response to preflight request doesn’t pass access control check: the OPTIONS request failed. Often the route does not handle OPTIONS, redirects it, or demands authentication for it.
  • Request header field authorization is not allowed by Access-Control-Allow-Headers: add that header name to Access-Control-Allow-Headers.
  • The value of the ‘Access-Control-Allow-Origin’ header must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’: echo the specific origin and add Access-Control-Allow-Credentials: true.

Open the Network tab, find the failed request (and the OPTIONS request before it, if any), and look at the status and response headers. That usually makes the cause obvious.

Fix 1: send CORS headers from the server

If you control the API, allow your front-end origin explicitly. A plain Node.js example that handles the preflight too:

import http from "node:http";

const ALLOWED_ORIGINS = new Set(["http://localhost:5173"]);

http.createServer((req, res) => {
  const origin = req.headers.origin;
  if (origin && ALLOWED_ORIGINS.has(origin)) {
    res.setHeader("Access-Control-Allow-Origin", origin);
    res.setHeader("Vary", "Origin");
  }

  if (req.method === "OPTIONS") {
    res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
    res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
    res.setHeader("Access-Control-Max-Age", "600");
    res.writeHead(204).end();
    return;
  }

  res.writeHead(200, { "Content-Type": "application/json" });
  res.end(JSON.stringify({ ok: true }));
}).listen(3000, () => console.log("API on http://localhost:3000"));

With Express and the cors package the same thing is one line: app.use(cors({ origin: "http://localhost:5173" })). Flask has the flask-cors extension. Put CORS handling before authentication middleware so preflights are not rejected.

Fix 2: use a development proxy

During development you can avoid cross-origin requests entirely. Let the dev server forward /api to the backend, and call a relative URL such as fetch("/api/items"). For Vite:

// vite.config.js
import { defineConfig } from "vite";

export default defineConfig({
  server: {
    proxy: {
      "/api": "http://localhost:3000",
    },
  },
});

In production, serving the front end and API from the same origin behind one reverse proxy has the same effect.

Fix 3: call a third-party API from your backend

If the API is not yours and does not allow browser access, call it from your own server and have your page talk to that. This is also the right move when the call needs a secret key, which must never be in browser code.

What not to do

  • mode: "no-cors" silences the error but returns an opaque response you cannot read.
  • Browser extensions or flags that disable CORS only hide the problem on your machine; your users will still hit it.
  • Access-Control-Allow-Origin: * on an API that uses cookies will not work, and on private data it is a risk.

See also

  • 0019 fetch with timeout, retries and proper error handling A reusable fetchJson helper for Node 20+ and browsers that adds a timeout, retries with backoff for temporary failures, and clear errors… Intermediate · How-to · Any system Script Async code · Making requests 15 Oct 2026
  • 0026 Fix: TypeError: Cannot read properties of undefined (reading ‘x’) You tried to read a property from a value that is undefined or null. Find which value is missing, then guard it… Beginner · Fix · Any system Article Basics · Common errors 15 Oct 2026
  • 0027 Fix: SyntaxError: Cannot use import statement outside a module The file uses ES module import syntax, but Node or the browser is loading it as a classic script or CommonJS. Tell… Intermediate · Fix · Any system Article Common errors · Node.js 15 Oct 2026
  • 0081 How an HTTP request works: methods, headers, and body An HTTP request is a short text message a client sends to a server: a method and path, some headers, and sometimes… Beginner · Concept · Any system Article Making requests 15 Oct 2026
  • 0083 Test a JSON API with curl A runnable bash script showing the curl commands you need most when testing an API: GET, POST JSON, custom headers, Bearer tokens,… Beginner · How-to · Linux, macOS, Windows Script Authentication · Making requests 15 Oct 2026
  • 0084 Tiny JSON echo server for testing HTTP clients A standard-library Python server that echoes back the method, path, query, headers, and body of every request, and can return any status… Intermediate · How-to · Any system Script Files & automation · Making requests 15 Oct 2026

Repos in the wild

  • Requests: HTTP for humans psf/requests Requests is the classic Python library for calling web APIs and downloading pages, with a simple API for GET and POST requests, headers, JSON and sessions. GitHub
  • Axios axios/axios A promise-based HTTP client for browsers and Node.js with interceptors, automatic JSON handling, request cancellation and a consistent API in both environments. GitHub
  • curl and libcurl (curl/curl) curl/curl The source of curl, the command-line tool for transferring data with URLs, and libcurl, the C library behind it that many other programs use for HTTP. GitHub

History

Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.

  1. commitpedia-admin +4,047 chars

Report a problem

Something wrong, unsafe or copied? Tell the editors.
What is wrong?