In Cypress 16, where does the application's traffic actually go in Chrome versus Firefox?
answer
- Two answers, not one
- It depends on the browser family
- Who opens the connection to your server
- Chromium family versus Firefox and WebKit
- One deprecated flag forces the old path
basics
~20 sIn Chrome, Chromium and Edge the browser connects to your server directly and Cypress intercepts inside the browser. Firefox, WebKit and Electron still route every request through Cypress's HTTP/1.1 proxy, and forceHttp1 puts every browser back on that path.
solid answer
~40 sAs of Cypress 16 the answer depends on the browser. In **Chrome, Chromium and Edge** Cypress uses the *native browser network*: the browser opens the connection to your statements API itself and negotiates whatever the server supports — HTTP/1.1, HTTP/2 or HTTP/3 — while Cypress pauses each request inside the browser. Your origin's real certificate is validated, and every change an intercept makes shows up in the browser's own network panel. **Firefox, WebKit and Electron** stay on the *legacy network path*: Cypress proxies the traffic, terminates TLS with a certificate it mints itself, and speaks HTTP/1.1 upstream. `forceHttp1: true` puts every browser back on the legacy path, but it was introduced and deprecated in the same release, so treat it as a migration aid rather than a setting.
go deeper
Know that Cypress can sit between the browser and the server, and that in Cypress 16 Chrome no longer works that way. Be able to name the default browser behaviour without reciting the whole table.
Explain the mechanics: who opens the connection, which protocol gets negotiated, and why the legacy path pinned everything to HTTP/1.1. Be ready to say what Cypress can and cannot observe once it is not the connection.
Show you have run a cross-browser suite through this. Expect the interviewer to ask what breaks in Firefox but not Chrome, and how you would find that out from a failure rather than by guessing.
Own the trade: the native path tests the protocol your users get, at the cost of a browser-dependent observability surface. Be ready to argue whether a suite should run on both paths at all, or standardise on one.
## Where the bytes actually go Cypress runs your spec inside the browser, but until version 16 it also sat **in the middle of every network exchange**. The browser was pointed at a Cypress-managed HTTP proxy, Cypress opened its own connection to your server, read the response, and handed a copy to the browser. That is the **legacy network path**, and because Cypress spoke HTTP/1.1 upstream, every request your bank-statement app made was downgraded to HTTP/1.1 no matter what your server supported. As of **Cypress 16**, Chrome, Chromium and Edge use the **native browser network** instead. The browser opens the connection to `/api/statements` itself and negotiates HTTP/1.1, HTTP/2 or HTTP/3 exactly as it does for a real customer. Cypress pauses each request and response *inside* the browser (implemented over the Chrome DevTools Protocol's `Fetch` domain) rather than being the connection. ## Which browser takes which path | Browser | `forceHttp1: false` (default) | `forceHttp1: true` | | --- | --- | --- | | Chrome, Chromium, Edge | Native browser network | Legacy network path | | Firefox, WebKit | Legacy network path | Legacy network path | | Electron | Legacy network path | Legacy network path | Firefox and WebKit have no native path implemented yet. Electron is Chromium-based and could take it, but it is deprecated as a test browser, so it was not carried over. **A cross-browser run therefore sees both behaviours inside a single suite**, which is the detail most people miss. ## What the change buys a suite - **Your production protocol is the one under test.** HTTP/2 and HTTP/3 are no longer downgraded, so a statement list that fires forty thumbnail requests multiplexes over one connection instead of queueing behind the browser's six-connections-per-origin ceiling. - **Your certificate is the one the browser validates.** Cypress no longer terminates TLS for the app under test. On the legacy path it acts as its own certificate authority and mints a certificate for your origin, which Chrome reports as issued by an unknown authority. - **What you stub is what the browser sees.** Modified request headers and bodies, stubbed responses and overridden status codes all appear in the browser's own network panel, because the browser is the one making the request. - **The "not secure" badge still appears**, and it is not about your app: the Cypress app itself is served over `http` on `localhost`, and the indicator describes that shell. ## What did *not* change `cy.intercept()` has the same API on both paths, and adopting the native browser network needs no configuration change at all. Cookie handling, `blockHosts`, obstructive-code rewriting and intercept matching run through the same request middleware on **both** transports, so a rule that blocks a telemetry host behaves identically in Chrome and in Firefox. What differs is a short list of **transport metadata Cypress can no longer observe**, because it is no longer the thing making the connection: 1. `req.httpVersion` is `undefined` and `res.httpVersion` is `null` in Chrome, Chromium and Edge; the legacy path still reports `'1.1'`. 2. `content-encoding`, `content-length` and `transfer-encoding` are absent from an intercepted response's headers — the body you get has already been decoded. 3. A revalidated resource reports `200` rather than the `304` your server actually sent, because the browser's cache merges the conditional response before Cypress sees it. 4. A response the browser's own network stack rejects never reaches Cypress at all; the request is still recorded, but `interception.response` is `undefined`. 5. Anything Cypress answers without a network exchange — a stubbed body, an `http` document loaded by `cy.visit()` — is not stored in the browser's HTTP cache, so a second navigation issues the request again. ## The escape hatch, and why it is already deprecated `forceHttp1: true` routes **every** browser back onto the legacy path, reproducing the pre-16 behaviour everywhere. It is worth knowing three things about it: - It was **introduced and deprecated in the same release**. It exists to buy a suite migration time or to work around a bug you have filed, and it will be removed. - Changing it **restarts the Cypress server**, and it cannot be set per test or per suite. - Setting it purely to avoid updating a handful of assertions is the wrong trade: it puts Chrome back on a transport your users never use, which is the gap the change closed. If a suite only passes with `forceHttp1: true` and the difference is not one of the documented behaviours above, that is a bug worth reporting rather than a setting worth keeping.
- Why does Electron stay on the legacy network path even though it is Chromium-based?Electron could technically take the native browser network path, but it is deprecated as a Cypress test browser, so the work was not carried onto it. That is also why a `Cypress.isBrowser({ family: 'chromium' })` filter is the wrong gate for path-dependent behaviour — it matches Electron, which is on the other path.
- Does moving to the native browser network require any change to a suite's configuration?No. It is the default in Chrome, Chromium and Edge as of Cypress 16, and `cy.intercept()` keeps the same API. Only tests that assert on transport metadata Cypress can no longer observe — `req.httpVersion`, compression headers, or a `304` status — need editing. Everything else, including blocking and rewriting, is unchanged.
The legacy path is an interpreter standing between two speakers: everything is heard, but it all comes out in the interpreter's dialect. The native browser network lets the two speak directly while the interpreter listens on the line.
saying these in an interview costs you the question
- Says Cypress always proxies every request
- Claims the change applies to all browsers equally
- Thinks forceHttp1 only affects Chrome
- Assumes cy.intercept needs rewriting for the new path
- Believes Cypress still issues a certificate for your origin in Chrome