Logo

dev-resources.site

for different kinds of informations.

How to generate PDF's with Puppeteer on Vercel in 2024

Published at
5/9/2024
Categories
vercel
puppeteer
serverless
nextjs
Author
travisbeck
Author
10 person written this
travisbeck
open
How to generate PDF's with Puppeteer on Vercel in 2024

I've spent a lot of time gathering information, reading documentation, and banging my head against the wall to get this to work finally, so I thought I'd share my setup for anyone else chewing on this problem.

We're using @sparticuz/chromium to provide the chromium executable bundle to puppeteer. This alone wasn't enough to get it to work, as it continually timed out attempting to create a new page until I set the args specifically to this:

  const chromeArgs = [
    '--font-render-hinting=none', // Improves font-rendering quality and spacing
    '--no-sandbox',
    '--disable-setuid-sandbox',
    '--disable-gpu',
    '--disable-dev-shm-usage',
    '--disable-accelerated-2d-canvas',
    '--disable-animations',
    '--disable-background-timer-throttling',
    '--disable-restore-session-state',
    '--disable-web-security', // Only if necessary, be cautious with security implications
    '--single-process', // Be cautious as this can affect stability in some environments
  ];

Enter fullscreen mode Exit fullscreen mode

This solution also attempts to keep the browser instance around between cold starts, but I haven't thoroughly tested that to see if it helps.

Also, keep in mind that I am running this on my own site with my own user's generated content, so I don't have any real security concerns regarding the Chromium args. If you're running this on public sites, you may need to further investigate whether these settings will work for you.

Here is the full code:


//Page router vercel function config
export const config = {
  maxDuration: 150,// seconds. You'll need a paid plan to increase the duration above 10s as it's likely not enough time to complete the task. 
};

//App router vercel function config
//export const maxDuration = 150; 

import chromium from '@sparticuz/chromium';
import puppeteer, { Browser } from 'puppeteer';

let browser: Browser;
const isLocal = process.env.NODE_ENV === 'development';


const generatePDF = async ({ url }: { url: string }) => {

  // Chromium only ships with Open Sans font by default
  // You can load additional fonts using the `font` method
  // Load a font from a local file

  // await chromium.font("/var/task/fonts/NotoColorEmoji.ttf");

  // or

  // await chromium.font(
  //   "https://raw.githack.com/googlei18n/noto-emoji/master/fonts/NotoColorEmoji.ttf"
  // );


  chromium.setHeadlessMode = true;
  chromium.setGraphicsMode = false;

  const chromeArgs = [
    '--font-render-hinting=none', // Improves font-rendering quality and spacing
    '--no-sandbox',
    '--disable-setuid-sandbox',
    '--disable-gpu',
    '--disable-dev-shm-usage',
    '--disable-accelerated-2d-canvas',
    '--disable-animations',
    '--disable-background-timer-throttling',
    '--disable-restore-session-state',
    '--disable-web-security', // Only if necessary, be cautious with security implications
    '--single-process', // Be cautious as this can affect stability in some environments
  ];


  try {
    if (!browser?.connected) {
      browser = await puppeteer.launch({
        ...(isLocal
          ? { channel: 'chrome' }
          : {
            args: chromeArgs,
            executablePath: await chromium.executablePath(),
            ignoreHTTPSErrors: true,
            headless: true,
          }),
      });
    }
  } catch (error) {
    throw new Error('Failed to start browser');
  }


  const page = await browser.newPage();

  await page.emulateMediaType('print')

  const response = await page.goto(url, { waitUntil: 'networkidle0', timeout: 30000 });

  if (!response || !response.ok()) {
    throw new Error('Failed to load the page for PDF generation');
  }

  const pdf = await page.pdf({
    format: 'a4',
    omitBackground: true, // Omit background colors and images
    printBackground: true, // Include background graphics
  });


  const pages = await browser.pages();
  for (const openPage of pages) {
    await openPage.close(); // Close all open pages to avoid resource leaks
  }


  if (isLocal) {
    await browser.close(); // Close the browser if running locally
  }

  return pdf;
};
Enter fullscreen mode Exit fullscreen mode
puppeteer Article's
30 articles in total
Favicon
How to Web Scrape with Puppeteer: A Beginner-Friendly Guide
Favicon
Running Puppeteer on a Server: A Complete Tutorial
Favicon
Collect All Requested Images on a Website Using Puppeteer
Favicon
Automate Web Testing in C#: A Guide with PuppeteerSharp and SpecFlow
Favicon
A step-by-step guide to setting up a Puppeteer screenshot API on Ubuntu
Favicon
Elevate Your Web Scraping with These Puppeteer Alternatives
Favicon
Creating a Next.js API to Convert HTML to PDF with Puppeteer (Vercel-Compatible)
Favicon
How to configure Swiftproxy proxy server in Puppeteer?
Favicon
installing google chrome in docker
Favicon
Code Against the Clock: Creating the class hunter
Favicon
Writing integration tests with jest and puppeteer
Favicon
Puppeteer Vs Playwright: Scrape a Strapi-Powered Website
Favicon
Mengirim Pesan WhatsApp dengan JavaScript
Favicon
Headless Browser – A Stepping Stone Towards Developing Smarter Web Applications
Favicon
Puppeteer junior
Favicon
Converting HTML web pages into PDF
Favicon
How to Scrape With Headless Firefox
Favicon
Top 5 Puppeteer Alternatives for Node.js
Favicon
How to generate PDF's with Puppeteer on Vercel in 2024
Favicon
Simplify PDF Generation in Node.js with html-to-pdf-pup
Favicon
How to do Web Scraping with Puppeteer and NodeJS in 2024 | Puppeteer tutorial
Favicon
Sometimes things simply don't work
Favicon
User browser vs. Puppeteer
Favicon
WebAuthn E2E Testing: Playwright, Selenium, Puppeteer
Favicon
Mastering Request Interceptions in Puppeteer
Favicon
How to grab all titles of products from an Amazon page
Favicon
Testing web components
Favicon
Rendering PDF from URLs and HTML input using express js
Favicon
Login with Puppeteer and re-use cookies for another window
Favicon
How to download and upload files in Puppeteer

Featured ones: