CORS

What is CORS? A Plain English Explanation

Browsers block requests from one domain to another by default. CORS is the mechanism that lets servers say "yes, requests from this other domain are allowed." Without it, your React frontend on app.example.com cannot call your API on api.example.com.

The same-origin policy

Browsers enforce the same-origin policy: JavaScript on page A can only make requests to the same origin as page A. Origin = protocol + hostname + port. https://app.example.com and https://api.example.com are different origins — even though they share the same domain.

What CORS does

CORS (Cross-Origin Resource Sharing) is a system where servers include response headers that tell the browser which cross-origin requests are allowed. The browser checks these headers and decides whether to let JavaScript read the response.

# Server response includes:
Access-Control-Allow-Origin: https://app.example.com

# Browser sees this and allows JavaScript to read the response
# Without it, the browser blocks the response even if the server returned 200

How a simple CORS request works

  1. JavaScript on app.example.com calls fetch('https://api.example.com/data')
  2. Browser adds Origin: https://app.example.com to the request
  3. Server processes the request normally and returns a response
  4. Browser checks the response for Access-Control-Allow-Origin
  5. If the origin matches, browser gives the response to JavaScript. If not, browser blocks it.

The preflight request

For non-simple requests (POST with JSON, PUT, DELETE, or requests with custom headers like Authorization), the browser first sends an OPTIONS request to check permission. Only if the server responds correctly does the browser send the actual request.

OPTIONS /api/data HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization, Content-Type

# Server must respond:
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type
# HTTP 204

Common misconceptions

Test your CORS config → CORSFixer