Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use puppeteer to take full screenshots of several websites?

I am trying to take a screenshot using Node.js with puppeteer. I am not using page.screenshot() because the screenshot needs to contain the entire desktop. Instead, I am screenshotting with ImageMagick's import command.

My current code works most of the time. But other times, it fails with strange results, such as:

  • The tab is switched, but the screenshot contains half of the old page.
  • The page is switched but blank.
  • Adding a delay works but is not ideal, because sometimes page loading is very slow.

The problem seems to be that page.bringToFront() does not wait for the page to load fully.

I am new to both Node and puppeteer. Please suggest a way to:

  1. Load a page in Chrome.
  2. Switch to the page once loaded.
  3. Take a screenshot of the desktop by executing a command-line tool.

Adding a delay to the code does not seem to be the best solution.

Any suggestion on code improvement would be helpful.

const puppeteer = require('puppeteer');
const execSync = require('child_process').execSync;
const sleep = require('sleep'); 

(async () => {
    const browser = await puppeteer.launch({
        headless: false,
        args: [
            '--ignore-certificate-errors',
            '--no-sandbox',
            '--disable-infobars',
            '--disable-setuid-sandbox',
            '--incognito',
            '--window-size=1600,1200',
            '--start-maximized',
            "--disable-gpu"],
        // slowMo: 250, // slow down by 1550ms
    });

    await browser.newPage();
    await browser.newPage();
    const pages = await browser.pages();
    await Promise.all([
        grabpage(pages[0], 'https://www.cnn.com', 'cnn'),
        grabpage(pages[1], 'https://www.bbc.com', 'bbc'),
        grabpage(pages[2], 'https://www.rediff.com', 'rediff'),
    ]);
    // Someday we will close the browser also.
})();

async function grabpage(page, url, path) {
    await page.goto(url);
    var infront =page.bringToFront();
    infront.then(
        sleep.sleep(5),
        execSync('import -window root ' + path +'.jpg'),
    );
    console.log('took Screenshot: '+path+'.jpg')
}

Rediff page not loaded fully without sleep

like image 207
Chakra Avatar asked Jan 22 '26 12:01

Chakra


1 Answers

You're making it all confusing by trying to run everything in parallel with Promise.all. Because you have only one instance of browser, when you run grabpage 3 times in parallel, they're all competing for control over browser and can get in between each other's awaits.

I would also suggest that you open and close individual pages in grabpage. You'd have to switch it to pass browser in and do const page = await browser.newPage();

so you end up with

(async () => {
    const browser = await puppeteer.launch({
      headless: false,
      args: [
            '--ignore-certificate-errors',
            '--no-sandbox',
            '--disable-infobars',
            '--disable-setuid-sandbox',
            '--incognito',
            '--window-size=1600,1200',
            '--start-maximized',
            "--disable-gpu"],
      //      slowMo: 250, // slow down by 1550ms
    });

    await grabpage(browser, 'https://www.cnn.com', 'cnn'),
    await grabpage(browser, 'https://www.bbc.com', 'bbc'),
    await grabpage(browser, 'https://www.rediff.com', 'rediff'),
})();

async function grabpage(browser, url, path) {
  const page = await browser.newPage();
  await page.goto(url);
  execSync('import -window root ' + path +'.jpg')
  // await page.screenshot({path: `${path}.png`}); //if you just need to take a screenshot, not the whole desktop
  await page.close();
}

not sure why you need to take the full desktop, though if you start-maximized. i guess you care about the tiny bit of OS chrome that you get in the screenshot.

like image 129
Andrei R Avatar answered Jan 24 '26 03:01

Andrei R



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!