CORS Explained
Understand Cross-Origin Resource Sharing (CORS), discover how browsers handle cross-origin requests and learn best practices for configuring CORS securely.
Cross-Origin Resource Sharing (CORS) is a browser security mechanism that controls whether a web page can access resources hosted on another origin. It allows servers to explicitly specify which external websites are permitted to access their resources through HTTP requests.
Although CORS often appears to developers as an error message in the browser console, it is actually an important security feature designed to protect users from unauthorized cross-origin access. Understanding how CORS works is essential when building APIs, frontend applications and integrations between different domains.
What Is CORS?
CORS stands for Cross-Origin Resource Sharing. It extends the browser's Same-Origin Policy by allowing servers to selectively grant permission for cross-origin requests. Without CORS, browsers block many requests made from one origin to another.
What Is an Origin?
An origin is defined by three components: the protocol, the hostname and the port number. Two URLs belong to the same origin only when all three components are identical.
| URL | Same Origin as https://example.com |
|---|---|
| https://example.com | Yes |
| https://api.example.com | No |
| http://example.com | No |
| https://example.com:8080 | No |
Why CORS Exists
Without browser restrictions, any website could silently make requests to another website using a visitor's browser. CORS helps prevent malicious websites from reading sensitive data that belongs to other origins unless the destination server explicitly allows it.
Same-Origin Policy
The Same-Origin Policy is one of the browser's fundamental security mechanisms. By default, JavaScript running on one origin cannot freely read responses from another origin. CORS provides a controlled way to relax this restriction when appropriate.
How CORS Works
When a browser sends a cross-origin request, it includes an Origin header identifying the requesting website. The server decides whether that origin is allowed and responds with one or more CORS headers. The browser then determines whether the response should be made available to JavaScript.
| Step | Description |
|---|---|
| 1 | Browser sends a request with an Origin header |
| 2 | Server evaluates the origin |
| 3 | Server returns CORS headers |
| 4 | Browser allows or blocks JavaScript access |
Simple Requests
Some cross-origin requests are considered simple requests because they use supported HTTP methods and headers. These requests are sent directly without an additional permission check, although the server must still return appropriate CORS headers for the browser to expose the response.
Preflight Requests
More complex requests require a preflight request before the actual request is sent. The browser automatically sends an HTTP OPTIONS request asking the server whether the planned request is allowed.
| Request Type | Preflight Required |
|---|---|
| Simple GET | Usually No |
| Simple POST | Usually No |
| PUT | Yes |
| DELETE | Yes |
| Custom headers | Yes |
Important CORS Headers
CORS behavior is controlled entirely through HTTP response headers. These headers tell the browser which origins, methods and request headers are permitted when accessing a resource.
| Header | Purpose |
|---|---|
| Access-Control-Allow-Origin | Specifies allowed origins |
| Access-Control-Allow-Methods | Lists permitted HTTP methods |
| Access-Control-Allow-Headers | Lists allowed request headers |
| Access-Control-Allow-Credentials | Allows cookies and credentials |
| Access-Control-Max-Age | Caches preflight responses |
| Access-Control-Expose-Headers | Makes selected response headers accessible to JavaScript |
Access-Control-Allow-Origin
This is the most important CORS header. It specifies which origin is allowed to access the resource. The server may return a specific origin or, in some situations, the wildcard character (*).
Access-Control-Allow-Origin: https://example.comAllowed Methods
The Access-Control-Allow-Methods header tells browsers which HTTP methods are permitted for cross-origin requests after a successful preflight check.
Access-Control-Allow-Methods: GET, POST, PUT, DELETEAllowed Headers
When a request contains custom headers such as Authorization or X-API-Key, the server must explicitly allow them using the Access-Control-Allow-Headers response header.
Access-Control-Allow-Headers: Authorization, Content-TypeCredentials
Browsers normally omit cookies and other credentials from cross-origin requests unless explicitly configured to include them. If credentials are allowed, the server must also return Access-Control-Allow-Credentials: true together with a specific allowed origin.
| Configuration | Allowed |
|---|---|
| Wildcard (*) + Credentials | No |
| Specific Origin + Credentials | Yes |
Preflight Requests Explained
Before sending certain cross-origin requests, browsers automatically perform a preflight request using the HTTP OPTIONS method. This request asks the server whether the actual request should be allowed before any potentially unsafe action is performed.
When Preflight Happens
- Using PUT, PATCH or DELETE requests.
- Sending custom request headers.
- Using certain Content-Type values.
- Making requests that are not considered simple requests.
Common CORS Errors
CORS problems usually appear as browser console errors stating that a request has been blocked by the CORS policy. In many cases, the server actually processed the request successfully—the browser simply refused to expose the response to JavaScript because the required CORS headers were missing or incorrect.
| Common Cause | Typical Solution |
|---|---|
| Missing Access-Control-Allow-Origin | Configure the server to return it |
| Origin not allowed | Whitelist the requesting origin |
| Missing allowed headers | Add Access-Control-Allow-Headers |
| Credentials with wildcard origin | Return a specific origin instead |
CORS and APIs
Most modern REST APIs and GraphQL APIs rely on CORS when they are accessed from web browsers. Since frontend applications and APIs are often hosted on different domains or ports, properly configured CORS headers are essential for allowing legitimate cross-origin communication while preventing unauthorized access.
CORS Does Not Replace Authentication
A common misconception is that CORS provides authentication or authorization. It does not. CORS only tells browsers whether JavaScript may access a response. Servers must still authenticate users and verify permissions using mechanisms such as sessions, API keys, OAuth or JWT authentication.
| Security Mechanism | Purpose |
|---|---|
| CORS | Controls browser access between origins |
| Authentication | Verifies user identity |
| Authorization | Determines allowed actions |
Server-to-Server Requests
CORS restrictions apply only to web browsers. Server-side applications, backend services and command-line tools such as curl or Postman are generally not restricted by the browser's Same-Origin Policy and therefore do not enforce CORS.
Development vs Production
During development, frontend and backend applications are often hosted on different ports or local domains, making CORS configuration a common requirement. In production, applications may share the same origin or use carefully configured allowlists that specify which origins are permitted.
Common Mistakes
- Allowing every origin without considering security implications.
- Using wildcard origins together with credentials.
- Forgetting to handle OPTIONS preflight requests.
- Assuming CORS protects APIs from unauthorized access.
- Missing required Access-Control-Allow-Headers values.
- Debugging only the frontend without checking server responses.
Best Practices
- Allow only trusted origins whenever possible.
- Use specific origins instead of wildcards for authenticated APIs.
- Support OPTIONS requests correctly.
- Keep the list of allowed methods and headers as small as practical.
- Use HTTPS for all cross-origin communication.
- Test CORS behavior in real browsers during development.
Frequently Asked Questions
What does CORS stand for?
CORS stands for Cross-Origin Resource Sharing. It is a browser security mechanism that allows servers to specify which external origins may access their resources.
Why am I getting a CORS error?
Most CORS errors occur because the server did not return the required CORS response headers or because the requesting origin, method or headers are not permitted.
Does CORS affect Postman or curl?
No. CORS is enforced by web browsers. Server-side applications and API testing tools such as Postman and curl are generally not subject to CORS restrictions.
Can CORS replace authentication?
No. CORS only controls whether browsers expose responses to JavaScript. Authentication and authorization must still be implemented separately by the server.
What triggers a preflight request?
Browsers send a preflight OPTIONS request before certain cross-origin requests, such as those using methods like PUT or DELETE, custom request headers or non-simple content types.
Helpful HTTP Tools
A CORS Header Generator helps create valid CORS response headers, an HTTP Header Generator builds complete request and response headers for testing, an HTTP Request Builder allows you to construct browser-like requests, an HTTP Header Viewer displays all request and response headers during debugging, and an HTTP Response Formatter makes it easier to inspect API responses while troubleshooting cross-origin issues.
Conclusion
CORS is an essential browser security feature that enables controlled communication between different origins without weakening the Same-Origin Policy. By understanding origins, preflight requests and the purpose of each CORS response header, developers can configure APIs that are both secure and accessible. Correct CORS configuration, combined with proper authentication and authorization, results in web applications that work reliably across modern browsers while protecting users from unauthorized cross-origin access.