---
title: CORS Errors Explained (and how to fix them)
description: Every web developer meets the dreaded 'blocked by CORS policy' error. It's not a bug — it's a security feature. Here's what CORS is, why the browser blocks your request, and how to fix it properly.
canonical: https://watchfor.io/blog/cors-errors-explained
---

# CORS Errors Explained (and how to fix them)

2026-03-02 · WatchFor Team · Monitoring · web, debugging, api

Every web developer meets the dreaded 'blocked by CORS policy' error. It's not a bug — it's a security feature. Here's what CORS is, why the browser blocks your request, and how to fix it properly.

You wire up a frontend to call your API, hit refresh, and the console lights up red: **"Access to fetch … has been blocked by CORS policy."** Your API works fine in a direct test, so what gives?

The frustrating truth: **CORS is working as intended.** It's a browser security feature, not a malfunction — and once you understand it, the fix is straightforward.

## What CORS is

**CORS (Cross-Origin Resource Sharing)** is a browser rule about which sites can call which APIs. By default, browsers enforce the **same-origin policy**: a page at `https://myapp.com` can't make JavaScript requests to `https://api.other.com` unless that other server *explicitly allows it*.

> **The key insight:** CORS is enforced by the **browser**, to protect *users* — not by your server, and not against you. Your API is fine; the browser is refusing to hand the response to JavaScript from a different origin unless the server says it's allowed.

That's why the same request works from a tool like curl (no browser, no CORS) but fails in the browser.

## What counts as a different "origin"

An origin is the combination of **scheme + host + port**. Any difference makes it cross-origin:

| From | To | Cross-origin? |
| --- | --- | --- |
| `https://app.com` | `https://api.app.com` | ✅ Yes (different host) |
| `https://app.com` | `http://app.com` | ✅ Yes (different scheme) |
| `https://app.com:443` | `https://app.com:8080` | ✅ Yes (different port) |
| `https://app.com/a` | `https://app.com/b` | ❌ No (same origin) |

## How to fix it (the right way)

The fix lives on the **server** being called — it must send headers permitting the calling origin:

1. **Send `Access-Control-Allow-Origin`.** Set it to the specific origin that's allowed (e.g. `https://myapp.com`), or `*` for a fully public API.
2. **Handle the preflight.** For many requests the browser first sends an `OPTIONS` "preflight" asking permission. Your server must answer it with the allowed methods and headers (`Access-Control-Allow-Methods`, `Access-Control-Allow-Headers`).
3. **Allow credentials if needed.** Sending cookies/auth? Set `Access-Control-Allow-Credentials: true` — and note you then **can't** use `*` for the origin; you must name it.

| Header | Purpose |
| --- | --- |
| `Access-Control-Allow-Origin` | Which origin(s) may read the response |
| `Access-Control-Allow-Methods` | Which HTTP methods are allowed |
| `Access-Control-Allow-Headers` | Which custom headers are allowed |
| `Access-Control-Allow-Credentials` | Whether cookies/auth may be sent |

## What *not* to do

- **Don't blindly set `Access-Control-Allow-Origin: *` on a private/authenticated API.** That opens it to every site. Allow only the origins you trust.
- **Don't try to "fix" it in the frontend.** CORS is server-side policy; a browser can't be told to ignore it (and shouldn't be).
- **Don't reach for a proxy** as a first resort when the real fix is one header.

## The bottom line

| | In one line |
| --- | --- |
| **What** | A browser rule on cross-origin requests — a security feature. |
| **Why blocked** | The target server didn't say your origin is allowed. |
| **Fix** | Send the right `Access-Control-Allow-*` headers from the server. |
| **Careful** | Don't use `*` on private APIs; name trusted origins. |

CORS errors feel like the browser fighting you, but it's protecting your users. The fix is almost always a small set of response headers on the API — set them correctly (and narrowly), and the red console messages disappear.

If you build APIs, monitor their headers and responses with the [API monitoring guide](/blog/api-monitoring-guide); inspect any URL's headers with the free [HTTP header checker](/http-header-checker).

---

Canonical page: https://watchfor.io/blog/cors-errors-explained · All articles: https://watchfor.io/blog/all.md · Site guide: https://watchfor.io/llms.txt
