How to handle Puppeteer performance issues?

Puppeteer is a powerful NodeJS library that enables automated control over Chromium-based browsers. While it’s widely used for automation, scraping and testing, you may encounter performance issues like slow script execution, excessive memory consumption or browser crashes when working with complex pages or large-scale tasks. Here are practical tips and best practices to handle these performance issues effectively.

1. Optimize page loading and navigation

  • Use page.goto() with proper options: Add waitUntil: 'networkidle0' or 'domcontentloaded' to control when the script proceeds, avoiding unnecessary waits.
    Copy code
    await page.goto('https://example.com', { waitUntil: 'networkidle0' });
  • Avoid loading unnecessary resources: Use request interception to block images, fonts, ads, or analytics scripts that are not needed.
    Copy code
    await page.setRequestInterception(true); page.on('request', (req) => { if (['image', 'stylesheet', 'font'].includes(req.resourceType())) { req.abort(); } else { req.continue(); } });

2. Reduce memory consumption

  • Close pages when they’re no longer needed: Avoid keeping multiple tabs open.
    Copy code
    await page.close();
  • Use browserContext for isolation: Instead of opening many separate browser instances, use multiple contexts within one instance.
    Copy code
    const context = await browser.createIncognitoBrowserContext(); const page = await context.newPage();
  • Call page.evaluate() carefully: Minimize passing large objects between Node.js and the browser context, as this can cause memory leaks.

3. Optimize script execution

  • Use page.evaluate() efficiently: Execute minimal, focused scripts inside the browser context.
    Copy code
    await page.evaluate(() => { document.querySelector('#button').click(); });
  • Throttle execution: Add small delays when scraping large datasets to avoid overwhelming the browser or server.
    Copy code
    await new Promise(resolve => setTimeout(resolve, 100));

4. Monitor and debug performance

  • Enable Chromium DevTools Protocol: Use client.send('Performance.enable') to capture metrics like CPU usage, memory, and network.
    Copy code
    const client = await page.target().createCDPSession(); await client.send('Performance.enable'); const metrics = await client.send('Performance.getMetrics');
  • Run with --disable-dev-shm-usage: When running Puppeteer in Docker, use this flag to prevent shared memory issues.
  • Use headless mode strategically: Sometimes running in headless: false helps reveal visual issues slowing things down.

5. Keep Chromium and Puppeteer updated

New releases often include performance improvements, bug fixes, and better memory management. Regularly update your Puppeteer package and review the release notes.

Example: Putting it all together

Copy code
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on('request', (req) => {
  if (['image', 'stylesheet', 'font'].includes(req.resourceType())) {
    req.abort();
  } else {
    req.continue();
  }
});

await page.goto('https://testingbot.com', { waitUntil: 'networkidle0' });
// Perform actions...
await page.close();
await browser.close();

Cloud-based Puppeteer testing

TestingBot provides remote browsers in the cloud, allowing you to run multiple Puppeteer tests in parallel, without having to worry about performance issues or maintenance.

TestingBot Logo

Sign up for a Free Trial

Start testing your apps with TestingBot.

No credit card required.

Start Free Trial

Other Questions