What is CORS? | Cross-Origin Resource Sharing Explained

CORS (Cross-Origin Resource Sharing) is a browser security mechanism that controls how web pages request resources from a different origin. Learn how CORS works, how to configure it, and how to fix common CORS errors.

CORS (Cross-Origin Resource Sharing) is a browser security mechanism that controls whether a web page running at one origin is allowed to request resources from a different origin.


TL;DR CORS is enforced by browsers, not servers. When JavaScript at app.example.com fetches data from api.other.com, the browser checks whether the API server explicitly permits this cross-origin request by examining HTTP response headers — primarily Access-Control-Allow-Origin. If the header is missing or doesn’t match, the browser blocks the response, even though the server successfully processed it. CORS errors are client-side blocks, not server-side failures. The fix is always adding the correct response headers on the server (or edge) that receives the request.


What is CORS?

CORS (Cross-Origin Resource Sharing) is a W3C standard implemented by all modern browsers. It extends the same-origin policy — the rule that a web page can only access resources from the exact same origin (protocol + domain + port) — by allowing servers to explicitly declare which other origins are permitted to access their resources.

An origin is defined by three components:

  • Protocolhttps:// vs http://
  • Domainexample.com vs api.example.com
  • Port:443 vs :3000

Two URLs have the same origin only if all three match exactly. https://app.example.com and https://api.example.com are different origins because the subdomain differs.


Why CORS exists

Without the same-origin policy, any malicious website could use JavaScript to make requests to your bank, email, or any authenticated service — and the browser would send your session cookies automatically. The browser would then receive and expose the response to the attacker’s script.

The same-origin policy prevents this by blocking cross-origin reads. CORS then provides a controlled way for servers to opt in to cross-origin sharing — selectively and explicitly.


How CORS works

Simple requests

A simple request is a cross-origin request that meets all of these conditions:

  • Method is GET, POST, or HEAD
  • Headers are only Accept, Accept-Language, Content-Language, or Content-Type (with value application/x-www-form-urlencoded, multipart/form-data, or text/plain)

For simple requests, the browser sends the request directly and includes an Origin header. The server must respond with Access-Control-Allow-Origin matching the request origin. If it doesn’t, the browser blocks the response from reaching JavaScript.

Request:
GET /data HTTP/1.1
Origin: https://app.example.com
Response:
Access-Control-Allow-Origin: https://app.example.com

Preflight requests

For requests that don’t meet the simple request criteria — such as PUT, DELETE, PATCH, or requests with custom headers like Authorization — the browser first sends a preflight request using the OPTIONS method.

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

The server must respond to the preflight with the appropriate CORS headers before the browser sends the actual request:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Max-Age: 86400

If the preflight fails, the browser never sends the actual request.


CORS response headers

HeaderPurposeExample value
Access-Control-Allow-OriginSpecifies which origin(s) may access the resourcehttps://app.example.com or *
Access-Control-Allow-MethodsAllowed HTTP methods for cross-origin requestsGET, POST, PUT, DELETE
Access-Control-Allow-HeadersAllowed request headersAuthorization, Content-Type
Access-Control-Allow-CredentialsWhether cookies/credentials are includedtrue
Access-Control-Max-AgeHow long (seconds) the preflight result can be cached86400
Access-Control-Expose-HeadersWhich response headers JavaScript can readX-Request-ID

Critical rule: You cannot use Access-Control-Allow-Origin: * together with Access-Control-Allow-Credentials: true. Browsers reject this combination. You must specify the exact origin when credentials are involved.


Common CORS errors and fixes

Error messageCauseFix
No 'Access-Control-Allow-Origin' header is presentServer doesn’t return the CORS headerAdd Access-Control-Allow-Origin to the response
The value of 'Access-Control-Allow-Origin' does not equal the supplied originHeader value doesn’t match the requesting originDynamically reflect the request Origin or list all allowed origins
Response to preflight request doesn't pass access control checkPreflight OPTIONS request not handledAdd OPTIONS handler that returns proper CORS headers
Credential flag is true but Access-Control-Allow-Credentials is not trueCredentials sent but server didn’t permit themAdd Access-Control-Allow-Credentials: true and specify exact origin
Method PUT is not allowedMethod missing from Access-Control-Allow-MethodsAdd the required method to the allowed methods header
Request header 'Authorization' is not allowedCustom header not listed in Access-Control-Allow-HeadersAdd the header to Access-Control-Allow-Headers

CORS security risks

Wildcard with credentials

Using Access-Control-Allow-Origin: * is safe for public APIs that don’t use cookies or session tokens. Never combine * with Access-Control-Allow-Credentials: true — it exposes authenticated data to any origin.

Reflecting the Origin header without validation

Some implementations blindly reflect the Origin request header back as Access-Control-Allow-Origin. If you do this without validating against an allowlist, you allow any origin to access your API. Always validate the Origin value against a whitelist before reflecting it.

Null origin

The Origin: null value is sent by browsers for requests from file:// URLs or sandboxed iframes. Never allowlist null as a permitted origin — it can be exploited.


Frequently asked questions

What is a CORS error? A CORS error is a browser-enforced block on a cross-origin HTTP response. It means JavaScript at one origin tried to read a response from a different origin, but the server’s response didn’t include the headers granting permission. The request itself reached the server — the browser just blocked the response from being accessible to the script.

Does CORS apply to server-to-server requests? No. CORS is enforced by browsers only. When your backend server calls another API, there is no CORS enforcement — the call goes through regardless. CORS only applies when JavaScript running in a browser makes a cross-origin request.

What is the difference between CORS and the same-origin policy? The same-origin policy is the default browser security rule that blocks cross-origin reads. CORS is the mechanism that allows servers to selectively relax that restriction by returning specific HTTP headers. CORS doesn’t bypass the same-origin policy — it provides a standardized way for servers to opt in to cross-origin access.

Can I disable CORS? You cannot disable CORS in browsers — it is enforced at the browser level. What you can do is configure your server to return the correct CORS headers that permit your specific cross-origin requests. Browser extensions that “disable CORS” only work by intercepting responses and injecting the missing headers client-side.

What does Access-Control-Allow-Origin: * mean? It means any origin is allowed to read the response. This is appropriate for fully public APIs (no authentication, no cookies). Never use * for APIs that require authentication or access to user data.

What is a preflight request? A preflight request is an automatic OPTIONS request that the browser sends before certain cross-origin requests to ask the server what it permits. The server must respond with CORS headers approving the method, headers, and origin before the browser sends the actual request. Preflight responses can be cached using Access-Control-Max-Age.

How do I fix CORS errors in development? In development, the most common approach is to configure your local API server to return Access-Control-Allow-Origin: http://localhost:3000 (your frontend dev server URL). Do not use a browser extension to bypass CORS in development — it hides real problems that will appear in production.

Can a CDN or edge handle CORS for me? Yes. You can configure CORS headers at the edge — adding Access-Control-Allow-Origin and other headers to responses before they reach the browser, without modifying the origin server. This is useful for third-party APIs you don’t control, or for centralizing CORS policy across multiple origins.

stay up to date

Subscribe to our Newsletter

Get the latest product updates, event highlights, and tech industry insights delivered to your inbox.