CORS (Cross-Origin Resource Sharing) is a browser security mechanism that controls whether a web page can access resources from a different origin using APIs like fetch().
π What is CORS?
CORS is a security feature implemented by browsers that allows or blocks cross-origin HTTP requests based on the response headers sent by the server.
π‘ What is an Origin?
An origin is defined by the combination of:
- π Protocol (HTTP or HTTPS)
- π Domain (example.com)
- π’ Port (80, 443, 3000, etc.)
π Same Origin vs Cross Origin
| URL A | URL B | Same Origin? |
|---|---|---|
| https://example.com | https://example.com | β Yes |
| https://example.com | http://example.com | β No (different protocol) |
| https://example.com | https://api.example.com | β No (different subdomain) |
| https://example.com | https://example.com:3000 | β No (different port) |
π Basic Fetch Request
Simple Fetch
fetch("https://api.example.com/users")
.then(response => response.json())
.then(data => console.log(data));If the server does not allow cross-origin requests from your website, the browser blocks access to the response.
π« Typical CORS Error
Browser Console
Access to fetch at
'https://api.example.com'
from origin
'https://mywebsite.com'
has been blocked by CORS policy.π‘οΈ How CORS Works
When a cross-origin request is made:
- π€ The browser sends the HTTP request.
- π₯οΈ The server responds with CORS headers.
- β If the headers allow the request, JavaScript can access the response.
- β Otherwise, the browser blocks the response.
π Important CORS Headers
| Header | Purpose |
|---|---|
| Access-Control-Allow-Origin | Specifies which origins are allowed. |
| Access-Control-Allow-Methods | Lists allowed HTTP methods. |
| Access-Control-Allow-Headers | Lists allowed request headers. |
| Access-Control-Allow-Credentials | Allows cookies and authentication credentials. |
| Access-Control-Max-Age | Caches preflight responses for a period of time. |
β Allowed Origin Example
Server Response Headers
Access-Control-Allow-Origin: https://mywebsite.comπ Allow All Origins
Public API
Access-Control-Allow-Origin: *Note
βοΈ Fetch Options
Fetch with Options
fetch("https://api.example.com/users", {
method: "GET",
mode: "cors"
});π Fetch Modes
| Mode | Description |
|---|---|
| cors | Default for cross-origin requests. Uses the CORS protocol. |
| same-origin | Allows requests only to the same origin. |
| no-cors | Sends a limited request but returns an opaque response that JavaScript cannot meaningfully inspect. |
| navigate | Used internally for browser navigation, not for fetch(). |
π Sending Credentials
If cookies or HTTP authentication are required, include credentials in the request.
Fetch with Credentials
fetch("https://api.example.com/profile", {
credentials: "include"
});The server must also return:
Required Server Header
Access-Control-Allow-Credentials: trueβοΈ Preflight Requests
Some requests require a preflight request. The browser sends an OPTIONS request first to check whether the actual request is allowed.
Requests That Commonly Trigger a Preflight
- π€ Methods such as PUT, PATCH, or DELETE.
- π Custom request headers (for example, X-API-Key).
- π¦ A Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain.
π Example POST Request
POST Request
fetch("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "John"
})
});Because this request sends JSON, browsers typically perform a preflightOPTIONS request before sending the actual POST.
π Complete Example
GET Data with Error Handling
async function loadUsers() {
try {
const response = await fetch(
"https://api.example.com/users"
);
if (!response.ok) {
throw new Error("Request failed");
}
const users =
await response.json();
console.log(users);
} catch (error) {
console.error(error);
}
}
loadUsers();π CORS vs Same-Origin Policy
| Feature | Same-Origin Policy | CORS |
|---|---|---|
| Purpose | Restricts cross-origin access by default. | Provides a controlled way to allow cross-origin access. |
| Configured By | Browser | Server response headers |
| Default Behavior | Blocks access | Allows access only when permitted by the server |
β οΈ Common Mistakes
- β Trying to "fix" CORS from frontend JavaScript. CORS is primarily controlled by the server.
- β Assuming mode: "no-cors" bypasses CORS restrictions. It does not provide access to the response body.
- β Using Access-Control-Allow-Origin: * together with credentialed requests.
- β Forgetting to configure the server to handle preflight OPTIONS requests.
Note
β Best Practices
- π Allow only trusted origins instead of using * whenever possible.
- π Handle preflight requests correctly on the server.
- πͺ Use credentials only when necessary.
- β‘ Keep custom headers to a minimum to reduce unnecessary preflight requests.
- π Configure CORS on the backend rather than attempting to work around it in frontend code.
π― Summary
CORS is a browser security mechanism that works alongside the Same-Origin Policy to control cross-origin HTTP requests. When using theFetch API, the browser checks the server's CORS response headers before allowing JavaScript to access the response. Proper server-side CORS configuration is essential for secure communication between different origins.