October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk4 min

How to Work with JavaScript Handles in Puppeteer

Puppeteer handles preserve references to page-side objects. Learn when to use evaluateHandle(), work with ElementHandle and properties, and dispose handles when finished.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use page.evaluate() when you need a serializable value back in Node.js; use page.evaluateHandle() when you need to keep working with a page-side object such as a DOM node. Puppeteer wraps that live reference in a JSHandle, or an ElementHandle when the result is an element. Dispose handles when you are finished with them.

What is a JSHandle in Puppeteer?

A JSHandle is a Node-side reference to an object in the page’s JavaScript context. It is not a copied JavaScript object that you can freely inspect in Node. The handle lets automation refer to that page-side object across calls while preserving its identity. Puppeteer keeps the referenced object from being garbage-collected until the handle is disposed or its page context is destroyed. See the JSHandle API reference.

This is useful when a result is not ordinary serializable data—for example, a DOM node—or when you need to perform further work against the same page-side object.

When should I use evaluate() or evaluateHandle()?

Method What you get Use it when
page.evaluate() A result transferred back as a serialized value. You need data such as text, a number, or a plain object in Node.js.
page.evaluateHandle() A handle to the object in the page context. You need a DOM node or another page-side object for follow-up work.

Returning a DOM node from ordinary evaluation can produce an unexpected empty object because the node is not a plain serializable value. Use evaluateHandle() to preserve the reference. The Puppeteer JavaScript execution guide explains the serialization distinction.

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

How do I get and use an ElementHandle?

ElementHandle extends JSHandle with element-specific operations. When evaluateHandle() returns a DOM element, Puppeteer represents it as an ElementHandle. For example, this code gets the body element, reads its HTML in the page context, then releases the handle:

const bodyHandle = await page.evaluateHandle(() => document.body);
const html = await bodyHandle.evaluate(body => body.innerHTML);
console.log(html);
await bodyHandle.dispose();

For an element you intend to interact with, you can use element methods such as click() rather than extracting a serialized value. For example:

const buttonHandle = await page.evaluateHandle(() => document.querySelector('button'));
const button = buttonHandle.asElement();

if (button) {
  await button.click();
  await button.dispose();
} else {
  await buttonHandle.dispose();
}

asElement() returns the handle as an ElementHandle if it represents an element; otherwise it returns null. The method is documented in the asElement API reference. The ElementHandle API reference covers element operations.

How do I pass handles and inspect properties?

A handle can be passed as an argument to an evaluation function, letting code in the page context work with the referenced object. Handles also provide methods including evaluate(), evaluateHandle(), getProperties(), getProperty(), jsonValue(), asElement(), and dispose().

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

getProperties() returns a map whose property values are themselves handles. Dispose those handles when finished, as well as the original handle if you no longer need it:

const objectHandle = await page.evaluateHandle(() => ({ title: document.title }));
const properties = await objectHandle.getProperties();
const titleHandle = properties.get('title');

if (titleHandle) {
  console.log(await titleHandle.jsonValue());
  await titleHandle.dispose();
}

await objectHandle.dispose();

For ordinary serializable output, use jsonValue() on a handle or return data directly from evaluate(). jsonValue() returns the serializable portions of the referenced object; it does not invoke a toJSON method and can throw if the value is circular. See the jsonValue API reference.

What runs in the page context?

Functions passed to evaluate() or evaluateHandle() are converted to strings and run in the target page. They cannot access variables or functions from the surrounding Puppeteer script’s lexical scope. Pass needed values as arguments instead. Puppeteer also awaits a promise returned by the page function.

const label = 'Continue';
const matchingText = await page.evaluate((text) => {
  return [...document.querySelectorAll('button')]
    .find(button => button.textContent.trim() === text)?.textContent.trim() ?? null;
}, label);

Here, label is passed explicitly; it is not captured from the Node.js closure.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When should I dispose handles?

Call dispose() when you are done with a handle. This releases its reference so the page-side object can be garbage-collected. Puppeteer also auto-disposes handles when their frame navigates or their parent execution context is destroyed, but those events are not a substitute for routine cleanup. See the dispose API reference.

In particular, keep cleanup visible when code creates handles in a loop or retains property handles from getProperties(). Dispose each retained handle once its value or interaction is no longer needed.

Common mistakes and fixes

  • Treating a handle as a plain Node object: use evaluate() or jsonValue() when you need serializable data.
  • Getting {} for a DOM node: use evaluateHandle() when you need the node reference.
  • Referencing an outer variable inside page code: pass it as an evaluation argument.
  • Calling element methods on a general handle: check asElement(); it can return null.
  • Leaving property handles unreleased: dispose handles returned from getProperties() as well as any parent handle you no longer need.

Or skip the browser setup

If your task is to capture a website screenshot rather than manipulate a live page object, ScreenshotNeo offers a one-request API. 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

ScreenshotNeo accepts cookie banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers indicate the page verdict and billing status. Its MCP server includes tools for AI agents to take screenshots. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. For this screenshot-specific task, try ScreenshotNeo. Sign up free for 1,000 screenshots a month, with no card required.

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

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

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.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.