Playwright Auto-wait and Timeout
This chapter provides an in-depth introduction to Playwright's auto-wait mechanism, as well as complete knowledge of manual waiting and timeout configuration.
Why do we need auto-wait
Modern web applications rely heavily on asynchronous rendering, and page content does not load completely in an instant.
In traditional testing frameworks, developers have to writesleeporwaitForThese wait operations are not flexible enough—they either wait too long and slow down the tests, or wait too little and cause flaky tests.
Playwright builds waiting logic into every Locator and Action, fundamentally solving this problem.
Three-layer auto-wait system
Layer 1: Locator Auto-wait
When you create a Locator, Playwright does not search for the element immediately; instead, it starts searching and automatically waits when you perform an action or assertion.
Example
const btn = page.getByRole('button', { name: 'Delayed button' });
// Automatically wait for the button to appear when clicking (waits up to the action timeout)
await btn.click();
Layer 2: Action Operability Check
Before performing an action (click, fill, etc.), Playwright ensures that the element is: Attached → Visible → Stable → Receives Events → Enabled.
Layer 3: Automatic Retry of Assertions
After an assertion fails, it does not immediately report an error; instead, it keeps retrying until the condition is met or a timeout occurs.
Example
await expect(page.getByText('Data loading complete')).toBeVisible();
Manual Waiting Methods
In special scenarios where auto-wait is insufficient, Playwright also provides manual waiting methods.
page.waitForTimeout(ms) — Fixed Wait
Example
await page.waitForTimeout(2000);
Try to avoid using it.
waitForTimeoutFixed waiting is extremely unstable under device performance differences. Prefer the followingwaitForURL、waitForResponseevent-driven waits.
page.waitForURL() — Wait for URL Change
Example
await page.waitForURL('https://www.example.com/dashboard');
// Wait for URL to contain a specific pattern
await page.waitForURL(/dashboard/);
page.waitForLoadState() — Wait for Load State
Example
await page.waitForLoadState('load');
// Wait for DOMContentLoaded
await page.waitForLoadState('domcontentloaded');
// Wait for network idle
await page.waitForLoadState('networkidle');
page.waitForResponse() — Wait for Network Response
Example
const response = await page.waitForResponse(
resp => resp.url().includes('/api/data') && resp.status() === 200
);
// Get response data
const data = await response.json();
page.waitForEvent() — Wait for Event
Example
const dialogPromise = page.waitForEvent('dialog');
await page.getByRole('button', { name: 'Delete' }).click();
const dialog = await dialogPromise;
await dialog.accept();
// Wait for a new page to open
const pagePromise = page.context().waitForEvent('page');
await page.getByRole('link', { name: 'Open in new window' }).click();
const newPage = await pagePromise;
Timeout Configuration Explained
Playwright has 4 types of timeouts, each acting on a different layer:
| Timeout Type | Configuration File Location | Default Value | Applies To |
|---|---|---|---|
| Test timeout | timeout | 30000ms | Entire test case |
| Expect timeout | expect.timeout | 5000ms | Assertion retry |
| Action timeout | use.actionTimeout | None (unlimited) | Element operations (click, fill, etc.) |
| Navigation timeout | use.navigationTimeout | None (unlimited) | Page navigation (goto, goBack, etc.) |
Global Configuration
Example
import { defineConfig } from '@playwright/test';
export default defineConfig({
// Total timeout for each test (milliseconds)
timeout: 60000,
// Timeout for assertion automatic retry
expect: {
timeout: 10000,
},
use: {
// Timeout for each action (click, fill, etc.)
actionTimeout: 15000,
// Timeout for each navigation
navigationTimeout: 30000,
},
});
Per-call Settings (Higher Priority than Global Configuration)
Example
test.setTimeout(120000);
// Set timeout for a single action
await page.getByRole('button').click({ timeout: 30000 });
// Set timeout for a single navigation
await page.goto('https://www.example.com/', { timeout: 60000 });
Timeout Priority
Per-call settings > Global config file settings > Default values.
Suggestions for Setting Timeouts Reasonably
| Scenario | Recommended Timeout | Description |
|---|---|---|
| Local Development | Default values | Local services respond quickly; default values are sufficient. |
| CI Environment | 2–3 times the default value | CI machine performance fluctuates significantly. |
| Slow Pages | actionTimeout: 15000 | Large forms, complex pages |
| Third-party service calls | test.setTimeout(120000) | External API responses are slow. |