Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsCall and await dispose() when you are finished with a live Puppeteer handle: await handle.dispose();. This releases the referenced page object for garbage collection; it does not promise that memory is reclaimed immediately. ElementHandle uses the same method because it extends JSHandle.
Dispose of a handle after its last use
A JSHandle retains a reference to an object in the page context. For example, page.evaluateHandle() returns a handle rather than a plain JavaScript value. While that handle remains live, the referenced object is kept from garbage collection. Dispose of it as soon as your code no longer needs the reference.
const handle = await page.evaluateHandle(() => window);
// Use handle while needed.
await handle.dispose();
JSHandle.dispose() returns a Promise<void>, so use await to ensure the cleanup call completes before proceeding.
Dispose of an ElementHandle
An ElementHandle is a handle to a DOM element and inherits dispose() from JSHandle. Dispose it after its final operation. A finally block is useful when an operation might throw, because it still runs cleanup on the error path.
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 →#1 Best Overall
const element = await page.waitForSelector('div.example');
try {
if (element) {
await element.click();
}
} finally {
await element?.dispose();
}
The null check matters: selector methods may return null when no element matches. Optional chaining in the cleanup also avoids calling dispose() on a null result.
Dispose of a selector handle after extracting data
If you pass a handle into page.evaluate() to read a value, dispose of the handle after the evaluation has finished. The evaluation result can be an ordinary string, while the handle remains a separate retained reference:
Rank #2
const bodyHandle = await page.$('body');
if (bodyHandle) {
try {
const html = await page.evaluate(body => body.innerHTML, bodyHandle);
console.log(html);
} finally {
await bodyHandle.dispose();
}
}
Know when Puppeteer disposes handles automatically
Puppeteer automatically disposes a handle when its associated frame navigates away or its parent execution context is destroyed. That lifecycle cleanup is not a substitute for disposing handles you are finished with while the context remains active—for example, during a long-running page session.
Disposal releases the reference for garbage collection; it does not guarantee immediate reclamation or a particular amount of memory freed. The API documentation does not establish that calling dispose() repeatedly is harmless, so structure code to dispose once, after the last use.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use a locator or a value when you do not need a live handle
For ordinary element selection and interaction, Puppeteer’s current guide recommends locators. They are often a better fit than retaining an element handle just to click or fill an element. If you use the lower-level waitForSelector() API and keep its returned handle, dispose it when done.
For data extraction, consider an API that returns the value you need rather than a page-object reference. jsonValue() produces serializable portions as a plain value, but it is a separate operation: it is not documented as disposing of the originating handle. It can fail on circular structures and does not call toJSON.
Rank #4
Troubleshoot common handle-cleanup mistakes
- Cleanup is skipped after an error: put the handle’s last operation in a
tryblock and calldispose()infinally. - A selector result is null: check the result before using it. A missing match is not a handle, so it cannot be clicked or disposed as one.
- You assumed extracting a value disposes the handle: it does not. Dispose the handle separately after the value operation completes.
- You expected memory to drop immediately: disposal makes the referenced object eligible for garbage collection; it does not force collection or promise when it occurs.
- You are keeping handles for routine interactions: use a locator when it suits the task, or return a serializable value when a live page-object reference is unnecessary.
Or skip the browser setup
Disposing a Puppeteer handle is the right fix when your code needs to manage a retained page-object reference. If your actual goal is simply to capture a website screenshot, ScreenshotNeo is a separate screenshot API: one GET request returns an image or PDF without requiring you to manage a browser handle. It removes cookie banners, popups and chat widgets before capture; bot checks, blank pages and failed loads are not billed; and its MCP server lets AI agents take screenshots.
For example, this cURL request saves a WebP screenshot of Stripe:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for request options. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for free.
Quick Recap
Best Value
- Used Book in Good Condition
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.

