Playwright Network Interception and Mock
This chapter introduces how to use Playwright to intercept, modify, and mock network requests, enabling independent testing that does not rely on backend APIs.
What is Network Interception
Network interception allows you to intervene when the browser makes HTTP requests.
You canblock requests, modify responses, and return mock data, making tests independent of external APIs or network status.
page.route() Intercept Requests
page.route(url, handler)Used to intercept all network requests matching a specified URL pattern.
Basic Interception
Example
// Intercept all PNG and JPEG images
await page.route('**/*.{png,jpg,jpeg}', route => route.abort());
// Navigate to the page (images will not be loaded)
await page.goto('https://www.example.com/');
// The page may load faster because no images are downloaded
});
URL Matching PatternsSupports the following formats:
| Pattern | Example | Description |
|---|---|---|
| Full URL | 'https://api.example.com/users' | Exact match |
| Glob wildcard | '**/api/**' | **Matches any path |
| Regular expression | /\/api\/v\d\/users/ | Flexible matching |
| Function | url => url.includes('/api/') | Programmatic logic matching |
route.abort() Abort Requests
Example
// Block analytics scripts such as Google Analytics
await page.route('**/*analytics*', route => route.abort());
// Block CSS files
await page.route('**/*.css', route => route.abort());
await page.goto('https://www.example.com/');
// The page loads without styles, but functional tests are unaffected
});
route.fulfill() Mock Responses
route.fulfill()It is the most powerful mock method, capable of returning any custom response.
Mock JSON Data
Example
// Intercept the user list API and return mock data
await page.route('**/api/users', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
json: [
{ id: 1, name: 'example_user', email: '[email protected]' },
{ id: 2, name: 'test_user', email: '[email protected]' },
],
});
});
await page.goto('https://www.example.com/users');
// The page will display mock data instead of real API data
});
Mock Error Responses
Example
// Simulate a 500 server error
await page.route('**/api/data', async route => {
await route.fulfill({
status: 500,
contentType: 'application/json',
json: { error: 'Internal server error' },
});
});
await page.goto('https://www.example.com/dashboard');
// Verify the error message is displayed correctly
await expect(page.getByText('Internal server error')).toBeVisible();
});
route.continue() Modify and Continue
Rather than directly returning mock data, it modifies the real request or response and then continues sending it to the server.
Example
await page.route('**/api/**', async (route, request) => {
// Modify request headers and add custom headers
const headers = {
...request.headers(),
'X-Custom-Header': 'EXAMPLE-TEST',
};
await route.continue({ headers });
});
await page.goto('https://www.example.com/');
});
test('Modify POST data', async ({ page }) => {
await page.route('**/api/login', async (route, request) => {
// Override the body of POST requests
const postData = JSON.parse(request.postData() || '{}');
postData.mode = 'test'; // Add a test marker
await route.continue({
postData: JSON.stringify(postData),
});
});
});
route.fetch() Real Requests
In the mock handler function, you can useroute.fetch()to actually send the request, get the real response, and then modify it.
Example
await page.route('**/api/products', async route => {
// First get the real response
const response = await route.fetch();
const body = await response.json();
// Modify the response data
body.items[0].name = 'EXAMPLE modified product name';
// Return the modified data
await route.fulfill({
status: response.status(),
contentType: 'application/json',
json: body,
});
});
});
Context-level Interception vs Page-level Interception
| Method | Scope | Use Cases |
|---|---|---|
page.route() | Current page only | Network mock for a single page |
context.route() | All pages in this context | Mock rules shared by multiple pages |
Example
// Intercept in the entire context; applies to all pages
await context.route('**/*.css', route => route.abort());
});
test('Test 1', async ({ page }) => { /* No CSS */ });
test('Test 2', async ({ page }) => { /* No CSS */ });
HAR File Recording and Playback
A HAR (HTTP Archive) file records all network requests of a page and can then replay or mock them.
Example
// Load network records from the HAR file and replay
await page.routeFromHAR('tests/hars/api-responses.har');
await page.goto('https://www.example.com/');
// All matching requests will get responses from the HAR file
});
# 录制 HAR 文件 npx playwright open --save-har=tests/hars/api-responses.har https://www.example.com/
Other ExtensionsHAR files are suitable for mocking large or complex API responses. Record once, and subsequent tests replay from the HAR without depending on a real server.