Category: Guides

  • Creating PDF from HTML using Puppeteer in Node.js

    This guide will walk you through how to generate a PDF file from an HTML page using Puppeteer — a popular Node.js library for controlling headless Chrome or Chromium browsers. You’ll also discover a smart way to simplify this workflow using online tools later in the guide.


    🧩 Prerequisites

    Before starting, make sure you have the following installed:

    • Node.js (v22 or later recommended)
    • npm or yarn or pnpm

    If you’re running this on WSL, Linux, or inside a Debian-based container, you may need to install additional system dependencies before using Puppeteer.

    Run the following commands:

    sudo apt-get update
    sudo apt-get install -y \
        fonts-liberation \
        libappindicator3-1 \
        libatk-bridge2.0-0 \
        libnspr4 \
        libnss3 \
        libxss1 \
        libx11-xcb1 \
        libxcomposite1 \
        libxdamage1 \
        libxrandr2 \
        libgbm1 \
        libgtk-3-0 \
        ca-certificates \
        wget \
        curl
    

    These packages ensure that Chromium (used by Puppeteer) runs correctly in a headless environment.


    ⚙️ Step 1: Setup a New Node.js Project

    mkdir html-to-pdf
    cd html-to-pdf
    npm init -y
    

    This creates a new Node.js project with a default package.json file.


    📦 Step 2: Install Puppeteer

    npm install puppeteer
    

    📝 Puppeteer will automatically download a compatible version of Chromium.


    🧱 Step 3: Create a Script to Generate PDF

    Create a new file named generate-pdf.js in your project root and add the following code:

    import puppeteer from 'puppeteer';
    
    async function generatePDF() {
      const browser = await puppeteer.launch();
      const page = await browser.newPage();
    
      const htmlContent = `
        <html>
          <head>
            <style>
              body { font-family: Arial, sans-serif; margin: 40px; }
              h1 { color: #4CAF50; }
              p { font-size: 14px; }
            </style>
          </head>
          <body>
            <h1>Invoice</h1>
            <p>This PDF was generated using Puppeteer.</p>
          </body>
        </html>
      `;
    
      await page.setContent(htmlContent, { waitUntil: 'networkidle0' });
    
      await page.pdf({
        path: 'output.pdf',
        format: 'A4',
        printBackground: true,
        margin: {
          top: '20mm',
          bottom: '20mm',
          left: '15mm',
          right: '15mm'
        }
      });
    
      console.log('✅ PDF generated successfully: output.pdf');
      await browser.close();
    }
    
    generatePDF().catch(console.error);
    

    💡 Step 4: Run the Script

    Run the script using Node.js:

    node generate-pdf.js
    

    After successful execution, you’ll see output.pdf in your project directory.


    🧠 Bonus: Generate PDF from an External URL

    You can also convert any webpage directly to a PDF.

    import puppeteer from 'puppeteer';
    
    (async () => {
      const browser = await puppeteer.launch();
      const page = await browser.newPage();
    
      await page.goto('https://example.com', { waitUntil: 'networkidle0' });
    
      await page.pdf({ path: 'example.pdf', format: 'A4', printBackground: true });
    
      console.log('✅ PDF generated from example.com');
    
      await browser.close();
    })();
    

    🧰 Optional Configurations

    You can customize PDF generation with additional options:

    OptionDescription
    pathFile path to save the PDF.
    formatPaper size (e.g., A4, Letter).
    printBackgroundWhether to include background colors/images.
    landscapeSet to true for landscape orientation.
    marginSet custom margins (top, right, bottom, left).

    Example:

    await page.pdf({
      path: 'custom.pdf',
      format: 'A4',
      landscape: true,
      printBackground: true,
      margin: { top: '10mm', bottom: '10mm' }
    });
    

    🧑‍💻 Troubleshooting

    1. Puppeteer Download Too Large?

    If you already have Chrome installed, skip downloading Chromium:

    npm install puppeteer-core
    

    Then, connect Puppeteer to your local Chrome installation:

    const browser = await puppeteer.launch({
      executablePath: '/usr/bin/google-chrome', // path to your Chrome
    });
    

    2. Running in Docker or CI/CD?

    Add this config to run Puppeteer in restricted environments:

    const browser = await puppeteer.launch({
      headless: 'new',
      args: ['--no-sandbox', '--disable-setuid-sandbox'],
    });
    

    ✅ Summary

    You’ve now learned how to:

    • Create a Node.js project
    • Install Puppeteer
    • Generate a PDF from HTML content or a URL
    • Customize page settings
    • Fix environment dependencies on Linux or containers

    This setup is perfect for generating invoices, reports, or certificates from dynamic HTML templates.

    If you ever need to automate PDF generation at scale without managing browsers or code execution, you can try services like Peedief — which lets you create and render PDF templates via simple API calls. It’s great for production apps that need reliability without the hassle of maintaining Puppeteer environments.