# How the Cypress HTTP Proxy Intercepts and Modifies Browser Traffic

> Discover how the Cypress HTTP proxy intercepts and modifies browser traffic. Learn about decryption, inspection, and rewriting requests and responses for efficient testing.

- Repository: [Cypress.io/cypress](https://github.com/cypress-io/cypress)
- Tags: internals
- Published: 2026-07-12

---

**Cypress routes all browser traffic through a built-in HTTPS proxy server that decrypts, inspects, and optionally rewrites requests and responses using adapter-based interception logic before re-encrypting data for the destination.**

Cypress is an end-to-end testing framework that launches browsers pre-configured to route through a local proxy. According to the cypress-io/cypress source code, this HTTP proxy architecture enables the framework to intercept, stub, and modify any network request made by the Application Under Test (AUT), providing complete control over the browser's network layer.

## Core Architecture Components

### The HTTPS-Proxy Server

At the foundation lies the HTTPS-Proxy server implemented in [`packages/https-proxy/lib/proxy.ts`](https://github.com/cypress-io/cypress/blob/main/packages/https-proxy/lib/proxy.ts). This module starts an HTTP/HTTPS server that acts as a transparent intermediary, forwarding traffic to real destinations while exposing hooks for request and response mutation. The server generates self-signed certificates at runtime to handle TLS decryption and re-encryption, enabling inspection of encrypted HTTPS traffic.

### Proxy Adapters

The interception logic is modularized through adapters located in `packages/proxy/lib/adapters/`:

- **ProxyRequestInterceptionAdapter** ([`proxy-request-interception.ts`](https://github.com/cypress-io/cypress/blob/main/proxy-request-interception.ts)): Matches incoming requests against `cy.intercept()` patterns and decides whether to stub, modify, or forward the request.
- **ProxyResponseInterceptionAdapter** ([`proxy-response-interception.ts`](https://github.com/cypress-io/cypress/blob/main/proxy-response-interception.ts)): Handles response modification, stubbing, and header tweaks before the browser receives the data.
- **ProxyNetworkCaptureAdapter** ([`proxy-network-capture.ts`](https://github.com/cypress-io/cypress/blob/main/proxy-network-capture.ts)): Streams request and response bodies for debugging and logging purposes, avoiding memory issues with large payloads.
- **ProxyCookieStateAdapter** ([`proxy-cookie-state.ts`](https://github.com/cypress-io/cypress/blob/main/proxy-cookie-state.ts)): Normalizes cookie handling and `Set-Cookie` headers across different origins to prevent domain-validation failures.

### Network Interception Core

The [`packages/server/lib/network-runtime.ts`](https://github.com/cypress-io/cypress/blob/main/packages/server/lib/network-runtime.ts) file provides the generic `HttpIntercept` API that adapters consume. This abstraction layer manages the registration of intercept patterns, stub callbacks, and user-defined handlers, working across different underlying transport mechanisms.

### Browser Transport Integration

Cypress supports multiple browser automation protocols:

- **CDP Fetch Transport** ([`packages/server/lib/browsers/cdp-protocol/cdp-fetch-transport.ts`](https://github.com/cypress-io/cypress/blob/main/packages/server/lib/browsers/cdp-protocol/cdp-fetch-transport.ts)): For Chromium-based browsers (Chrome, Edge), this enables the Chrome DevTools Protocol Fetch domain to register intercepts directly with the browser.
- **BiDi Automation** ([`packages/server/lib/browsers/bidi_automation.ts`](https://github.com/cypress-io/cypress/blob/main/packages/server/lib/browsers/bidi_automation.ts)): For Firefox and other BiDi-compatible browsers, providing equivalent interception capabilities via the WebDriver BiDi protocol.
- **Classic Proxy**: For browsers where CDP/BiDi are unavailable, the system falls back to the traditional HTTPS proxy mechanism.

## The Interception Lifecycle

When a test invokes `cy.intercept()`, the following sequence occurs:

1. **Create an `HttpIntercept` object** that stores the matching pattern, stub callbacks, and user handler functions.
2. **Register the intercept** with the appropriate browser transport (CDP Fetch, BiDi, or classic proxy).
3. **Proxy receives the raw request** through the HTTPS-Proxy server, decrypting TLS if necessary.
4. **Proxy adapters execute**:
   - The request adapter checks patterns and either mutates the URL/headers, aborts the request, or returns a stubbed response.
   - If a stub exists, the response adapter builds the stubbed response and returns it immediately without contacting the remote server.
5. **Forward or modify**:
   - If no stub matches, the request forwards to the destination server.
   - The response adapter intercepts the real response and can modify headers or body before passing it to the browser.
6. **Log all events** to [`packages/driver/src/cypress/proxy-logging.ts`](https://github.com/cypress-io/cypress/blob/main/packages/driver/src/cypress/proxy-logging.ts) for display in the Cypress Command Log UI.

## Handling Encrypted and Cross-Origin Traffic

### TLS Decryption and Certificate Injection

To inspect HTTPS traffic, the proxy generates self-signed certificates at runtime. The browser launches with the `--ignore-certificate-errors` flag (or equivalent configuration) to trust these certificates, allowing the proxy to decrypt outgoing requests and re-encrypt responses without triggering security warnings.

### Cookie State Normalization

Cross-origin requests often encounter cookie validation issues. The **ProxyCookieStateAdapter** ([`packages/proxy/lib/adapters/proxy-cookie-state.ts`](https://github.com/cypress-io/cypress/blob/main/packages/proxy/lib/adapters/proxy-cookie-state.ts)) normalizes `Set-Cookie` headers and cookie domains, particularly for `localhost` or IP-based origins, ensuring that authentication and session state work correctly across different domains during testing.

## Practical Implementation with cy.intercept()

The following examples demonstrate how tests leverage the proxy architecture:

```javascript
// 1. Simple request stub – returns a static JSON payload
cy.intercept('GET', '/api/users', { fixture: 'users.json' })

// 2. Dynamic response modification – alter headers before the browser receives them
cy.intercept('GET', '/api/config', (req) => {
  req.reply((res) => {
    res.headers['x-feature-flag'] = 'true'
    res.send()
  })
})

// 3. Abort a request – simulate network failures
cy.intercept('POST', '/api/upload', { forceNetworkError: true })

// 4. Capture request body for later assertions
let capturedBody
cy.intercept('POST', '/api/login', (req) => {
  req.continue((res) => {
    capturedBody = req.body
    res.send()
  })
}).as('login')

// later in the test
cy.wait('@login')
expect(capturedBody).to.have.property('username', 'bob')

```

These commands delegate to the **ProxyRequestInterceptionAdapter** and **ProxyResponseInterceptionAdapter** to execute the actual network manipulation.

## Performance and Isolation Guarantees

The proxy implementation includes several optimizations:

- **Streaming bodies**: The **ProxyNetworkCaptureAdapter** streams request and response bodies rather than buffering them entirely, conserving memory when handling large file uploads or downloads.
- **Per-spec isolation**: The proxy initializes fresh for each spec file, ensuring that stubs and network state from one test cannot leak into subsequent tests.
- **Abort handling**: Requests can be aborted at the adapter level before establishing costly connections to external servers.

## Summary

- The Cypress HTTP proxy in [`packages/https-proxy/lib/proxy.ts`](https://github.com/cypress-io/cypress/blob/main/packages/https-proxy/lib/proxy.ts) acts as a transparent intermediary between the browser and the network.
- **Proxy adapters** ([`proxy-request-interception.ts`](https://github.com/cypress-io/cypress/blob/main/proxy-request-interception.ts), [`proxy-response-interception.ts`](https://github.com/cypress-io/cypress/blob/main/proxy-response-interception.ts)) provide modular logic for matching, stubbing, and modifying traffic.
- The system supports **HTTPS interception** through runtime certificate generation and browser flags that disable certificate validation.
- **CDP Fetch** and **BiDi** transports enable native browser interception for Chromium and Firefox, respectively, with fallback to classic proxy mode.
- All network activity is logged via [`proxy-logging.ts`](https://github.com/cypress-io/cypress/blob/main/proxy-logging.ts) for UI visualization and debugging.

## Frequently Asked Questions

### How does Cypress decrypt HTTPS traffic without triggering certificate errors?

Cypress generates self-signed certificates at runtime and launches the browser with the `--ignore-certificate-errors` flag. This allows the HTTPS proxy in [`packages/https-proxy/lib/proxy.ts`](https://github.com/cypress-io/cypress/blob/main/packages/https-proxy/lib/proxy.ts) to terminate TLS, inspect the plaintext, and re-encrypt the connection to the destination without browser security warnings.

### What is the difference between CDP Fetch and BiDi transports?

The **CDP Fetch Transport** ([`cdp-fetch-transport.ts`](https://github.com/cypress-io/cypress/blob/main/cdp-fetch-transport.ts)) uses the Chrome DevTools Protocol Fetch domain to intercept requests in Chromium browsers, while **BiDi Automation** ([`bidi_automation.ts`](https://github.com/cypress-io/cypress/blob/main/bidi_automation.ts)) implements the WebDriver BiDi protocol for Firefox and other compatible browsers. Both provide native interception hooks, but CDP offers deeper integration with Chrome-specific features.

### Can the proxy modify responses after they leave the server?

Yes. The **ProxyResponseInterceptionAdapter** ([`packages/proxy/lib/adapters/proxy-response-interception.ts`](https://github.com/cypress-io/cypress/blob/main/packages/proxy/lib/adapters/proxy-response-interception.ts)) can intercept real server responses, modify headers or body content, and then forward the modified response to the browser. This occurs when using `req.reply()` or `req.continue()` with a callback that mutates the response object.

### How does Cypress prevent network stubs from leaking between tests?

The proxy initializes fresh for each spec file, creating isolated instances of the `HttpIntercept` registry and adapter states. This per-spec isolation ensures that matchers and stubs defined in one test file do not affect network behavior in subsequent tests.