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.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

After the exposed function has finished running, call await browser.close() to close the Puppeteer browser and all of its pages. page.exposeFunction() does not require a separate shutdown call. Put browser cleanup in a finally block if it must also run when your task throws an error.

Close the browser with browser.close()

page.exposeFunction(name, callback) makes a named function available on the page’s window. When page JavaScript calls it, Puppeteer runs the callback in Node.js and gives the page a promise for its result. Once that work is complete, close the browser through the Browser object returned by puppeteer.launch():

import puppeteer from 'puppeteer';

let browser;

try {
  browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.exposeFunction('myFunction', async value => {
    // This callback runs in Node.js.
    return value;
  });

  const result = await page.evaluate(async () => {
    return window.myFunction('done');
  });

  console.log(result);
} finally {
  if (browser) {
    await browser.close();
  }
}

The await on page.evaluate() matters here: it waits for the page-side call and its exposed-function promise to finish before execution reaches cleanup. The finally block then attempts to close the browser whether the task completes normally or throws after launch. The if (browser) guard covers a launch failure, where there is no browser instance to close.

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

This is a cleanup pattern, not a special requirement imposed by exposeFunction(). If you already have a browser lifecycle managed elsewhere, close it at the point that owns the browser rather than unexpectedly shutting it down from a task that only borrows it.

Choose the shutdown method by what should remain open

The methods below have different scopes. Select the one that matches both who owns the browser and which resources should remain available after the operation.

Method What it closes or leaves running Use it when
await browser.close() Closes the browser and all pages associated with it. Your script owns the browser and the whole browser session should end.
browser.disconnect() Stops Puppeteer from controlling the browser; the browser and its pages remain running. You connected to an externally managed browser and want to detach without shutting it down.
await context.close() Closes all pages in that BrowserContext. The task is isolated to a context, but the browser should remain available.
await page.close() Closes one page, not the whole browser. Only the tab or page used for the task should end.

Do not use browser.disconnect() as a substitute for closing a browser your script launched and is responsible for shutting down: it detaches the controller but intentionally leaves the browser running. Conversely, calling browser.close() on a shared browser ends the session for every page associated with it, not just the page where the exposed function was registered.

Rank #2
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

Does exposeFunction change browser cleanup?

No. The exposed callback runs in Node.js, but it is not a separate browser process that needs its own shutdown method. Complete or await any work that depends on it, then clean up the browser, context, or page according to the scope you intend to end.

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

One detail matters if the page remains open: exposed functions survive navigations. Navigating to another URL is therefore not a way to remove the exposed function. If you want to keep the page but remove the binding, use the page-level removeExposedFunction(name) method. Removing the binding and closing the browser are separate operations; you do not need to remove it before closing the browser.

Common shutdown mistakes and fixes

  • The browser stays open after the exposed call. Make sure the code path reaches await browser.close(). If earlier work can throw, put cleanup in finally rather than only after the successful path.
  • The page call is still in progress when cleanup starts. Await the promise returned by page.evaluate(), and make the in-page function await window.myFunction() when its result or completion matters. Otherwise the task can proceed to cleanup before the exposed callback has completed.
  • Other pages unexpectedly close. You closed the browser, which ends all associated pages. Use page.close() for a single page or context.close() for pages in one context.
  • The browser remains running after Puppeteer stops controlling it. browser.disconnect() only detaches Puppeteer. Use browser.close() if this code owns the browser and should end it.
  • The exposed function still exists after navigation. That is expected: exposed functions survive navigations. Call removeExposedFunction(name) if the page is staying open and you need to remove the binding.
  • Cleanup throws because launch did not produce a browser. Keep the browser variable outside the try block and check that it was assigned before calling close(), as in the example.

Reliability and version considerations

Awaiting the operation before cleanup makes the intended ordering explicit: the page finishes its call to the Node.js callback, then the browser is closed. A finally block is useful for ordinary JavaScript error paths, but it cannot guarantee cleanup if the process is forcibly terminated or otherwise stops executing.

Puppeteer documentation reviewed for this guidance is version 25.12.0; the API reference may change as Puppeteer releases new versions. Match the method names and behavior to the version installed in your project. Browser shutdown is a resource-lifecycle decision rather than a special cost or billing step associated with exposeFunction().

Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • 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
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If what you need is a website screenshot rather than a page-to-Node callback, ScreenshotNeo offers a one-request screenshot API. It is a different task from exposeFunction(): it captures a page instead of running your custom Node.js callback. The API accepts a URL and can return PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 screenshots. Every feature is available on every plan.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card required.

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.