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

There is no single Puppeteer wait that proves every page is completely finished. For normal navigation, page.goto() waits for the browser’s load milestone by default. If you need content rendered later by an app, wait for that content; if a click triggers navigation, start page.waitForNavigation() before clicking. Use network idle only when a quiet network is itself the condition you need.

Choose a wait condition that matches the next step

A page can reach its load event while an application is still fetching data or rendering a component. Conversely, a page can be usable before every resource has loaded. Choose the condition based on what your script will do next, rather than treating “finished loading” as one universal state.

What your script needs Use What the wait establishes
The browser’s normal load milestone after direct navigation page.goto(url) or page.goto(url, { waitUntil: 'load' }) The documented page.goto() default is the load lifecycle event.
The document parsed, without waiting for all load-event resources page.goto(url, { waitUntil: 'domcontentloaded' }) The DOMContentLoaded lifecycle event fired.
A particular app result to appear or become visible page.waitForSelector(selector, options) The requested selector condition was met.
To act on an element when it is ready for interaction page.locator(selector).click() The locator waits for the element and action preconditions.
A defined interval of network quiet page.waitForNetworkIdle() or a navigation lifecycle option The configured network-idle condition was reached; it does not confirm a particular application task is complete.
A click that navigates or reloads the page Promise.all([page.waitForNavigation(), action]) The navigation wait is registered before the action can trigger navigation.

These conditions are not interchangeable. A selector wait is usually the clearest signal when the next operation depends on a specific result; a lifecycle event is useful when the browser milestone itself matters.

Wait for direct navigation

For a page opened by URL, await page.goto(). Its documented default is load, but spelling out the option makes the intended milestone explicit:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Search+ For Google
  • google search
  • google map
  • google plus
  • youtube music
  • youtube
await page.goto('https://example.com', { waitUntil: 'load' });

Use domcontentloaded when parsing completion is enough and you do not need to wait for the full load milestone:

await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });

That may let later script steps begin earlier, but it does not guarantee that images, application data, or delayed interface elements are ready. Add a selector or other task-specific wait if the next step relies on them.

Wait for navigation caused by an action

When clicking a link or submitting a form can navigate, register the navigation wait before triggering the action. Otherwise the navigation may begin before Puppeteer starts waiting for it.

const [response] = await Promise.all([
  page.waitForNavigation({ waitUntil: 'domcontentloaded' }),
  page.click('a.my-link'),
]);

waitForNavigation() resolves with the main resource response, or null for a fragment change or a History API URL change. Puppeteer treats History API use as navigation. If the response matters to your script, account for the possibility that it is null.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Amazon Silk - Web Browser
  • Easily control web videos and music with Alexa or your Fire TV remote
  • Watch videos from any website on the best screen in your home
  • Bookmark sites and save passwords to quickly access your favorite content

The same ordering applies to other actions that may navigate: create the wait and perform the action together with Promise.all(). Choose the lifecycle condition that suits the next step; navigation completion alone does not mean late-rendered application content is ready.

Wait for app content after navigation

For dynamic pages, wait for the specific result your script needs instead of guessing how long rendering will take:

await page.goto('https://example.com/results');
await page.waitForSelector('.results-ready', { visible: true });

Use a selector tied to a meaningful state—for example, the results container that appears when the requested data is rendered—rather than a broad element that exists before useful content is available. The visible option asks Puppeteer to wait until the matched element is present and visible.

waitForSelector() can also wait for presence without requiring visibility, or for a selector to become hidden or absent. For hidden waits, an absent selector can resolve to null. If your next step is an interaction, Puppeteer’s current interactions guidance favors locators, which wait for element presence and action readiness:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.locator('button').click();

A locator can be a better fit than separately waiting for a button and then clicking it. Use waitForSelector() when you need an explicit selector condition or when you need to confirm content before doing something else.

When network idle is appropriate

Use network idle if the condition you care about is a period of network quiet. For navigation, Puppeteer supports the networkidle0 and networkidle2 lifecycle conditions. They mean no more than zero or two network connections, respectively, for at least 500 milliseconds.

await page.goto('https://example.com', { waitUntil: 'networkidle0' });

You can also wait for network idle after navigation:

await page.waitForNetworkIdle();

The separate waitForNetworkIdle() API documents defaults of zero concurrent network connections and 500 milliseconds of idle time; it waits for at least the configured idle interval. These are defined quiet-network conditions, not a promise that a particular component has finished rendering or that the page is ready for every task.

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

Pages that hold requests open or generate periodic network activity may not reach the selected condition promptly. If the desired result is a specific piece of content, a selector or application-specific predicate is more directly tied to that result. Avoid using network idle merely as a more emphatic version of “page loaded.”

Set timeouts and handle failed waits

Waits can reject when their condition is not met in time. Puppeteer documents a 30,000-millisecond default timeout for waitForSelector(); navigation waits also document a 30,000-millisecond default. For a selector wait, set a timeout for the particular operation or adjust the page’s default timeout using the relevant page timeout method:

await page.waitForSelector('.results-ready', {
  visible: true,
  timeout: 10000,
});

The selector wait accepts an AbortSignal, and setting its timeout to 0 disables the timeout. An unbounded wait can leave automation stuck, so use that setting only when your surrounding code has another deliberate way to stop or recover the operation.

Handle timeouts at the level where you can make a useful decision: retry a transient navigation if appropriate, report that a required result did not appear, or capture diagnostic information. Do not catch and ignore a timeout if later steps assume the awaited state exists.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
Downloader for Fire, Browser...
  • Directly enter the URL of the desired file
  • Store frequently visited URLs in the favorites section for easy retrieval
  • Open the downloaded files in the file manager
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot common loading waits

  • waitForNavigation() times out after a click: Confirm that the click actually triggers navigation. Start the wait before the click, preferably in the same Promise.all(). If the action updates the current page without navigating, wait for the resulting selector or state instead.
  • The script continues but the results are missing: A lifecycle event may have fired before the app rendered its data. Add a wait for a selector that represents the required result, or use an application-specific predicate.
  • waitForNetworkIdle() never resolves: Ongoing or periodic requests can prevent a quiet interval. If network quiet is not essential, replace it with a task-specific wait. If it is essential, review the configured concurrency, idle time, and timeout against the behavior you expect.
  • A selector wait times out: Check that the selector matches the actual page, that the expected state is reachable, and whether your task needs presence or visibility. Increase the timeout only when the task legitimately needs more time; a longer timeout does not fix a selector that can never match.
  • A click fails even though the element exists: Existence alone does not establish that an element is ready for interaction. Use a locator for the action, or wait for the relevant visibility and state before interacting.
  • The navigation response is missing: A null response can be valid for fragment or History API URL changes. Check whether your workflow requires a main resource response before treating that result as an error.

Or skip the browser setup

If your goal is to capture a website image or PDF rather than automate a browser interaction, ScreenshotNeo offers a screenshot API and MCP server. A single GET request returns a PNG, JPEG, WebP, or PDF. Its capture can accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets before the shot; those steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status.

For example, this cURL request captures a page as WebP. See the ScreenshotNeo API documentation for request options.

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

ScreenshotNeo is for producing captures, not a replacement for Puppeteer when you need to click through a workflow or inspect browser state. 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.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.

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

FAQ

Can Puppeteer wait until a page is completely finished?

Not in a universal sense. A browser lifecycle event, a quiet network, and an application-specific ready state describe different conditions; wait for the one your task requires.

Should I use a fixed delay such as page.waitForTimeout()?

A fixed delay does not confirm that navigation, rendering, or a required request has completed. Prefer a lifecycle event, selector, locator, or predicate tied to the task.

Does waitForNavigation() cover History API changes?

Yes. Puppeteer considers History API URL changes navigation, although the promise can resolve with null rather than a main-resource response.

Quick Recap

Bestseller No. 1
Search+ For Google
Search+ For Google
google search; google map; google plus; youtube music; youtube; gmail
Bestseller No. 2
Amazon Silk - Web Browser
Amazon Silk - Web Browser
Easily control web videos and music with Alexa or your Fire TV remote; Watch videos from any website on the best screen in your home
SaleBestseller No. 3
Bestseller No. 5
Downloader for Fire, Browser...
Downloader for Fire, Browser...
Directly enter the URL of the desired file; Store frequently visited URLs in the favorites section for easy retrieval

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.

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