Puppeteer Scroll Flickering Fix [Solved]

Immediate Fix

To eliminate Puppeteer scroll flickering, you must ensure the scroll action synchronizes with the browser’s internal rendering loop. Using a standard loop without delays often triggers screenshots before the browser has finished painting the new scroll position.

The most reliable fix involves using a “scroll-and-wait” approach within the page.evaluate context. This ensures the DOM is ready before the next frame is captured.


// Implementation to stop screen flickering
await page.evaluate(async () => {
  await new Promise((resolve) => {
    let totalHeight = 0;
    const distance = 100;
    const timer = setInterval(() => {
      const scrollHeight = document.body.scrollHeight;
      window.scrollBy(0, distance);
      totalHeight += distance;

      if (totalHeight >= scrollHeight) {
        clearInterval(timer);
        resolve();
      }
    }, 100); // 100ms delay to allow paint cycles
  });
});

Technical Explanation

Flickering occurs because of a mismatch between the Chrome DevTools Protocol (CDP) and the browser’s Compositor thread. When Puppeteer sends a scroll command, the browser schedules a repaint. If your script requests a screenshot or moves to the next action immediately, it may capture a “partial paint” or a blank frame.

In headless mode, GPU acceleration is often simulated or disabled. This makes the rendering pipeline more susceptible to timing issues. By introducing a small delay or using requestAnimationFrame, you allow the browser to complete the layout shift and composite the layers correctly.

Additionally, hardware acceleration settings in Node.js can conflict with certain viewports, leading to the “black screen” or “flickering white” effect during high-speed automated scrolling.

Puppeteer scroll flickering fix visualization for Node.js developers.

Alternative Methods

If the standard scroll-and-wait approach does not fit your performance requirements, you can try manipulating the viewport or using CSS overrides.

Method Best For Pros/Cons
Full Page Viewport Static Screenshots Avoids scrolling entirely; heavy on RAM.
CSS “Instant” Scroll Fast Scraping Removes animation lag; can still skip frames.
CDP Wheel Events High-Fidelity Recording Simulates real user input; complex to implement.

Disabling GPU via Launch Arguments

Often, flickering is an environment-specific bug related to hardware rendering. You can force Puppeteer to use software rendering by passing specific flags during the browser launch phase.


const browser = await puppeteer.launch({
  args: [
    '--disable-gpu',
    '--disable-dev-shm-usage',
    '--disable-setuid-sandbox',
    '--no-first-run',
    '--no-sandbox',
    '--no-zygote',
    '--deterministic-mode'
  ]
});