Question

Same-Origin Policy in Chrome: CORS and Safe Development Options

javascriptajaxgoogle-chrome

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.

Take Quiz

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.get("/products", (request, response) => {
  response.json([{ id: 1, name: "Notebook" }]);
});

app.listen(3000, () => {
  console.log("API running at http://localhost:3000");
});

The cors middleware sends a response header similar to:

Access-Control-Allow-Origin: http://localhost:5173

That header tells browsers that JavaScript from that exact origin may read the API response.

Install the packages for this example with:

npm install express cors

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:

  1. The browser sees that the page origin is http://localhost:5173.
  2. It sees that the request target is http://localhost:3000.
  3. The ports differ (5173 and 3000), so this is a cross-origin request.
  4. The browser sends the request to the API.
  5. The API responds with JSON and, when correctly configured, Access-Control-Allow-Origin: http://localhost:5173.
  6. The browser checks whether that header permits the frontend origin.
  7. If it does, response.json() reads the JSON successfully.
  8. 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 OPTIONS 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.

Take Quiz

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 default defineConfig({
  server: {
    proxy: {
      "/api": "http://localhost:3000"
    }
  }
});

The frontend uses a same-origin-looking URL:

const response = await fetch("/api/products");

Keep secrets on the server

If an external API requires a private token, do not put that token in browser JavaScript. Call the external API from your backend and return a limited response to the client.

Use guard clauses for origin validation

When manually setting CORS headers, validate the requested origin before reflecting it in a response. Never blindly copy arbitrary Origin values into Access-Control-Allow-Origin.

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: *
Access-Control-Allow-Credentials: true

When credentials are involved, the server must return a specific allowed origin and carefully configure cookie settings.

Confusing CORS with server access control

CORS protects browser-based reads. It does not stop scripts, command-line tools, or other servers from calling a public endpoint. Protect sensitive APIs with authentication and authorization as well.

Opening an app directly from disk

Opening index.html as file://... often causes confusing origin and module-loading behavior. Run a local development server instead.

npx vite

Disabling browser security to hide a configuration bug

A weakened browser session may make a local request appear to work, but other users' normal browsers will still enforce CORS. Fix the API or proxy configuration before deploying.

Comparisons

ApproachWhere it is configuredAppropriate useImportant limitation
Same-Origin PolicyBrowserProtecting users by defaultNot something a web page should disable
CORSDestination serverPermit selected browser originsDoes not replace authentication
Development proxyLocal frontend serverAvoid local cross-origin frictionMust be configured separately for production
Backend proxyYour application serverHide secrets and integrate external APIsAdds server code and operational responsibility
no-cors request modeBrowser request optionLimited requests where response does not need to be readResponse body is unavailable to JavaScript

CORS is not the opposite of SOP. SOP remains active; CORS is the server-provided permission mechanism that lets the browser make a controlled exception for a particular response.

Take Quiz

Cheat Sheet

  • Origin = protocol + host + port.
  • Different ports are different origins: localhost:3000 is not localhost: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 an OPTIONS preflight.
  • 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.

Take Quiz

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

  1. Create an Express server that listens on port 3000.
  2. Add a GET /products endpoint that returns JSON.
  3. Allow requests from http://localhost:5173 using CORS.
  4. Create a small frontend page that fetches and displays the products.
  5. Run the frontend through a local HTTP server rather than a file:// URL.
Take Quiz

Keep learning

Related questions

View more