Managing Network Requests in Cypress: Choosing Between Intercept and Route
Learn when to use cy.intercept() over the deprecated cy.route() to handle asynchronous network requests, stub API errors, and avoid the pitfalls of contract drift in Cypress.
30 Sept 2025, 00:59 UTC

The Problem: Unreliable Network Dependencies
Testing frontend applications often leads to a conflict: relying on a live backend makes tests slow and flaky, but mocking everything can hide critical integration bugs. When you need to verify that a specific API call was made or simulate a server failure, you must decide how to handle the network layer.
The primary goal is to decouple the UI tests from the backend's current state while maintaining a high degree of confidence that the application handles various HTTP responses correctly.
Comparing Network Handling Options
For several versions, Cypress has transitioned from cy.route() to cy.intercept(). While cy.route() is still present in some legacy codebases, it is deprecated and limited to XMLHttpRequest (XHR).
| Feature | cy.route() (Legacy) | cy.intercept() (Current) |
|---|---|---|
| Protocol Support | XHR only | Fetch and XHR |
| HTTP Methods | Limited (mostly GET/POST) | All (PUT, DELETE, PATCH, etc.) |
| Request Modification | No | Yes (via callback functions) |
| Network Layer | Application layer | Network proxy layer |
| Status | Deprecated | Standard |
Trade-offs in Network Orchestration
Spying vs. Stubbing
You have two primary modes of operation when using cy.intercept():
- Spying: The request is allowed to hit the real server, but Cypress records the interaction. This is ideal for integration tests where you want to verify the actual data returned by the API.
- Stubbing: Cypress catches the request and returns a predefined response (a fixture or a static object) without ever hitting the server. This is essential for testing edge cases, such as 500 Internal Server Errors or 403 Forbidden responses, which are difficult to trigger on a live backend.
The Risk of Contract Drift
Extensive stubbing creates a "green test" trap. If the backend API changes its response schema but the Cypress stub remains the same, your tests will pass while the production application crashes. To mitigate this, combine stubbed unit-like tests with a small set of end-to-end tests that use spying to validate the real API contract.
Implementation: Stubbing an API Error
To implement a network intercept, you must define the intercept before the action that triggers the request. If the intercept is defined after the button click, the request will have already left the browser before Cypress can catch it.
The following example demonstrates how to simulate a server failure (500 error) to verify that the UI displays an appropriate error message. This assumes Cypress v6.0+.
// Run this in your Cypress test file (.cy.js)
it('should show an error message when the API fails', () => {
// 1. Define the intercept before the trigger
// Syntax: cy.intercept(method, url, staticResponse)
cy.intercept('GET', '/api/users*', {
statusCode: 500,
body: { error: 'Internal Server Error' }
}).as('getUsersError');
// 2. Trigger the action that causes the network request
cy.visit('/users');
cy.get('[data-cy="load-users-btn"]').click();
// 3. Wait for the intercepted request to complete
// This ensures the async request finishes before assertions run
cy.wait('@getUsersError');
// 4. Assert the UI handles the 500 error correctly
cy.get('.error-banner').should('be.visible').and('contain', 'Something went wrong');
});
Verification and Diagnostics
To verify the intercept is working as intended:
- Open the Cypress Test Runner.
- Click on the
GET /api/usersentry in the command log. - Check the console output. If the request was stubbed, the response will be marked as
(stubbed). If it was a spy, you will see the actual response from the server.
Rollback and State
Because cy.intercept() operates at the proxy level for the duration of the test, it does not permanently change the server state. However, if you use a global intercept in a beforeEach hook, it will persist across all tests in that file. To reset network behavior, simply avoid defining global intercepts or use specific aliases to differentiate between test cases.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.