Puppeteer wait for all images to load then take screenshot

Wait for Lazy Loading Images

You may want to consider scrolling down first using a method such as Element.scrollIntoView() to account for lazy loading images:

await page.goto('https://www.digg.com/', {
  waitUntil: 'networkidle0', // Wait for all non-lazy loaded images to load
});

await page.evaluate(async () => {
  // Scroll down to bottom of page to activate lazy loading images
  document.body.scrollIntoView(false);

  // Wait for all remaining lazy loading images to load
  await Promise.all(Array.from(document.getElementsByTagName('img'), image => {
    if (image.complete) {
      return;
    }

    return new Promise((resolve, reject) => {
      image.addEventListener('load', resolve);
      image.addEventListener('error', reject);
    });
  }));
});

There is a built-in option for that:

await page.goto('https://www.digg.com/', {"waitUntil" : "networkidle0"});

networkidle0 - consider navigation to be finished when there are no more than 0 network connections for at least 500 ms

networkidle2 - consider navigation to be finished when there are no more than 2 network connections for at least 500 ms.

P.S. Of course it won't work if you're working with endless-scrolling-single-page-applications like Twitter.


Another option, actually evaluate to get callback when all images were loaded

This option will also work with setContent that doesn't support the wait networkidle0 option

await page.evaluate(async () => {
  const selectors = Array.from(document.querySelectorAll("img"));
  await Promise.all(selectors.map(img => {
    if (img.complete) return;
    return new Promise((resolve, reject) => {
      img.addEventListener('load', resolve);
      img.addEventListener('error', reject);
    });
  }));
})