Am I Hackable?
Back to Learn

CORS Explained: Why Your Browser Blocks Requests

Benji··3 min read

The short version

CORS (Cross-Origin Resource Sharing) is a browser security mechanism that controls which websites can make requests to your server. If your frontend at app.example.com tries to fetch data from api.otherdomain.com, the browser checks if api.otherdomain.com explicitly allows it.

If the server doesn't say "yes, that origin is allowed," the browser blocks the response. That's the CORS error you keep seeing in your console.

Why does this exist?

Imagine you're logged into your bank. You visit a random website. Without CORS (and the same-origin policy it builds on), that random website could make fetch requests to your bank's API, and your browser would send your cookies along. The attacker could read your balance, initiate transfers, anything.

The same-origin policy prevents this by default: a page from evil.com cannot read responses from bank.com. CORS is the controlled way for bank.com to say "actually, trusted-app.com is allowed to read my responses."

How CORS works

When your browser makes a cross-origin request, here's what happens:

  1. Simple requests (GET, POST with basic content types): The browser sends the request and checks the response for Access-Control-Allow-Origin. If the header matches your origin, you get the data. If not, blocked.

  2. Preflight requests (PUT, DELETE, custom headers): The browser sends an OPTIONS request first, asking "are you cool with this?" The server responds with allowed methods, headers, and origins. Only if everything checks out does the real request happen.

The MDN CORS documentation explains the full flow in detail.

The headers that matter

Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true

Common mistakes

Setting Access-Control-Allow-Origin: * with credentials. The OWASP CORS guidance warns against this. If you need credentials, specify the exact origin.

Reflecting the Origin header without validation. Some developers read the incoming Origin header and echo it back as Access-Control-Allow-Origin. This is effectively the same as using * but with credentials enabled. An attacker's site gets full access.

Thinking CORS protects your API. CORS is enforced by browsers only. A curl command, a server-side script, or Postman will never hit a CORS error. CORS does not replace authentication, rate limiting, or input validation.

Not handling the preflight OPTIONS request. If your server returns a 404 or 500 for OPTIONS requests, every non-simple request will fail. Make sure your server handles OPTIONS on CORS-enabled endpoints.

How to fix CORS errors

  1. Identify the requesting origin from your browser's error message.
  2. Add that origin to your server's Access-Control-Allow-Origin header.
  3. Handle OPTIONS preflight requests if you're using custom headers or methods.
  4. Don't use * if you need cookies or authentication. Specify the exact origin instead.

If you're using a framework like Express, Next.js, or FastAPI, they all have CORS middleware that handles this for you.

Check your site

Want to know if your site has this issue? Scan it now and find out in 60 seconds.

Frequently Asked Questions

Why does my browser block CORS requests?
Browsers enforce the same-origin policy by default. CORS is the mechanism that lets servers explicitly opt in to cross-origin requests. If the server doesn't send the right headers, the browser blocks the response.
Is Access-Control-Allow-Origin: * safe?
For public, read-only APIs it's fine. For anything that uses cookies or authentication, it's dangerous. An attacker's site could make requests to your API and read the responses.
Does CORS protect my API?
No. CORS is a browser-side mechanism. Server-to-server requests, curl, Postman, and scripts all bypass CORS entirely. You still need authentication and authorization on your API.

Your AI writes the code. We find what it missed.

Paste your URL. Security audit in 60 seconds.

Scan my app