13 min read

How to Take Screenshots with Puppeteer

This article will show you examples of using Puppeteer to take simple screenshots, full-page screenshots, multiple screenshots and screenshots of a particular HTML element.

by Josephine Loo · June 2022
How to Take Screenshots with Puppeteer
How to Take Screenshots with Puppeteer

Contents

    Puppeteer is a popular Node library that is very useful for developers to run automated website tests. In this tutorial, we will be showing you examples of how to use Puppeteer to take screenshots of web pages. We can use Puppeteer to capture simple screenshots, full-page screenshots, multiple screenshots, and screenshots of a particular HTML element.

    Pre-requisites

    To use Puppeteer to take screenshots of web pages, you will need to have these installed:

    For reference, these are the versions used in this tutorial:

    • Node.js - 14.17.3
    • npm - 6.14.13

    Please check the official documentation to check your version compatibility.

    Getting Started

    Step 1. Create a New Node.js Project

    Create a new folder for your project and go to the directory.

    mkdir puppeteer-screenshot
    cd puppeteer-screenshot
    

    Init a new Node.js project in the folder.

    npm init
    

    It will prompt you for input for a few aspects of the project, just press enter if you want to use the default values.

    Once you run through the npm init steps above, a package.json file will be generated and placed in the current directory.

    screenshot of a Node.js project

    Step 2. Install Puppeteer

    Run the command below to install Puppeteer.

    npm i puppeteer
    

    A folder named node_modules and a file named package-lock.json will be added to your project after running the command.

    screenshot of a Node.js project after installing Puppeteer

    When you run the command above to install Puppeteer, a recent version of Chromium which is guaranteed to work with the Puppeteer API is also downloaded.

    screenshot of Chromium being downloaded

    Step 3. Create a New File

    In the same project, create index.js file. This is where we will be writing our code to capture screenshots with Puppeteer.

    screenshot of index.js file

    Step 4. Import Puppeteer

    Inside the index.js file, import puppeteer.

    const puppeteer = require('puppeteer');
    

    Now, we have all files and dependencies required. Let’s start coding!

    Note : We will be writing the code in a self-invoking function.

    Taking a Simple Screenshot

    Step 1. Create a Browser Instance and a New Page

    First, create a Chrome browser instance in headless mode. As Puppeteer runs headless by default, we don’t have to state it in the parameter. Then, create a new page in the browser.

    // Create a browser instance
      const browser = await puppeteer.launch();
    
    // Create a new page
    const page = await browser.newPage();
    

    We can take the screenshot in different device views by setting the viewport size. For example, we can set the viewport to 1280x720 pixels to take a screenshot of the page in desktop view.

    // Set viewport width and height
    await page.setViewport({ width: 1280, height: 720 });
    

    Step 2. Navigate to a URL

    Next, set the URL of your target web page and call the page.goto() method with { waitUntil: 'networkidle0' } to open the URL in current page.

    const website_url = 'https://www.bannerbear.com/blog/how-to-convert-html-into-pdf-with-node-js-and-puppeteer/';
    
    // Open URL in current page  
    await page.goto(website_url, { waitUntil: 'networkidle0' });
    

    { waitUntil: 'networkidle0' } will ensure that there are no more than 0 network connections for at least 500ms before the navigation is considered to be finished.

    Step 3. Capture a Screenshot

    Next, call page.screenshot() along with the path option to capture a screenshot of the page.

    // Capture screenshot
    await page.screenshot({
      path: 'screenshot.jpg'
    });
    

    The path will set the file path to save the image to. The screenshot type (jpg/png) will be inferred from the file extension. Make sure to state the path as the image won’t be saved to the disk if no path is provided.

    We will be saving our screenshot in JPEG format in this tutorial as the speed of taking a screenshot in JPEG is faster compared to PNG.

    Beside saving your screenshot in JPEG format, there are other ways to speed up your Puppeteer screenshots too. You can read more about them in this article: 8 Tips for Faster Puppeteer Screenshots.

    Step 4. Close the Browser

    Finally, close the browser instance after the screenshot is completed.

    // Close the browser instance
    await browser.close();
    

    This is the complete code for the operation:

    const puppeteer = require('puppeteer');
    
    (async () => {
      // Create a browser instance
      const browser = await puppeteer.launch();
    
      // Create a new page
      const page = await browser.newPage();
    
      // Set viewport width and height
      await page.setViewport({ width: 1280, height: 720 });
    
      const website_url = 'https://www.bannerbear.com/blog/how-to-convert-html-into-pdf-with-node-js-and-puppeteer/';
    
      // Open URL in current page
      await page.goto(website_url, { waitUntil: 'networkidle0' });
    
      // Capture screenshot
      await page.screenshot({
        path: 'screenshot.jpg',
      });
    
      // Close the browser instance
      await browser.close();
    })();
    

    Execute the code by running node index.js in your command line and you should get a result similar to this:

    a single screenshot of a Bannerbear page captured by Puppeteer

    The code above takes a screenshot of the web page as how it is displayed on a browser window. It works fine for websites like the Google homepage which has nothing to scroll.

    a screenshot of Google homepage captured by Puppeteer

    For most web pages that are scrollable, it does not take a complete screenshot of your web page. If you want to take a full-page screenshot, you need to add an option for page.screenshot().

    Taking a Full-page Screenshot

    To take a full-page screenshot, add fullPage: true to page.screenshot().

    await page.screenshot({
          path: 'screenshot_full.jpg',
          fullPage: true 
        })
      }
    

    This will take a full-page screenshot of the web page instead of capturing just a part of the web page that fits the viewport.

    full-page screenshot captured by Puppeteer

    There are also other options that you can set for your Puppeteer screenshot like clip, encoding, omitBackground, etc. For more details, you can refer to the Puppeteer official documentation.

    Taking Multiple Screenshots

    You can also capture multiple screenshots of different web pages by passing in the URLs as an array and saving them in a folder.

    In this example, we will be taking screenshots of these pages and saving them in a folder named /images:

    First, create a new /images folder in your project directory to save the screenshots.

    screenshot of new images folder

    We want to modify this part of the code to loop through the URLs in an array and capture full-page screenshots of them:

    const website_url = urlArray[i];
    
        // Open URL in current page
        await page.goto(website_url, { waitUntil: 'networkidle0' });
      
        // Capture screenshot
        await page.screenshot({
          path: 'screenshot_full.jpg',
          fullPage: true
    });
    

    Next, create an array to store the URLs of the web pages which you want to capture full-page screenshots.

    const urlArray = [
        'https://www.bannerbear.com/blog/how-to-convert-html-into-pdf-with-node-js-and-puppeteer/',
        'https://www.bannerbear.com/blog/how-to-download-images-from-a-website-using-puppeteer/',
        'https://www.bannerbear.com/blog/5-image-apis-you-can-use-for-your-next-project-in-2022/'
    ];
    

    Then, move the code into a for loop and change the naming format of the Puppeteer screenshots:

    for(var i = 0; i < urlArray.length; i++) {
    
        const website_url = urlArray[i];
    
        // Open URL in current page
        await page.goto(website_url, { waitUntil: 'networkidle0' });
      
        // Capture screenshot
        await page.screenshot({
          path: `images/screenshot_full_${i+1}.jpg`,
          fullPage: true
        });
    
    }
    

    The code will loop through every URL in the array, capture a full-page screenshot and save them as screenshot_full_1.jpg, screenshot_full_2.jpg, and screenshot_full_3.jpg in the /images folder.

    screenshot of Bannerbear page captured by Puppeteer

    Taking a Screenshot of a Particular HTML Element

    Other than adding the fullpage option to capture a full-page screenshot, we can also capture only a particular HTML element in the webpage. For example, we can modify the previous code to capture only the post image using the CSS selector.

    You can copy the selector of the post image by right-clicking the image and selecting Inspect. Then, right-click the highlighted HTML code of the image and copy the selector.

    screenshot of getting selector of the HTML element

    This is the selector copied:

    #article_top > div > div.hero_image_container > div.

    Next, go to your index.js file and declare a variable for the selector before .screenshot() and get the element from the web page.

    const selector = '#article_top > div > div.hero_image_container > div';
    

    We can remove { waitUntil: 'networkidle0' } and ask the page to wait for the selector instead.

    await page.goto(website_url);
    await page.waitForSelector(selector);
    
    const element = await page.$(selector);
    

    Next, change page.screenshot() to element.screenshot() to capture the element. Remove fullPage: true or set it to false.

    // Capture screenshot
    await element.screenshot({
      path: `images/post_image_${i+1}.jpg`
    });
    

    The complete code looks like this:

    const puppeteer = require('puppeteer');
    
    const urlArray = [
      'https://www.bannerbear.com/blog/how-to-convert-html-into-pdf-with-node-js-and-puppeteer/',
      'https://www.bannerbear.com/blog/how-to-download-images-from-a-website-using-puppeteer/',
      'https://www.bannerbear.com/blog/5-image-apis-you-can-use-for-your-next-project-in-2022/'
    ];
    
    const selector = '#article_top > div > div.hero_image_container > div';
    
    (async () => {
      // Create a browser instance
      const browser = await puppeteer.launch();
    
      // Create a new page
      const page = await browser.newPage();
    
      // Set viewport width and height
      await page.setViewport({ width: 1280, height: 720 });
    
      for(var i = 0; i < urlArray.length; i++) {
    
        const website_url = urlArray[i];
    
        // Open URL in current page
        await page.goto(website_url);
        await page.waitForSelector(selector);
        
        const element = await page.$(selector);
    
        // Capture screenshot
        await element.screenshot({
          path: `images/post_image_${i+1}.jpg`,
        });
      }
    
      // Close the browser instance
      await browser.close();
    })();
    

    Run node index.js and you should have the post images saved to the /images folder.

    HTML element captured by Puppeteer

    Using Bannerbear API

    If you want to apply an image template or add a watermark to your images, you can do it with Bannerbear Image Generation API. It is a simple REST API that offers easy integration into any existing platform or app to generate designed images automatically.

    This is an example generated automatically from one of the Puppeteer screenshots using Bannerbear API:

    an image auto-generated using Bannerbear

    If your Puppeteer screenshots are hosted on a server, you can apply an image template to all images automatically using Bannerbear.

    Before that, you need to create a Bannerbear project and a design template. You can design the template from scratch or choose a design from the template library.

    This Pitch Deck Template consists of a dynamic image object and some dynamic text objects which can be set when calling the API.

    You need to call the API with your project API key and the template ID.

    imgUrl.forEach((url, i) => {
    
      var data = {
        template: TEMPLATE_ID,
        modifications: [
        {
          "name": "title",
          "text": "You can change this text",
          "color": null,
          "background": null
        },
        {
          "name": "rectangle",
          "color": null
        },
        {
          "name": "page_number",
          "text": "You can change this text",
          "color": null,
          "background": null
        },
        {
          "name": "image_container",
          "image_url": url
        },
        {
          "name": "heading_1",
          "text": "You can change this text",
          "color": null,
          "background": null
        },
        {
          "name": "paragraph_1",
          "text": "You can change this text",
          "color": null,
          "background": null
        },
        {
          "name": "heading_2",
          "text": "You can change this text",
          "color": null,
          "background": null
        },
        {
          "name": "paragraph_2",
          "text": "You can change this text",
          "color": null,
          "background": null
        },
        {
          "name": "heading_3",
          "text": "You can change this text",
          "color": null,
          "background": null
        },
        {
          "name": "paragraph_3",
          "text": "You can change this text",
          "color": null,
          "background": null
        }
       ]
      };
    
      fetch('https://api.bannerbear.com/v2/images', {
        method: 'POST',
        body: JSON.stringify(data),
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${API_KEY}`,
        }
      });
      
    });
    

    It saves a lot of time when you have a lot of images that needs to be edited as the images can be generated automatically using Bannerbear by simply calling the API.

    If you’re interested to know more about how you can automate your process using Puppeteer or Bannerbear, here are some articles that might help you:

    Josephine Loo
    Josephine is an automation enthusiast. She loves automating stuff and helping people to increase productivity with automation.

    Follow the Journey

    Hello I'm Jon, the founder of Bannerbear — every 2 weeks I send a newsletter with updates from the Product, Marketing and Business sides of my startup, subscribe below to receive it!