waitUntil tells Puppeteer or Playwright which browser navigation milestone must occur before a navigation call resolves. Both default to load, but their network-idle options differ: Puppeteer has networkidle0 and networkidle2, while Playwright has one networkidle value and advises against using it to decide whether a test is ready. Choose the milestone—or, better for tests, the application condition—the next step actually needs.
What each waitUntil option means
| Purpose | Puppeteer | Playwright | What it waits for |
|---|---|---|---|
| Document parsed | domcontentloaded |
domcontentloaded |
The document’s DOMContentLoaded event. Parsing is complete, but useful content in a single-page app may not yet be rendered. See the Puppeteer lifecycle events and Playwright Page API. |
| Browser load event | load (default) |
load (default) |
The browser’s load event. Use it when that event is the required boundary, not merely because it is the default. See Puppeteer WaitForOptions and the Playwright Page API. |
| Network quiet | networkidle0 or networkidle2 |
networkidle |
Puppeteer distinguishes at most zero from at most two active connections for at least 500 ms. Playwright’s single value means no network connections for at least 500 ms. These are not interchangeable labels. See Puppeteer lifecycle events and the Playwright Page API. |
| Response received and loading begun | Not a documented lifecycle value | commit |
Playwright resolves after the response is received and the document has started loading. It does not wait for document events or content to appear. See the Playwright Page API. |
Which condition should you choose?
- Choose
domcontentloadedif the next operation needs only the parsed document and you have another check for the content it uses. - Choose
loadwhen the browser load event itself matters to the workflow. - Choose Playwright
commitwhen you need to know the response arrived and loading started, then wait separately for the needed content or condition. - Choose an application-specific check for test readiness. If the test needs a button to be usable or results to be visible, assert that state rather than treating quiet network activity as proof. Playwright says not to use
networkidlefor testing and recommends web assertions to assess readiness in its Page API.
Network silence can be a poor proxy for readiness: polling, analytics, streaming, and other background requests may prevent a quiet period, while a quiet network alone does not prove the page has rendered the state your test needs.
How to use waitUntil in navigation calls
Puppeteer
Puppeteer’s page.goto() accepts one lifecycle value or an array. With an array, navigation resolves only after every listed event has fired. The documented default is load; its WaitForOptions interface documents a 30,000 ms timeout default, which can be changed with page timeout settings. See WaitForOptions.
await page.goto('https://example.com', {
waitUntil: 'domcontentloaded',
timeout: 30_000,
});
// An array requires both lifecycle events.
await page.goto('https://example.com', {
waitUntil: ['domcontentloaded', 'load'],
});
The first example uses the documented timeout default explicitly; omit timeout to use the configured page timeout. Pick an array only when all listed milestones are genuinely required.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →#1 Best Overall
Playwright
Playwright navigation methods default to load and support commit, domcontentloaded, load, and networkidle. A test should usually follow navigation with a web assertion for the state it needs.
await page.goto('https://example.com', {
waitUntil: 'domcontentloaded',
});
await expect(page.getByRole('heading', { name: 'Example Domain' }))
.toBeVisible();
For an early navigation boundary, use commit and then make the readiness condition explicit:
Rank #2
await page.goto('https://example.com', { waitUntil: 'commit' });
await expect(page.getByRole('heading', { name: 'Example Domain' }))
.toBeVisible();
Navigation waits versus waitForLoadState
In Playwright, page.goto() and other navigation waits use navigation waitUntil options. page.waitForLoadState() is different: it waits for a state on an already committed navigation, accepts only load, domcontentloaded, or networkidle, and resolves immediately if the requested state has already occurred. The documentation notes it is usually unnecessary because Playwright auto-waits before actions. See the Frame API.
await page.goto('https://example.com', { waitUntil: 'commit' });
await page.waitForLoadState('domcontentloaded');
Do not assume that similarly named APIs share option types: Puppeteer’s separate waitForNetworkIdle() has its own options, including a documented default idle time of 500 ms. That is not the same thing as copying a navigation lifecycle label into another framework.
Free tools Windows power users keep installed
One-click scans. No signup required.
Common mistakes and fixes
- Using
networkidle0ornetworkidle2with Playwright: those are Puppeteer lifecycle labels. Use Playwright’snetworkidleif you specifically need that state, or preferably assert the application state required by the test. - Using
commitwith Puppeteer: it is not a documented Puppeteer lifecycle value. Choose a Puppeteer-supported event such asdomcontentloadedorload. - Waiting for
loadwhen the page keeps background requests open: if the workflow does not require that event, wait for an earlier meaningful milestone and then check the specific content needed. - Assuming
domcontentloadedmeans the app is ready: it confirms document parsing, not that a client-rendered interface has finished producing the target content. Add a selector or web assertion for that content. - Waiting for a state that already happened: Playwright’s
waitForLoadState()resolves immediately if that state was already reached; it does not force a new navigation.
Version and API reference notes
The cited Puppeteer API search result identifies version 25.12.0. Playwright’s linked API references are rolling documentation pages; the Page API displayed later-version additions including v1.62 when retrieved. Check the current references when relying on version-specific behavior: Puppeteer WaitForOptions, Puppeteer lifecycle events, Playwright Page API, and Playwright Frame API.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If your goal is to capture a page rather than write browser automation, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF; for example:
Quick Recap
Best Value
Rank #4
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for request options. Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Sign up for free.
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.




