# How to Mock Network Requests in Cypress: A Complete Guide to cy.intercept()

> Master mocking network requests in Cypress with cy.intercept(). Learn to stub APIs using static responses, fixtures, or dynamic replies for stable testing.

- Repository: [Cypress.io/cypress](https://github.com/cypress-io/cypress)
- Tags: how-to-guide
- Published: 2026-06-16

---

**Use `cy.intercept()` to mock network requests in Cypress by registering route matchers that return static responses, fixtures, or dynamic replies, enabling reliable API stubbing without modifying application code.**

Cypress provides a powerful network-stubbing API through the `cy.intercept()` command, implemented in the **net-stubbing** package of the cypress-io/cypress monorepo. Understanding how to mock network requests in Cypress requires familiarity with the command's architecture, which spans from driver-side validation to server-side request interception. This guide covers the complete implementation path, from matcher registration to response generation, using the actual source code structure.

## The Architecture Behind cy.intercept()

The `cy.intercept()` command operates through a coordinated system between the Cypress driver and a dedicated server-side net-stubbing layer. When you call `cy.intercept()`, the command registration occurs in [`packages/driver/src/cy/net-stubbing/add-command.ts`](https://github.com/cypress-io/cypress/blob/main/packages/driver/src/cy/net-stubbing/add-command.ts), which validates your matcher, creates a unique route ID, and emits a `route:added` net-event to the server.

### Matcher Normalization and Validation

Before a route becomes active, the driver normalizes your matcher options. In [`add-command.ts`](https://github.com/cypress-io/cypress/blob/main/add-command.ts), the helper function `annotateMatcherOptionsTypes` converts non-primitive types like **RegExp** into serializable formats that can traverse the driver-server boundary. HTTP header names are normalized to lowercase (lines 4-8) to ensure case-insensitive matching according to HTTP specifications.

### Static Response Processing

When you provide a static response (JSON objects, strings, or fixtures), the driver validates these options through `validateStaticResponse` in [`packages/driver/src/cy/net-stubbing/static-response-utils.ts`](https://github.com/cypress-io/cypress/blob/main/packages/driver/src/cy/net-stubbing/static-response-utils.ts). This function enforces mutually exclusive rules—such as preventing simultaneous `body` and `fixture` usage—while `getBackendStaticResponse` transforms your configuration into a server-compatible format with correct MIME types and throttling parameters.

### Server-Side Request Interception

The server component resides in `packages/net-stubbing/lib/server/`. When the `route:added` event arrives, the `DriverInterceptRegistrationAdapter` registers a request interceptor that monitors every HTTP request from the Application Under Test (AUT). The matching logic in [`handle-intercept-request.ts`](https://github.com/cypress-io/cypress/blob/main/handle-intercept-request.ts) determines whether to forward the request to the original destination or serve a stubbed response based on your registered routes.

## Basic Request Mocking with Static JSON

The most common approach to mock network requests in Cypress involves returning a static payload for a specific URL pattern. The driver sends this configuration through `validateStaticResponse` before the server applies it.

```javascript
// Intercept any GET request to /api/users and return a custom payload
cy.intercept('GET', '/api/users', {
  statusCode: 200,
  body: [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }],
}).as('getUsers')

// Trigger the request in your app
cy.get('button.load-users').click()

// Wait for the stubbed request and assert the UI
cy.wait('@getUsers')
cy.get('.user-list').should('contain', 'Alice')

```

## Mocking with Fixture Files

For larger response payloads, store data in the `cypress/fixtures` directory and reference them using the `fixture` key. The `STATIC_RESPONSE_KEYS` definition includes `fixture` support, and `getFixtureOpts` resolves the file path on the server side.

```javascript
// Serve a fixture located at cypress/fixtures/users.json
cy.intercept('GET', '/api/users', { fixture: 'users.json' }).as('usersFixture')
cy.wait('@usersFixture')

```

## Simulating Network Latency and Throttling

You can test how your application handles slow networks by adding artificial delays or bandwidth constraints. These values pass through `validateStaticResponse` (lines 52-58) and are enforced by the server when constructing the response stream.

```javascript
cy.intercept('GET', '/slow-endpoint', {
  delay: 2000,          // 2-second artificial latency
  throttleKbps: 50,     // limit bandwidth to 50 kbps
  body: 'slow response',
}).as('slow')

```

## Dynamic Request Handling with Route Handlers

For conditional logic or request modification, provide a function as the second argument. When [`add-command.ts`](https://github.com/cypress-io/cypress/blob/main/add-command.ts) detects a function handler (line 81), it sets `hasInterceptor = true` and registers a request interceptor that forwards the request to your callback, allowing you to inspect, modify, or abort the request programmatically.

```javascript
cy.intercept(
  { method: 'POST', url: '/api/login' },
  (req) => {
    // inspect or modify the request before it goes to the server
    if (req.body.username === 'admin') {
      req.reply({ statusCode: 403, body: 'Forbidden' })
    } else {
      req.continue()
    }
  }
).as('login')

```

## Matching Requests by Headers

To mock network requests based on specific headers, include a `headers` object in your matcher. The driver automatically lowercases header names during normalization to ensure reliable matching regardless of casing.

```javascript
cy.intercept({
  method: 'GET',
  url: '/api/data',
  headers: { 'x-custom-header': 'my-value' }
}, { body: 'ok' })

```

## Key Implementation Files

Understanding these source files helps debug complex stubbing scenarios:

- **[`packages/driver/src/cy/net-stubbing/add-command.ts`](https://github.com/cypress-io/cypress/blob/main/packages/driver/src/cy/net-stubbing/add-command.ts)** – Registers `cy.intercept`, validates matchers, creates route IDs, and emits net events to the server.
- **[`packages/driver/src/cy/net-stubbing/static-response-utils.ts`](https://github.com/cypress-io/cypress/blob/main/packages/driver/src/cy/net-stubbing/static-response-utils.ts)** – Validates static response options and converts them for backend consumption.
- **[`packages/net-stubbing/lib/server/handle-intercept-request.ts`](https://github.com/cypress-io/cypress/blob/main/packages/net-stubbing/lib/server/handle-intercept-request.ts)** – Performs server-side request matching and determines whether to stub or forward requests.
- **[`packages/net-stubbing/lib/server/intercepted-request.ts`](https://github.com/cypress-io/cypress/blob/main/packages/net-stubbing/lib/server/intercepted-request.ts)** – Represents intercepted requests for logging and UI visualization.
- **`packages/driver/src/cy/net-stubbing/events/*`** – Adapters that update the Cypress UI when requests are stubbed or pass through.

## Summary

- **Mock network requests in Cypress** using `cy.intercept()`, which replaces the deprecated `cy.route()` with a more flexible API.
- The command implementation spans [`packages/driver/src/cy/net-stubbing/add-command.ts`](https://github.com/cypress-io/cypress/blob/main/packages/driver/src/cy/net-stubbing/add-command.ts) for validation and `packages/net-stubbing/lib/server/` for execution.
- **Static responses** are validated by `validateStaticResponse` and transformed by `getBackendStaticResponse` before reaching the server.
- **Dynamic handling** uses function interceptors set via `hasInterceptor = true` in the route registration logic.
- **Header matching** is case-insensitive due to normalization in the driver layer.
- Network conditions like **delay** and **throttleKbps** are applied server-side after passing through static response validation.

## Frequently Asked Questions

### What is the difference between cy.intercept() and cy.route() in Cypress?

`cy.intercept()` is the modern replacement for `cy.route()` that uses the **net-stubbing** architecture instead of the legacy `cy.server()` mechanism. According to the cypress-io/cypress source code, `cy.intercept()` operates at the network layer rather than the XMLHttpRequest layer, allowing it to stub **fetch** requests, **WebSockets**, and other HTTP traffic that `cy.route()` cannot capture. The new API also supports route matching with **glob patterns**, **RegExp**, and **headers** without requiring `cy.server()` to be initialized first.

### How do I mock network requests with dynamic responses based on request data?

Provide a **route handler function** as the second argument to `cy.intercept()`. When the driver detects a function in [`add-command.ts`](https://github.com/cypress-io/cypress/blob/main/add-command.ts), it sets `hasInterceptor = true` and registers a request interceptor that invokes your function with a `req` object. You can inspect `req.body`, `req.headers`, or `req.url`, then call `req.reply()` to send a custom response or `req.continue()` to pass the request to the original server. This pattern is implemented in the server-side logic where `DriverInterceptRegistrationAdapter` forwards matched requests to your handler.

### Can I delay or throttle responses when mocking network requests in Cypress?

Yes, include `delay` (milliseconds) or `throttleKbps` (kilobits per second) in your static response object. These values are validated by `validateStaticResponse` in [`static-response-utils.ts`](https://github.com/cypress-io/cypress/blob/main/static-response-utils.ts) and enforced by the server when streaming the response back to the browser. This allows you to simulate slow 3G connections or server latency by adding `delay: 2000` or `throttleKbps: 50` to your `cy.intercept()` configuration.

### How does Cypress handle case-insensitive header matching?

The driver normalizes all header names to lowercase in [`add-command.ts`](https://github.com/cypress-io/cypress/blob/main/add-command.ts) (lines 4-8) before sending the matcher to the server. This ensures that `headers: { 'X-Custom-Header': 'value' }` matches requests containing `x-custom-header` or `X-CUSTOM-HEADER`, adhering to HTTP specification requirements for case-insensitive header names. When you provide a `headers` matcher object, the comparison occurs after this normalization on both the matcher and the incoming request headers.