Glossary
CORS
Cross-Origin Resource Sharing
By Buğra SözeriPublished Updated
CORS (Cross-Origin Resource Sharing) is the browser mechanism that controls when JavaScript from one origin can read responses from another. By default, browsers block cross-origin XHR/fetch responses — CORS headers from the server unlock controlled access.
The two main response headers:
Access-Control-Allow-Origin: which origins can read the response. Either a specific origin or*(any).Access-Control-Allow-Credentials: whether cookies are allowed to flow with cross-origin requests.truerequires the origin to be specific, not*.
For requests that aren’t “simple” (custom headers, non-GET/POST methods, JSON bodies), the browser sends a preflight OPTIONS request first to check what’s allowed. The server responds with Access-Control-Allow-Methods and Access-Control-Allow-Headers; the actual request only fires if preflight succeeds.
Common misconceptions: CORS isn’t a server-side security mechanism — it’s a browser-enforced restriction that protects users from one site reading data on their behalf from another site. Servers can still receive and process cross-origin requests; CORS just controls whether the browser hands the response back to the calling JS.
What “origin” means precisely: the tuple (scheme, host, port). http://example.com and https://example.com are different origins (different scheme). https://api.example.com and https://example.com are different origins (different subdomain). https://example.com:8080 and https://example.com are different origins (different port). This is the same-origin policy that CORS layers exceptions on top of. Internet Explorer ignored the port part — a quirk that produced years of cross-browser bugs until IE’s retirement removed the question.
Common production gotchas: wildcard Access-Control-Allow-Origin: * blocks credentials by spec; if you need cookies on a cross-origin request you must echo the request’s Origin back specifically. Adding a Authorization header upgrades the request from “simple” to “preflighted”, doubling the round-trips — caching the preflight via Access-Control-Max-Age (up to 7200 seconds in Chrome, 600 in Firefox) is the standard mitigation. Finally, the browser’s CORS error in the DevTools console is genuinely the browser’s decision — server logs will show the request reached the backend and was processed normally; the response was just discarded client-side. Reference: WHATWG Fetch — HTTP-CORS Protocol.
Worked example: a preflighted JSON POST
A SPA at https://app.example.com POSTs JSON with a bearer token to https://api.example.com/v1/orders. Because the request uses Content-Type: application/json and an Authorization header, it is non-simple. The browser first sends OPTIONS /v1/orders with Origin: https://app.example.com, Access-Control-Request-Method: POST, and Access-Control-Request-Headers: authorization,content-type. The server responds 204 with Access-Control-Allow-Origin: https://app.example.com, Access-Control-Allow-Methods: POST, Access-Control-Allow-Headers: authorization,content-type, and Access-Control-Max-Age: 600. Only then does the real POST fire. Setting Max-Age: 600 avoids the preflight for the next 10 minutes, eliminating one round-trip from every subsequent call — measurable as a 50-100ms cut on transatlantic links.
When CORS isn’t enough
CORS protects users from cross-origin reads; it does not protect servers from unwanted requests. State-changing endpoints still need CSRF tokens or SameSite cookies, and authentication still needs proper token validation server-side. A public API behind Access-Control-Allow-Origin: * is publicly callable by anyone — CORS just enabled the browser to surface that fact. For deeper architectural background see MDN’s CORS reference, which mirrors the WHATWG spec with practical examples.
Frequently asked questions
- What is CORS?
- CORS (Cross-Origin Resource Sharing) is a browser security mechanism that controls which cross-origin HTTP requests JavaScript can make. The browser blocks requests from one origin (e.g., app.example.com) to another (api.other.com) unless the server responds with the appropriate Access-Control-Allow-Origin header.
- How does CORS work in practice?
- A React app at https://app.example.com fetches from https://api.example.com/data. The browser adds an Origin header; the API must respond with Access-Control-Allow-Origin: https://app.example.com (or *). Without that header, the browser blocks the response even though the server sent it.
- What is the difference between a simple request and a CORS preflight?
- Simple requests (GET/POST with standard headers and content types) are sent directly with the Origin header. Preflight requests are sent automatically by the browser before complex requests (DELETE, custom headers, JSON body) as an OPTIONS call to ask the server if the real request is allowed.
- Does CORS protect the server from being accessed directly?
- No — CORS only applies to browser-based JavaScript. curl, Postman, and server-to-server calls ignore CORS entirely. CORS protects the user's browser from being tricked into sending authenticated cross-origin requests; it does not protect the API endpoint from direct access.
Related
Published May 15, 2026 · Last reviewed May 31, 2026