Question
Is there a way to disable the Same-Origin Policy in Google Chrome? If so, what are the risks, and what safer approaches should be used when developing or testing a web application?
Short Answer
You will learn what the Same-Origin Policy (SOP) protects, why a browser-wide bypass is unsafe, and how to solve legitimate cross-origin development problems with CORS, a backend proxy, and a local development server.
Concept
The Same-Origin Policy (SOP) is a browser security rule that limits how a page loaded from one origin can read resources from another origin.
An origin consists of three parts:
- Protocol, such as
https - Host, such as
app.example.com - Port, such as
443
For example, these are different origins:
https://app.example.com
http://app.example.com # different protocol
https://api.example.com # different host
https://app.example.com:3000 # different port
Without SOP, a malicious page could potentially read private data from sites where a visitor is signed in, such as an email provider, banking site, or internal company tool.
Chrome does not provide a safe, normal-browsing setting to turn off SOP. Developer-only browser launch configurations that weaken web security do exist, but they should not be used for everyday browsing, personal profiles, or as a deployed application solution. They remove an important protection for every page opened in that browser session.
For a legitimate application, solve the actual cross-origin problem instead:
- Configure the server with CORS headers.
- Send requests through your own backend server or development proxy.
- Serve files through a local HTTP server instead of opening them with
file://. - Use an API designed to accept browser requests from your application's origin.
This matters because browser security is enforced in the user's browser. JavaScript cannot safely override SOP for itself.
Mental Model
Imagine every origin is an apartment building with a controlled entrance.
A page from https://shop.example can freely access rooms in its own building. It cannot walk into https://bank.example and inspect its rooms merely because the same person happens to be logged into both buildings.
CORS is like the bank's receptionist explicitly saying: “Visitors from this specific building may receive this specific public information.” The destination server, not the visiting page, decides whether access is allowed.
Disabling browser web security is like removing the access controls from every building you visit. It may make one test easier, but it exposes unrelated accounts and sites too.
Syntax and Examples
Browsers commonly enforce SOP when JavaScript uses fetch to read a cross-origin response.
fetch("https://api.example.com/products")
.then((response) => response.json())
.then((products) => console.log(products))
.catch((error) => console.error("Request failed:", error));
If api.example.com does not permit requests from the page's origin, the browser blocks JavaScript from reading the response and reports a CORS-related error.
The usual fix is on the API server. For example, an Express API can allow one known frontend origin:
import express from "express";
import cors from "cors";
const app = express();
app.use(
cors({
origin: "http://localhost:5173"
})
);
app.(, {
response.([{ : , : }]);
});
app.(, {
.();
});
Step by Step Execution
Consider a frontend running at http://localhost:5173 and an API running at http://localhost:3000.
const response = await fetch("http://localhost:3000/products");
const products = await response.json();
console.log(products);
Execution proceeds as follows:
- The browser sees that the page origin is
http://localhost:5173. - It sees that the request target is
http://localhost:3000. - The ports differ (
5173and3000), so this is a cross-origin request. - The browser sends the request to the API.
- The API responds with JSON and, when correctly configured,
Access-Control-Allow-Origin: http://localhost:5173. - The browser checks whether that header permits the frontend origin.
- If it does,
response.json()reads the JSON successfully. - If the header is missing or names another origin, JavaScript cannot read the response, even if the server received and processed the request.
For some requests, such as those using custom headers or non-simple HTTP methods, the browser first sends a preflight request to ask the server which methods and headers it permits.
Real World Use Cases
Common situations involving SOP and CORS include:
- Frontend and API on separate domains: A React, Vue, or plain JavaScript frontend calls an API hosted elsewhere.
- Local development: A development server runs on one port while an API runs on another port.
- Third-party services: A browser app requests maps, payment, analytics, or public data APIs that explicitly support browser access.
- Backend integration: Your server calls a third-party API with a secret key, then returns only the data your frontend needs.
- Static sites: A site deployed on a CDN calls an API whose CORS policy must list the production site origin.
In each case, the intended solution is server authorization through CORS or a backend intermediary—not weakening the browser's security globally.
Real Codebase Usage
Real projects usually handle cross-origin access with explicit, environment-aware configuration.
Restrict allowed origins
Avoid allowing every website unless the API is truly public and does not use credentials.
const allowedOrigins = new Set([
"http://localhost:5173",
"https://app.example.com"
]);
app.use(
cors({
origin(origin, callback) {
// Requests without an Origin header can include server-to-server tools.
if (!origin || allowedOrigins.has(origin)) {
callback(null, true);
} else {
callback(new Error("Origin is not allowed by CORS"));
}
}
})
);
Use a development proxy
A frontend tool can proxy /api requests to a local backend. The browser then talks to the frontend origin, while the development server forwards the request.
For example, a Vite configuration can proxy API requests:
import { defineConfig } from "vite";
export ({
: {
: {
:
}
}
});
Common Mistakes
Treating CORS as a client-side problem
This does not grant permission:
fetch("https://api.example.com/data", {
mode: "no-cors"
});
no-cors can produce an opaque response. Your code cannot read its status, headers, or body. It is not a solution for reading API data.
Adding Access-Control-Allow-Origin to the request
This is incorrect:
fetch("https://api.example.com/data", {
headers: {
"Access-Control-Allow-Origin": "*"
}
});
Access-Control-Allow-Origin is a response header sent by the server, not a request header the browser client can use to authorize itself.
Using * with cookies or HTTP authentication
This combination is invalid for credentialed browser requests:
// Unsafe/invalid for credentialed cross-origin requests
Access-Control-Allow-Origin: *
---:
Comparisons
| Approach | Where it is configured | Appropriate use | Important limitation |
|---|---|---|---|
| Same-Origin Policy | Browser | Protecting users by default | Not something a web page should disable |
| CORS | Destination server | Permit selected browser origins | Does not replace authentication |
| Development proxy | Local frontend server | Avoid local cross-origin friction | Must be configured separately for production |
| Backend proxy | Your application server | Hide secrets and integrate external APIs | Adds server code and operational responsibility |
no-cors request mode | Browser request option | Limited requests where response does not need to be read | Response body is unavailable to JavaScript |
Cheat Sheet
- Origin = protocol + host + port.
- Different ports are different origins:
localhost:3000is notlocalhost:5173. - SOP prevents a page from freely reading cross-origin responses.
- CORS permission comes from the response server, not frontend JavaScript.
- Use a specific allowed origin when possible:
Access-Control-Allow-Origin: https://app.example.com
- Requests with custom headers,
PUT,PATCH,DELETE, and similar cases may trigger anOPTIONSpreflight. mode: "no-cors"does not make API JSON readable.- Do not expose private API keys in frontend code; use a backend proxy.
- Use a local HTTP development server rather than
file://pages. - Avoid disabling browser web security; it is unsafe and does not fix the production configuration.
FAQ
Can I disable the Same-Origin Policy in Chrome?
Chrome has developer-only ways to start a separate session with web security weakened, but it is unsafe for normal browsing and is not a solution for an application. Prefer fixing CORS or using a proxy.
Why does my request work in Postman but fail in Chrome?
CORS is enforced by browsers. Postman and server-to-server clients are not subject to the browser's Same-Origin Policy.
Does CORS block the request from reaching the API?
Not always. Often the request reaches the server, but the browser blocks JavaScript from reading the response because the required CORS headers are absent or do not match.
Can JavaScript add its own CORS permission header?
No. The destination server must send Access-Control-Allow-Origin in its response.
Is Access-Control-Allow-Origin: * always safe?
No. It is suitable only for intentionally public resources and cannot be combined with credentialed cross-origin requests.
Why are two localhost ports considered different origins?
The port is part of an origin. Therefore, http://localhost:3000 and http://localhost:5173 are different origins.
Should I use a CORS browser extension for development?
It can mask the real issue and may affect browser security. Configure your local API or a development proxy so testing matches the behavior users will have.
Mini Project
Description
Build a small products API that explicitly allows a local frontend origin. This demonstrates the correct way to enable a browser application on one port to read an API response from another port.
Goal
Return product data from an Express API and allow only http://localhost:5173 to read it from browser JavaScript.
Requirements
- Create an Express server that listens on port 3000.
- Add a
GET /productsendpoint that returns JSON. - Allow requests from
http://localhost:5173using CORS. - Create a small frontend page that fetches and displays the products.
- Run the frontend through a local HTTP server rather than a
file://URL.
Keep learning
Related questions
Abort Ajax Requests with jQuery jqXHR.abort()
Learn how to cancel an in-progress jQuery Ajax request with jqXHR.abort(), handle abort status safely, and avoid stale UI updates.
Access the Correct this Inside a JavaScript Callback
Learn why JavaScript this changes in callbacks and how to preserve an object context using bind, arrow functions, and event handler patterns.
Add Key-Value Pairs to JavaScript Objects
Learn how to add key-value pairs to JavaScript objects with dot and bracket notation, dynamic keys, examples, and common mistakes.