Perform the interaction first, wait for the state change that matters, and only then call page.screenshot(). Puppeteer’s current guidance recommends locators for clicking, filling, hovering, scrolling and waiting because they check that an element is in view, visible, enabled and stable. If the action navigates, arm page.waitForNavigation() and perform the action in the same Promise.all(). For JavaScript-driven updates that do not navigate, wait for an application-specific DOM or visibility condition before capturing.
The reliable action–wait–screenshot sequence
A screenshot records whatever is rendered at the instant the capture starts. A successful click call does not necessarily mean that an asynchronous request, animation or component update has finished. Treat the workflow as three explicit phases:
- Action: locate and interact with the target element.
- Synchronization: wait for navigation or the visible/DOM condition that proves the desired state exists.
- Capture: call
await page.screenshot()after that condition is true.
The selector and final wait must describe your application, not merely the fact that Puppeteer accepted the input.
Use locators for routine interactions
Puppeteer’s Page interactions guide states that “Locators is the recommended way to select an element and interact with it.” A locator action retries while Puppeteer checks readiness, including viewport visibility, enabled state and layout stability across animation frames.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
- Compact Mouse: With a comfortable and contoured shape, this Logitech ambidextrous wireless mouse feels great in either right or left hand and is far superior to a touchpad
- Durable and Reliable: This USB wireless mouse features a line-by-line scroll wheel, up to 1 year of battery life (2) thanks to a smart sleep mode function, and comes with the included AA battery
- Universal Compatibility: Your Logitech mouse works with your Windows PC, Mac, or laptop, so no matter what type of computer you own today or buy tomorrow your mouse will be compatible
- Plug and Play Simplicity: Just plug in the tiny nano USB receiver and start working in seconds with a strong, reliable connection to your wireless computer mouse up to 33 feet / 10 m (5)
- Better than touchpad: Get more done by adding M185 to your laptop; according to a recent study, laptop users who chose this mouse over a touchpad were 50% more productive (3) and worked 30% faster (4)
Click, fill, hover and scroll
Use the action that matches the user operation:
page.locator('button#details').click()clicks a button when it is actionable.page.locator('input[name="email"]').fill('dev@example.com')replaces the field value.page.locator('.product-card').hover()moves the pointer over an element.page.locator('#results').scroll()scrolls the target into view.
Prefer selectors that express an accessible role, stable ID or deliberate test attribute. Avoid selectors based on generated class names or page position when the application can provide a stable attribute.
Wait for the result, not just the action
After a non-navigating action, wait for an observable result such as a panel becoming visible, a status changing, a loading indicator disappearing or a result row appearing. A locator wait can express that condition:
await page.locator('[data-testid="results-ready"]').wait();
Choose a condition that cannot become true before the operation has completed. For example, waiting for a permanent container that existed before the click is weaker than waiting for a newly rendered result inside it.
Complete Puppeteer example
This script opens a page, fills a search field, submits it, waits for a result element, and captures the resulting state. Replace the URL and selectors with those from your application.
Recommended Free Tools
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.locator('input[name="query"]').fill('puppeteer');
await page.locator('button[type="submit"]').click();
// The application updates without a full navigation.
await page.locator('[data-testid="results-ready"]').wait();
await page.screenshot({ path: 'results.png', fullPage: true });
} finally {
await browser.close();
}
fullPage: true is optional; omit it for the current viewport only. The important ordering is the wait before the screenshot.
Rank #2
- The next-generation optical HERO sensor delivers incredible performance and up to 10x the power efficiency over previous generations, with 400 IPS precision and up to 12,000 DPI sensitivity
- Ultra-fast LIGHTSPEED wireless technology gives you a lag-free gaming experience, delivering incredible responsiveness and reliability with 1 ms report rate for competition-level performance
- G305 wireless mouse boasts an incredible 250 hours of continuous gameplay on just 1 AA battery; switch to Endurance mode via Logitech G HUB software and extend battery life up to 9 months
- Wireless does not have to mean heavy, G305 lightweight mouse provides high maneuverability coming in at only 3.4 oz thanks to efficient lightweight mechanical design and ultra-efficient battery usage
- The durable, compact design with built-in nano receiver storage makes G305 not just a great portable desktop mouse, but also a great laptop travel companion, use with a gaming laptop and play anywhere
When the action causes navigation
Set up the navigation listener before triggering the click. Puppeteer warns that a separate wait after the click can race with a fast navigation. Pair both promises in one Promise.all():
const [response] = await Promise.all([
page.waitForNavigation(),
page.locator('a.next-page').click(),
]);
await page.locator('main h1').wait();
await page.screenshot({ path: 'next-page.png' });
The navigation promise tells you that navigation completed according to Puppeteer’s navigation lifecycle. The additional heading wait verifies that the page content you intend to show is present. If you know the application’s lifecycle, you can pass an appropriate waitUntil option to waitForNavigation(), but a content-specific wait is still useful for client-rendered pages.
Form submissions and redirects
Submit buttons, links and JavaScript handlers can redirect through one or more URLs. Keep the action and navigation wait together, then wait for a selector unique to the final page. Do not infer completion from the URL alone when the destination renders asynchronously.
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 →Non-navigating UI: wait for the state your screenshot needs
Tabs, accordions, filters, modal dialogs and “load more” controls often update the existing document. Use a condition tied to the final visual state.
Opening a modal
await page.locator('[aria-label="Open settings"]').click();
await page.locator('[role="dialog"]').wait();
await page.screenshot({ path: 'settings-modal.png' });
Waiting for filtered results
await page.locator('[data-testid="filter-menu"]').click();
await page.locator('[data-value="in-stock"]').click();
await page.locator('[data-testid="results-loading"]').wait();
await page.locator('[data-testid="results-loading"]').wait({ hidden: true });
await page.locator('[data-testid="product-row"]').wait();
await page.screenshot({ path: 'in-stock.png' });
Use a result-specific condition when possible. A loading indicator that briefly appears may be missed; waiting for the resulting row or status text is generally more representative of the state you want to document.
Rank #3
- Compact Mouse: With a comfortable and contoured shape, this Logitech ambidextrous wireless mouse feels great in either right or left hand and is far superior to a touchpad
- Durable and Reliable: This USB wireless mouse features a line-by-line scroll wheel, up to 1 year of battery life (2) thanks to a smart sleep mode function, and comes with the included AA battery
- Universal Compatibility: Your Logitech mouse works with your Windows PC, Mac, or laptop, so no matter what type of computer you own today or buy tomorrow your mouse will be compatible
- Plug and Play Simplicity: Just plug in the tiny nano USB receiver and start working in seconds with a strong, reliable connection to your wireless computer mouse up to 33 feet / 10 m (5)
- Better than touchpad: Get more done by adding M185 to your laptop; according to a recent study, laptop users who chose this mouse over a touchpad were 50% more productive (3) and worked 30% faster (4)
Animations and transitions
Locator actions wait for element stability when performing the action, but your application may continue animating afterward. Wait for an end-state class, an attribute, a visible panel or another application-owned signal. A fixed delay can be useful for an unavoidable visual transition, but it is less reliable than a condition and can make tests unnecessarily slow.
Locators versus lower-level selector APIs
| Approach | Best use | Readiness and lifecycle |
|---|---|---|
| Locator actions | Routine clicks, fills, hovers, scrolling and waits | Retries while checking actionability and stability |
waitForSelector() |
Lower-level visibility or DOM selection control | Available, but it does not automatically retry a later action that fails |
| Element handles | Specialized direct DOM interaction | More control; dispose handles when they are no longer needed |
The official guide presents waitForSelector() and ElementHandle APIs as lower-level choices. Use them when their additional control is necessary; otherwise, locators make the action and readiness checks easier to reason about.
Lower-level example
await page.waitForSelector('#report', { visible: true });
const report = await page.$('#report');
if (!report) throw new Error('Report was not found');
try {
await report.click();
await page.waitForSelector('.report-complete', { visible: true });
} finally {
await report.dispose();
}
await page.screenshot({ path: 'report.png' });
With this style, you are responsible for checking that the handle still represents a usable element after rerenders and for releasing it.
Choosing waits that do not create flaky captures
- Navigation: use
Promise.all([page.waitForNavigation(), action]); then verify final content. - DOM replacement: wait for a selector that appears only after replacement.
- Visibility: wait for the panel, dialog or status that must be visible in the image.
- Loading completion: wait for the loading indicator to disappear and the expected content to appear.
- Network-dependent rendering: prefer an application-owned ready marker over a guessed delay.
Do not capture immediately after click() merely because the promise resolved. The promise confirms that the interaction was performed, not that every application task triggered by it has completed.
Common failures and fixes
“Node is either not clickable or not an Element”
Cause: the target is hidden, disabled, outside the viewport or still moving. Fix: use a locator, verify the selector, and wait for the element’s actionable state. Remove overlays or close a blocking dialog if the page requires it.
Rank #4
- Computer mouse for easily navigating a computer interface; click, scroll, and more
- USB-A wired connection; if existing device only supports USB-C, an additional adapter will be required
- High-definition (1000 dpi) optical tracking ensures responsive cursor control for precise tracking and easy text selection
- 3 buttons offer effortless fingertip control
- Plug-and-go ready for instant use
The screenshot shows the old page after a click
Cause: navigation or asynchronous rendering was not synchronized. Fix: pair navigation waits with the action in Promise.all(), or wait for a result-specific selector before capturing.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
The selector wait succeeds too early
Cause: the selector identifies a container that existed before the action. Fix: target newly inserted content, a changed attribute, a completion status or a hidden-to-visible transition that represents the final state.
The page times out
Cause: a selector never appears, the page is still loading, or the test uses a condition that this route does not produce. Fix: confirm the selector in the same viewport and account for authentication, redirects and error states. Keep timeouts finite so failures are reported instead of producing an apparently valid but incomplete image.
The captured image is blank or incomplete
Cause: capture occurred before content or lazy resources were rendered, or the page reached an error state. Fix: wait for the content marker used by the application, check the URL and visible error messages, and only then call screenshot().
Reliability and performance considerations
Use one browser lifecycle per job
Launch the browser, create the page, perform the action, capture, and close the browser in a finally block. This prevents orphaned browser processes when a navigation or selector wait throws.
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 minuteBest Value
- 【Plug and Play for Home/Office/School】The wireless computer mouse features 2.4GHz connectivity, delivering a stable, interference-free connection up to 32ft. Designed for 𝐦𝐞𝐝𝐢𝐮𝐦 𝐭𝐨 𝐥𝐚𝐫𝐠𝐞 𝐬𝐢𝐳𝐞𝐝 𝐡𝐚𝐧𝐝𝐬, it ensures comfortable use all day. Simply plug in the USB-A receiver for instant pairing—no drivers needed. 📌📌 If the mouse isn’t suitable, place the USB receiver in the battery compartment and return both.
- 【3 Levels Adjustable DPI】This travel USB mouse offers 3 adjustable DPI settings (800, 1200, 1600), allowing you to customize sensitivity for precise design work. Effortlessly switch to match your task and elevate your productivity. 📌 Please remove the film at the bottom of the mouse before use.
- 【Effortless Browsing】Equipped with forward and backward buttons, this computer mice streamlines your workflow, making it easy to navigate through web pages and files with a simple click. 📌Side button does not work on Mac.
- 【Visible Indicator Light】 The pc mouse features a visual indicator for DPI levels and low battery alerts. The red light flashes once for 800 DPI, twice for 1200 DPI, and three times for 1600 DPI. When the battery level is below 10%, the light flashes red until the mouse is completely out of power.
- 【Click to Wake】With smart sleep mode, it saves power by standby after 10 inactive minutes, just 2-3 clicks to wake. This efficient design delivers 3x longer battery life than motion-wake mice. Engineered for durability, its buttons and scroll wheel are tested for 10 million clicks, ensuring long-term reliability and consistent performance.
Keep waits specific
Broad delays increase runtime and still may be too short on a slow run. A narrow readiness selector finishes as soon as the required state exists and fails clearly when the application does not reach it.
Capture only what you need
Viewport screenshots are faster and smaller than full-page captures. Use fullPage: true when the complete document is required, and ensure the page has reached its intended scroll and lazy-loading state first.
Make failures diagnosable
On an error, record the URL, relevant selector, and exception, and save a diagnostic screenshot before closing when appropriate. This distinguishes a bad selector from a failed application request.
Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server when you want a rendered image without maintaining Puppeteer. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result.
Make one GET request (see the ScreenshotNeo documentation):
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
For code, the same request in Python is:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
And in Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo also exposes an MCP server with take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. Free accounts include 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Quick checklist
- Navigate to the starting URL and establish the required session state.
- Use a locator for the interaction whenever a routine action is sufficient.
- If it navigates, start
waitForNavigation()before the action inPromise.all(). - If it does not navigate, wait for the application’s final DOM or visibility condition.
- Call
page.screenshot()only after that condition succeeds. - Close the browser in
finallyand retain useful diagnostics on failure.
Frequently Asked Questions
Should I use a fixed timeout after every Puppeteer click?
No. Prefer a selector, visibility change or application-ready marker that proves the required state. Use a delay only when no observable condition exists.
Does a successful locator click mean the page is ready to capture?
No. It means the interaction was performed after Puppeteer’s actionability checks. Your application may still be navigating, fetching data or animating.
When is ElementHandle preferable to a locator?
Use an ElementHandle when you need lower-level control that a locator does not provide. Manage its lifetime explicitly and account for rerenders that can detach it.
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.

