Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →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.
| # | Preview | Product | Price | |
|---|---|---|---|---|
| 1 |
|
Search+ For Google | Buy on Amazon | |
| 2 |
|
Amazon Silk - Web Browser | Buy on Amazon | |
| 3 |
|
Web Browser Engineering | $50.00 | Buy on Amazon |
| 4 |
|
Web Browser Surfer 3rd Edition (Web Surfer Series Book 1) | $0.99 | Buy on Amazon |
| 5 |
|
Downloader for Fire, Browser... | Buy on Amazon |
| 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:
#1 Best Overall
- 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.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsRank #2
- 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:
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Rank #3
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.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePages 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.
Best Value
- 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
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 samePromise.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
nullresponse 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.
Recommended Free Tools
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
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.

