Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

To wait for traffic caused by a user action in Playwright, create a page.waitForRequest() or page.waitForResponse() promise before triggering the action, then await that promise afterward. Use the request wait to inspect what the browser sent; use the response wait to inspect status, headers, or the returned data. Match the specific traffic your test cares about, then assert both the network result and the relevant page state.

Wait for the request or response caused by an action

The order matters: register the wait first, trigger the action second, and await the saved promise third. This avoids missing a fast request and prevents the test from waiting for a request that cannot start until the action runs. Playwright’s Network guide and Page API demonstrate this pattern.

import { test, expect } from '@playwright/test';

test('submits an order', async ({ page }) => {
  await page.goto('https://example.com/checkout');

  const responsePromise = page.waitForResponse(response =>
    response.url().includes('/api/orders') &&
    response.request().method() === 'POST'
  );

  await page.getByRole('button', { name: 'Submit order' }).click();

  const response = await responsePromise;
  expect(response.status()).toBe(201);
  await expect(page.getByText('Order confirmed')).toBeVisible();
});

Replace the example URL, endpoint, method, expected status, and visible confirmation with values for the application under test. The promise is created without await, so the click can run; awaiting it before the click would block the action that produces the response.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose the right Playwright wait

Need Use What it gives you
Confirm that the browser issued a matching request; inspect its URL, method, or request data page.waitForRequest() A matching Request
Check response status, headers, or response-related details page.waitForResponse() A matching Response, with access to its associated request
Observe or diagnose many requests and responses page.on('request'), page.on('response'), or page.on('requestfailed') Event notifications as traffic occurs
Know that the response body download has completed requestfinished event A later lifecycle event than receipt of response status and headers

For a request-triggered workflow, waitForRequest() answers whether the browser sent a matching request. It does not establish that the server accepted it. waitForResponse() is usually the more useful choice when the test must distinguish success from an HTTP error. A response event means status and headers have arrived; the request body download finishes later. Playwright documents the lifecycle in its Request API.

Match only the traffic the test intends to wait for

A broad match can be satisfied by unrelated background traffic, such as analytics, polling, or another call to the same host. Prefer the narrowest stable condition that describes the operation.

Exact URL

const responsePromise = page.waitForResponse(
  'https://example.com/api/orders'
);
await page.getByRole('button', { name: 'Submit order' }).click();
const response = await responsePromise;

Use an exact URL when it is stable. If query parameters change, match a stable path and inspect the parts that matter.

Regular expression

const responsePromise = page.waitForResponse(//api/orders(?:?.*)?$/);
await page.getByRole('button', { name: 'Submit order' }).click();
const response = await responsePromise;

A regular expression can handle variable query strings or a family of URLs. Keep the expression specific enough to exclude unrelated endpoints.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Predicate over the response and its request

const responsePromise = page.waitForResponse(response => {
  const request = response.request();
  return response.url().includes('/api/orders') &&
    request.method() === 'POST' &&
    response.status() === 201;
});

await page.getByRole('button', { name: 'Submit order' }).click();
const response = await responsePromise;

The predicate can combine URL, request method, and status. You can also wait for the response irrespective of status, then assert status afterward; that makes an unexpected 4xx or 5xx visible as a meaningful assertion failure rather than a wait that times out.

Playwright glob patterns

The official Network guide also shows URL matching with simplified glob patterns. In those patterns, * matches characters except /, ** can also match across slashes, ? represents a literal question mark, and brace lists such as {png,jpg} match alternatives. For example, **/*.js can match JavaScript files at the root or in nested paths. Use the syntax documented in the Network guide, and choose a pattern that distinguishes the target call from other traffic.

Wait for a request when the outgoing call is the assertion

When the test is about what the client sends—rather than what the server returns—wait for the request. This example checks that searching issues a GET request:

const requestPromise = page.waitForRequest(request =>
  request.url().includes('/api/search') &&
  request.method() === 'GET'
);

await page.getByRole('button', { name: 'Search' }).click();
const request = await requestPromise;

expect(request.method()).toBe('GET');
expect(request.url()).toContain('/api/search');

After obtaining the Request, inspect the request properties your test needs using the installed Playwright API. A request wait proves only that matching traffic was issued; add a response wait or a user-visible assertion if the test also needs to prove the operation completed.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Understand response, completion, and failure events

For a successful request, Playwright documents the sequence as request when it is issued, response when status and headers arrive, and requestfinished after the response body downloads. If transport or client-side failure prevents completion, Playwright emits requestfailed instead of requestfinished; a response may never arrive. Redirects finish the original request and issue a new request for the redirected URL.

An HTTP error status is still a response. A 404 or 503 can reach requestfinished; that is not the same as a network-level failure. If success is required, assert the response status explicitly. The distinctions and events are described in the Request API.

Use a response wait and UI assertion instead of network idle

networkidle means there have been no network connections for at least 500 ms. The Page API marks it discouraged for testing and recommends using web assertions to assess readiness. A page can keep background connections open, or become temporarily quiet before the user-facing result is ready. If the requirement is “the order request returned and the confirmation appeared,” wait for that response and assert the confirmation instead of treating general network quiet as proof.

Set practical timeouts and debug missed waits

The documented defaults are API-method-specific: waitForRequest() has a 30-second default timeout, while waitForResponse() has a 0 ms default. These values can be configured through the relevant page or context defaults or passed as method options. Defaults can be version-sensitive, so check the reference for the Playwright version installed in the project before depending on them. See the Page API.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When a wait times out, first verify the trigger, matcher, and test environment rather than simply increasing the timeout. Attach listeners temporarily to see which events actually occur:

page.on('request', request => {
  console.log('request', request.method(), request.url());
});
page.on('response', response => {
  console.log('response', response.status(), response.url());
});
page.on('requestfailed', request => {
  console.log('requestfailed', request.url(), request.failure()?.errorText);
});

Register these listeners before the action being diagnosed. Remove or gate verbose logging after investigating so routine test output stays useful. A 404 appears as a response; a network-level failure appears through requestfailed.

Common causes and fixes

  • The wait is awaited before the action. Save the promise first, perform the click or submit, then await the promise.
  • The matcher is too broad or too narrow. Inspect logged URLs and methods, then match a stable endpoint, method, and—when useful—status.
  • The wrong event is being observed. Use a response wait for status and headers, a request wait for outgoing traffic, and requestfinished when body download completion is the requirement.
  • The test assumes an HTTP error is a transport failure. A 404 or 503 is a response; await it and assert the status you expect.
  • The response never arrives. Inspect requestfailed details and verify the application’s network setup, server availability, and whether the action actually sends the call.
  • Built-in routing or interception seems to miss traffic. Playwright notes that service workers can affect built-in page.route() and browserContext.route() handling; Mock Service Worker can also take over requests. For those routing/interception scenarios, try serviceWorkers: 'block' in the browser context. This is targeted troubleshooting, not a requirement for every waitForResponse() call. See the Network guide and BrowserContext API.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If the goal is to capture a page rather than test its network behavior, ScreenshotNeo offers a one-call screenshot API. It is a different tool from Playwright’s network waits: it returns a screenshot or PDF rather than a Playwright Request or Response. See the ScreenshotNeo API documentation for parameters.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; those steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and each response identifies the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Every feature is available on every plan. Visit ScreenshotNeo or sign up free for 1,000 screenshots a month with no card.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Performance, reliability, and cost considerations

For tests, a narrowly matched response wait avoids depending on unrelated page traffic and expresses the condition under test directly. Pair it with the user-visible state that matters, because an HTTP response alone does not prove that the interface rendered the intended result. Use timeouts to bound a wait, but investigate the event log before extending them; longer waits can conceal a wrong trigger or matcher.

For debugging, event listeners are more informative than replacing a specific wait with a page-wide quiet period: they show whether the request was issued, received a response, completed its body, or failed at the network level. Keep the distinction between HTTP status errors and request failures in assertions and diagnostics so the failure points toward the right layer.

Frequently asked questions

Can I wait for a request and a response from the same click?

Yes. Create both wait promises before the click, perform the action once, and await both promises. Match each narrowly so they refer to the intended operation.

Does a successful waitForResponse() mean the page is ready?

No. It establishes that a matching response arrived, not that the application finished rendering. Assert the relevant visible state separately.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should I use waitForResponse() for every API call?

No. Use it when the response matters to the test. If the assertion concerns only the outgoing method or URL, waitForRequest() is the more direct wait.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.