Implementation:Microsoft Playwright Page WaitForNetwork
| Knowledge Sources | |
|---|---|
| Domains | Network_Testing, Mocking, API_Verification |
| Last Updated | 2026-02-11 00:00 GMT |
Overview
Concrete tool for waiting on and asserting against specific network requests and responses provided by the Playwright library.
Description
Playwright provides two primary methods for synchronizing with network events:
page.waitForRequest() (packages/playwright-core/src/client/page.ts:L411-419) returns a Promise that resolves with the first Request object matching the given URL pattern or predicate function. Internally, it constructs a predicate that supports string, RegExp, and function matchers, then delegates to _waitForEvent() at L441-457 which uses the Waiter class from client/waiter.ts.
page.waitForResponse() (packages/playwright-core/src/client/page.ts:L422-431) returns a Promise that resolves with the first Response object matching the given URL pattern or predicate function. It follows the same pattern as waitForRequest() but listens on the Events.Page.Response event.
Both methods use the Waiter infrastructure (Waiter.createForEvent() at L445) which provides:
- Timeout rejection:
waiter.rejectOnTimeout()at L448 throws a descriptive error if the event is not received within the configured timeout. - Crash guard:
waiter.rejectOnEvent(this, Events.Page.Crash)at L449-450 rejects the Promise if the page crashes while waiting. - Close guard:
waiter.rejectOnEvent(this, Events.Page.Close)at L451-452 rejects if the page closes while waiting.
URL matching uses urlMatches() from utils/isomorphic/urlMatch, which supports matching against the page's baseURL configuration for relative URL patterns.
Additionally, page.requests() (packages/playwright-core/src/client/page.ts:L792-795) returns a snapshot array of all tracked requests, enabling post-hoc inspection of network traffic without event-based waiting.
Usage
Use these methods when:
- You need to wait for an API call triggered by a user action before asserting on the response.
- You want to verify that a form submission sends the correct POST body.
- You need to assert that authentication headers are included in API requests.
- You want to capture a response and inspect its status code, headers, or body.
- You need to synchronize test execution with asynchronous network events to avoid flaky tests.
- You want to inspect all requests made during a page load via
page.requests().
Code Reference
Source Location
- Repository: playwright
- waitForRequest:
packages/playwright-core/src/client/page.ts:L411-419 - waitForResponse:
packages/playwright-core/src/client/page.ts:L422-431 - _waitForEvent:
packages/playwright-core/src/client/page.ts:L441-457 - page.requests:
packages/playwright-core/src/client/page.ts:L792-795
Signature
// Wait for a matching request
page.waitForRequest(
urlOrPredicate: string | RegExp | ((request: Request) => boolean | Promise<boolean>),
options?: { timeout?: number }
): Promise<Request>;
// Wait for a matching response
page.waitForResponse(
urlOrPredicate: string | RegExp | ((response: Response) => boolean | Promise<boolean>),
options?: { timeout?: number }
): Promise<Response>;
// Get snapshot of all tracked requests
page.requests(): Promise<Request[]>;
Import
// Playwright Test (recommended)
import { test, expect } from '@playwright/test';
// Library mode
import { chromium, Request, Response } from 'playwright';
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| urlOrPredicate (waitForRequest) | RegExp | ((request: Request) => boolean | Promise<boolean>) | Yes | URL pattern or predicate function to match against emitted requests. Strings are matched as glob patterns with baseURL support. RegExp is tested against the full URL. Functions receive the Request object and return a boolean.
|
| urlOrPredicate (waitForResponse) | RegExp | ((response: Response) => boolean | Promise<boolean>) | Yes | URL pattern or predicate function to match against emitted responses. Same matching semantics as waitForRequest.
|
| options.timeout | number |
No | Maximum time to wait in milliseconds. Defaults to the page's configured timeout. Set to 0 to disable timeout.
|
Outputs
| Name | Type | Description |
|---|---|---|
| waitForRequest return | Promise<Request> |
Resolves with the first Request object matching the predicate. The Request provides url(), method(), headers(), postData(), postDataJSON(), resourceType(), and other introspection methods.
|
| waitForResponse return | Promise<Response> |
Resolves with the first Response object matching the predicate. The Response provides url(), status(), ok(), headers(), body(), text(), json(), and other methods.
|
| page.requests return | Promise<Request[]> |
Returns a snapshot array of all tracked Request objects at the time of the call. |
Usage Examples
Basic Example: Wait for API Response
import { test, expect } from '@playwright/test';
test('wait for API response after click', async ({ page }) => {
await page.goto('https://example.com');
// Use Promise.all to register wait BEFORE triggering action
const [response] = await Promise.all([
page.waitForResponse('**/api/users'),
page.click('#load-users'),
]);
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.users).toHaveLength(10);
});
Verify Request Payload
import { test, expect } from '@playwright/test';
test('verify form submission sends correct data', async ({ page }) => {
await page.goto('https://example.com/register');
// Wait for the POST request triggered by form submission
const [request] = await Promise.all([
page.waitForRequest(request =>
request.url().includes('/api/register') &&
request.method() === 'POST'
),
page.click('#submit-registration'),
]);
// Assert on the request body
const postData = request.postDataJSON();
expect(postData).toEqual({
name: 'Alice',
email: 'alice@example.com',
role: 'user',
});
});
Verify Request Headers
import { test, expect } from '@playwright/test';
test('verify auth header is present', async ({ page }) => {
await page.goto('https://example.com/login');
// Perform login flow
await page.fill('#email', 'user@example.com');
await page.fill('#password', 'password123');
await page.click('#login');
// Wait for an authenticated API call
const request = await page.waitForRequest('**/api/profile');
const headers = await request.allHeaders();
expect(headers['authorization']).toMatch(/^Bearer .+/);
});
Use Regex for URL Matching
import { test, expect } from '@playwright/test';
test('wait for response matching regex', async ({ page }) => {
await page.goto('https://example.com/products');
// Match any product detail API call
const [response] = await Promise.all([
page.waitForResponse(/\/api\/products\/\d+/),
page.click('.product-card:first-child'),
]);
expect(response.ok()).toBeTruthy();
const product = await response.json();
expect(product).toHaveProperty('id');
expect(product).toHaveProperty('name');
expect(product).toHaveProperty('price');
});
import { test, expect } from '@playwright/test';
test('inspect all API requests after page load', async ({ page }) => {
await page.goto('https://example.com/dashboard');
await page.waitForLoadState('networkidle');
// Get snapshot of all requests
const allRequests = await page.requests();
const apiRequests = allRequests.filter(r => r.url().includes('/api/'));
// Verify expected API calls were made
const urls = apiRequests.map(r => r.url());
expect(urls).toContain(expect.stringContaining('/api/user/profile'));
expect(urls).toContain(expect.stringContaining('/api/dashboard/stats'));
// Verify no unexpected calls to external services
const externalRequests = allRequests.filter(
r => !r.url().includes('example.com')
);
expect(externalRequests).toHaveLength(0);
});
Custom Predicate with Async Logic
import { test, expect } from '@playwright/test';
test('wait for response with specific body content', async ({ page }) => {
await page.goto('https://example.com');
// Use async predicate to inspect response body
const response = await page.waitForResponse(async response => {
if (!response.url().includes('/api/search'))
return false;
const body = await response.json();
return body.results.length > 0;
});
const data = await response.json();
expect(data.results.length).toBeGreaterThan(0);
});