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

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:

  1. Action: locate and interact with the target element.
  2. Synchronization: wait for navigation or the visible/DOM condition that proves the desired state exists.
  3. 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
Logitech M185 Compact Ambidextrous 2.4 GHz Wireless Mouse - Swift Grey
  • 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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
Sale
Logitech G305 Lightspeed Wireless Gaming Mouse - Black
  • 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.

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

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
Sale
Logitech M185 Compact Ambidextrous Wireless Mouse with Rubber Grips - Blue
  • 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.

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

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
Sale
Amazon Basics 3-Button USB Wired Mouse with Responsive Tracking, Plug & Play, Compatible with Windows and Mac, Black
  • 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.

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

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().

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
Sale
Acer Wireless Mouse for Laptop, 2.4GHz Computer Mouse 3 Adjustable 1600 DPI
  • 【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.

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

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 in Promise.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 finally and 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.

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

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

SaleBestseller No. 1
Logitech M185 Compact Ambidextrous 2.4 GHz Wireless Mouse - Swift Grey
Logitech M185 Compact Ambidextrous 2.4 GHz Wireless Mouse - Swift Grey
Product carbon footprint: 3.97 kg CO2e; Contoured shape: Gives you more comfort and control
$12.34
SaleBestseller No. 3
SaleBestseller No. 4
Amazon Basics 3-Button USB Wired Mouse with Responsive Tracking, Plug & Play, Compatible with Windows and Mac, Black
Amazon Basics 3-Button USB Wired Mouse with Responsive Tracking, Plug & Play, Compatible with Windows and Mac, Black
Computer mouse for easily navigating a computer interface; click, scroll, and more; 3 buttons offer effortless fingertip control
$6.79

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.