Recommended Free Tools
Puppeteer’s Page class is the control surface for one browser tab: use it to navigate, find and interact with page content, run JavaScript in the page, wait for outcomes, and capture screenshots or PDFs. The examples below target Puppeteer 25.12.0, the version surfaced by the official API reference; check the matching documentation if you use another release.
What the Puppeteer Page API controls
A Page represents one tab (or an extension background page). A browser can have multiple Page instances. Page methods orchestrate work within that tab, while browser- or context-wide tasks belong to their more specific APIs. The official Page class reference covers the available methods and events.
As an Amazon Associate I earn from qualifying purchases.
For example, a typical automation flow navigates to a URL, waits for a meaningful page condition, interacts with an element, reads a result, and optionally saves a screenshot or PDF. The key is to choose a wait that matches the outcome you need rather than assuming that navigation alone means the application is ready.
Set up a Page and navigate
Install Puppeteer in a Node.js project with npm install puppeteer. This example opens a browser, creates a tab, navigates, waits for a heading, reads its text, and closes the browser even if an operation fails:
#1 Best Overall
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('h1', { visible: true });
const heading = await page.$eval('h1', element => element.textContent.trim());
console.log(heading);
} finally {
await browser.close();
}
})();
goto() accepts navigation options, including waitUntil. The documented default lifecycle event for navigation waits is load, and the documented default timeout is 30 seconds. Select a lifecycle event appropriate to the page, then wait separately for the actual application state your task depends on when necessary. See the WaitForOptions reference.
Choose how to find and interact with elements
Locators for synchronized interactions
Puppeteer’s Locator API provides a higher-level way to express interactions with page elements. Prefer it for ordinary actions when its available methods cover your needs; consult the evolving Page interactions guide for current methods and selector support.
Selectors and element handles for lower-level control
page.$(selector) finds the first matching element and returns an element handle or null. page.$$(selector) returns handles for all matching elements. page.$eval(selector, fn) runs a callback on the first match and throws if none exists; page.$$eval(selector, fn) passes all matching elements to the callback. These are useful when you need direct DOM access or a capability not exposed by a Locator.
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
For example, collect the text from every matching link:
const labels = await page.$$eval('a', links =>
links.map(link => link.textContent.trim())
);
For a state-changing action, a Locator can express the target and action together. If using a selector-based click, first verify that the target exists and is actionable as appropriate for your workflow; do not treat a successful selector lookup as proof that the click produced the intended outcome.
Run JavaScript in the page context
page.evaluate(fn, ...args) runs the supplied function in the browser page’s JavaScript context. Node.js variables are not implicitly available inside that function: pass needed values as arguments. If the function returns a Promise, Puppeteer waits for its resolution and returns the resolved value. evaluateHandle() instead returns a handle to an in-page object.
Rank #3
const title = await page.evaluate(() => document.title);
const text = await page.evaluate(selector => {
const element = document.querySelector(selector);
return element ? element.textContent.trim() : null;
}, 'h1');
Use evaluate() for values that can be returned to Node.js, and evaluateHandle() when you need to continue working with an object in the page. See the Page.evaluate() reference.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Wait for the condition that proves the task is ready
Wait for a selector
waitForSelector() resolves immediately if the selector already exists. It can wait for an element to be visible or hidden; if the expected condition is not met before the timeout, it throws. Its documented default timeout is 30,000 ms, configurable through Page timeout settings. It can also continue waiting across navigations, which is useful when a condition may appear after a sequence of page loads. See the waitForSelector reference.
await page.waitForSelector('[data-testid="results"]', {
visible: true,
timeout: 10_000,
});
Wait for a page function or network event
Use waitForFunction() when readiness is defined by a truthy expression in the page, waitForRequest() or waitForResponse() when a particular network event matters, and waitForNetworkIdle() when network activity settling is the condition you want to observe. These waits answer different questions; choose based on what constitutes success in your task.
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
Coordinate an action that may navigate
Start the navigation wait and the action together. Otherwise, a fast navigation can begin before Puppeteer starts listening for it:
const [response] = await Promise.all([
page.waitForNavigation(),
page.click('a.some-link'),
]);
This is a synchronization pattern, not a guarantee that every click navigates. Adapt the selector and navigation options to the page. A lifecycle event can occur before an application has finished rendering or fetching data, so follow it with a selector, response, or page-state wait when that is the real completion condition.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, 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 minuteCapture a screenshot or PDF
Screenshot
page.screenshot() captures the page and returns image data; request a base64 string when that output form suits your workflow. For example:
Best Value
await page.screenshot({ path: 'page.png', fullPage: true });
page.pdf() generates a PDF using print CSS media by default. To render with screen media instead, set the media type before generating the PDF:
await page.emulateMediaType('screen');
await page.pdf({ path: 'page.pdf', format: 'A4' });
Screenshot and PDF capture preserve a visual artifact; they do not establish that the page’s data or business outcome is correct. Refer to the Page API documentation for capture options.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If you need a website screenshot rather than browser automation, ScreenshotNeo can return an image or PDF from one GET request. For example, using cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
See the ScreenshotNeo API documentation for request options. It accepts cookie or consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Sign up for ScreenshotNeo free.
Troubleshoot common failures
waitForSelector()times out: The selector may not match the rendered DOM, the element may not become visible, or the page may not have reached the needed state. Check the selector against the live DOM and wait for the specific condition your task requires.$eval()throws: No element matched the selector at the time of evaluation. Wait for the element first or use a query that handles absence, such aspage.evaluate()returningnull.- Click succeeds but the next step runs too soon: The action may trigger asynchronous updates or navigation. Start navigation waits alongside navigation-triggering actions, or wait for the resulting element, response, or application state.
- Values are missing inside
evaluate(): The callback runs in the page context, not the Node.js lexical scope. Pass values through the method’s arguments. - PDF appearance differs from the browser view: PDF generation uses print media by default. Call
page.emulateMediaType('screen')first if screen media is required.
FAQ
Does each Puppeteer Page represent a separate browser?
No. A Page represents one tab or extension background page; a browser can contain multiple Page instances.
Does evaluateHandle() return the same kind of value as evaluate()?
No. evaluate() returns a value serialized back to Node.js, while evaluateHandle() returns a handle to an object in the page.
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.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →




