The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
In Playwright, usually await the action that starts navigation, then assert the destination or the visible page state your test needs. Playwright waits for navigation triggered by actions automatically; add an explicit load-state wait only when that milestone matters. For most readiness checks, a retrying locator assertion is more reliable than a fixed sleep or waiting for all network activity to stop.
Choose the condition that proves the page is ready
“Page loaded” can mean several different things: a response arrived, the document was parsed, the browser fired its load event, or the interface became usable. Pick the condition that matches what the test will do next. A page can fire load before its app has rendered the data your test needs, and a page can remain busy with background requests after the relevant interface is ready.
| Wait condition | What it means | When it fits |
|---|---|---|
commit |
The response was received and document loading started. | When the test needs to know navigation began and does not require parsed markup or rendered content. |
domcontentloaded |
The document’s DOM was parsed; dependent resources such as images may still be loading. | When the test can proceed from the parsed page structure. |
load |
The browser fired the document’s load event. |
When resources whose loading contributes to that event are needed before proceeding. |
networkidle |
No network connections for at least 500 ms. | Rarely useful as a test-readiness condition; Playwright discourages using it for testing. |
These milestones are documented in the Playwright Page API and navigation guide. “Network idle” does not mean the page is correct or usable. Analytics, polling, streaming, and other background activity can keep connections open; conversely, a quiet network does not prove a particular element has appeared.
Wait for navigation and assert the destination
When a click triggers navigation, await the click, then check the URL and a meaningful element. This keeps the test tied to user-visible outcomes instead of an estimated delay:
#1 Best Overall
import { test, expect } from '@playwright/test';
test('opens reports', async ({ page }) => {
await page.goto('https://example.com');
await page.getByRole('link', { name: 'Reports' }).click();
await expect(page).toHaveURL(/reports/);
await expect(page.getByRole('heading', { name: 'Reports' })).toBeVisible();
});
Playwright’s navigation-triggering actions wait for navigation as appropriate, and actions auto-wait for their actionability conditions. An explicit waitForLoadState() is often unnecessary; the Page API says, “Most of the time, this method is not needed because Playwright auto-waits before every action.” See the Page API and navigation guide.
For a single-page application that changes route without a document navigation, the URL and destination UI assertions are still useful: they wait for the expected result without incorrectly requiring a browser load event.
Use an explicit load-state checkpoint when it matters
For direct navigation, specify the milestone in page.goto() when you have a reason to stop at that point. The default navigation condition is load; choosing domcontentloaded can let a test proceed earlier if it only needs the parsed document.
Recommended Free Tools
Rank #2
import { test, expect } from '@playwright/test';
test('checks a page after document parsing', async ({ page }) => {
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.waitForLoadState('load');
await expect(page.getByRole('main')).toBeVisible();
});
This example deliberately waits for both milestones. In real tests, remove the second wait if the test does not need the load event; do not add it by habit. You can also use waitUntil: 'commit' or waitUntil: 'networkidle', but the latter is discouraged as a testing readiness signal. For an assertion about app readiness, prefer the element, text, URL, or response condition that represents readiness.
Wait for the UI instead of sleeping
Replace arbitrary delays such as await page.waitForTimeout(3000) with web-first assertions. These retry until the condition passes or the assertion timeout expires:
await expect(page.getByTestId('results')).toBeVisible({ timeout: 10_000 });
await expect(page.getByRole('status')).toHaveText('Ready', { timeout: 10_000 });
Choose an assertion that reflects the test’s goal: visibility, text, URL, enabled state, or another observable condition. A fixed sleep wastes time when the page is fast and still fails when it is slower than the guessed duration. Playwright documents page.waitForSelector() as discouraged in favor of locator-based waiting and assertions; see the Page API.
If the application has a specific loading indicator, you can assert that it disappears or that the final content appears. Prefer the final state when possible: it makes the failure explain what the user actually needed rather than merely reporting that a spinner changed.
Free tools Windows power users keep installed
One-click scans. No signup required.
Handle popups and secondary pages
Register the popup wait before clicking the control that opens it, so the event cannot be missed. Once the popup exists, wait for an appropriate milestone and assert its content:
const popupPromise = page.waitForEvent('popup');
await page.getByRole('button', { name: 'Open report' }).click();
const popup = await popupPromise;
await popup.waitForLoadState('domcontentloaded');
await expect(popup).toHaveTitle(/Report/);
The popup pattern and waiting for its load state are documented in the Playwright Page API. If the popup is a client-rendered app, the title or a locator for its ready state may be a better signal than waiting for a later load milestone.
Rank #4
Tell navigation timeouts from assertion and test timeouts
A timeout message points to different scopes of failure. Raising the wrong timeout can hide the symptom without fixing the cause.
| Timeout or error | What it applies to | What to inspect |
|---|---|---|
Navigation timeout |
A navigation wait. The current documentation does not state one universal default in its timeout table. | Target URL, redirects, server response, and the selected waitUntil milestone. |
expect(...): Timeout |
A web-first assertion. Current Playwright Test documentation gives a 5,000 ms default assertion timeout. | Whether the locator matches the intended element and whether the expected state or value is correct. |
Timeout of 30000ms exceeded |
Playwright Test’s test timeout. Current documentation gives 30,000 ms for the test function and fixture setup/teardown scope it describes. | The whole test and fixture path, not only the last locator. |
The values above are current defaults in the Playwright Test timeout documentation; configure them if needed rather than assuming a navigation has the same default as a test or assertion. The navigation guide and Page API describe navigation-specific waits and settings: navigation guide and Page API.
Fix a Playwright timeout in a focused sequence
- Reproduce the smallest failing operation. Reduce the test to the navigation or assertion that fails, then read the call log to see which condition Playwright was waiting for.
- Check the destination and redirects. Confirm the URL is valid and the server responds as expected. The navigation guide notes that
page.goto()follows a client-side redirect that occurs beforeload: navigation guide. - Replace fixed delays with observable conditions. Assert the destination URL, a visible heading, ready status, or other state the user needs.
- Match the milestone to the test. Use
domcontentloadedfor parsed HTML orloadwhen the load event’s resources matter. Avoidnetworkidleas a blanket fix. - Adjust only the narrow timeout that is too short. Set an assertion timeout for a genuinely slow assertion or a navigation timeout for a slow navigation, instead of raising the whole test timeout by default.
- Collect diagnostics if it remains intermittent. Capture a trace, screenshot, and relevant response details in the test environment. These are practical debugging steps, not Playwright defaults.
Common timeout symptoms and fixes
- Navigation never reaches
load: check whether a resource or redirect is stalled and whether the test truly needs that milestone. If the parsed DOM is sufficient, usedomcontentloaded; if readiness is defined by app content, assert that content. networkidlenever arrives: the page may keep connections open for polling, analytics, or other work. Do not wait for network quiet if the test only needs a specific UI state.- The click succeeds but the next assertion times out: verify the route, locator, expected text, and whether the app performs client-side navigation. Assert the resulting URL or page state instead of adding a generic load-state wait.
- The test hits 30 seconds despite a small final action: examine setup, fixtures, earlier actions, and teardown, because the test timeout covers a broader scope than one assertion.
- Increasing the test timeout changes nothing: the failing wait may be governed by a separate expect or navigation timeout. Configure the narrow scope shown by the error and investigate why the condition is not occurring.
Or skip the browser setup
If your goal is to capture a rendered page rather than test browser behavior, ScreenshotNeo offers a one-request website screenshot API. Its clean-shot flow accepts cookie or consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and each response identifies the page verdict and billing status in headers. It also has an MCP server with take_screenshot, get_page_info, and capture_pdf tools for AI agents.
curl -G "https://api.screenshotneo.com/v1/shot"
-d access_key=YOUR_API_KEY
--data-urlencode url=https://example.com
-o shot.webp
See the ScreenshotNeo API documentation for request options. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, no card required.
Frequently Asked Questions
Does Playwright automatically wait for navigation after a click?
Yes. For actions that initiate navigation, Playwright waits for navigation as appropriate. Await the action and assert the destination or resulting UI; add a load-state wait only when that milestone is needed.
Should I use networkidle to fix flaky tests?
Usually not. Playwright discourages networkidle for testing; assert the UI or other condition the test actually requires.
Quick Recap
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.

