October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk5 min

Convert a URL to PDF in Node.js Using Puppeteer

A practical Puppeteer workflow for turning a web page into a PDF, with advice on page readiness, print layout, PDF options, and common failures.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Puppeteer to open a fully qualified URL in a bundled browser, wait for the page state your target site needs, then call page.pdf(). Puppeteer generates PDF output with print CSS by default; the example below saves an A4 PDF and closes the browser even if navigation or rendering fails.

Install Puppeteer and create a PDF

From an existing Node.js project, install Puppeteer:

As an Amazon Associate I earn from qualifying purchases.

npm install puppeteer

Puppeteer is guaranteed to work with its bundled browser; using a different browser is at your own risk. The official PDF options reference used here reports Puppeteer version 25.12.0, so check the documentation for the version installed in your project if defaults or behavior differ. LaunchOptions

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Save the following as url-to-pdf.mjs and run it with node url-to-pdf.mjs. Replace the example URL with the page you want to render.

import puppeteer from 'puppeteer';

const url = 'https://example.com';
const browser = await puppeteer.launch();

try {
  const page = await browser.newPage();
  const response = await page.goto(url, {
    waitUntil: 'networkidle2',
    timeout: 30_000,
  });

  if (response && !response.ok()) {
    throw new Error(`Navigation failed with HTTP ${response.status()}`);
  }

  await page.pdf({
    path: 'page.pdf',
    format: 'A4',
    printBackground: true,
  });
} finally {
  await browser.close();
}

The URL passed to page.goto() should include its scheme, such as https://. Navigation can resolve after redirects with the response for the final destination; a resolved navigation does not necessarily mean the response was successful, which is why the example checks its status. The PDF is written to page.pdf in the current working directory. page.goto() · Getting started

Choose when the page is ready

page.goto() defaults to the load lifecycle condition. Its waitUntil option accepts a lifecycle value or an array of values; if you pass an array, all listed conditions must occur. The right choice depends on the site, and the documentation does not prescribe one universal readiness condition. page.goto() · WaitForOptions

Readiness choice When it can help Trade-off
load When the page’s load event is an adequate signal for the content you need. It may not mean a client-rendered application has finished updating.
networkidle2 When waiting for a quieter network is appropriate for the site. Pages that keep network requests active may not reach a network-idle condition promptly.
Page-specific signal When a known element or application-ready state indicates the content is ready; navigate, then wait for that signal. You must identify a reliable signal for the target page. There is no generic selector that fits every site.

If a page keeps polling, streaming, or otherwise making requests, a network-idle wait can be unsuitable. Choose a lifecycle condition that fits the page, then wait for a known element or application signal when navigation completion alone is insufficient. Avoid treating an arbitrary delay as proof that dynamic content is ready.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Set print layout, page size, and PDF options

page.pdf() uses print CSS media by default. This can produce a layout different from the one visible in a browser window. To render with screen CSS instead, call await page.emulateMediaType('screen') before page.pdf(). Set printBackground: true when the PDF should include background graphics; print rendering may otherwise alter colors. Page class · PDFOptions, Puppeteer 25.12.0

Option What it controls
format Named paper size. The documented default is letter; the example selects A4.
landscape Whether the page uses landscape orientation.
margin PDF page margins.
path Output file path. A relative path is resolved from the current working directory.
pageRanges The page range or ranges to include.
scale The scale applied to the page during PDF output.
preferCSSPageSize Whether CSS page dimensions take priority over the PDF’s format, width, or height options. The documented default is false.
waitForFonts Whether to wait for fonts before generating the PDF. The documented default is true.

For a document with its own @page dimensions, use preferCSSPageSize: true so CSS page sizing takes priority. Otherwise, select the intended paper format and use margins or orientation options as needed. The documented PDF timeout is 30 seconds; if rendering takes longer, review the current PDF options reference for the installed version. PDFOptions

Handle navigation errors and unsuccessful responses

page.goto() can reject for an invalid URL, SSL error, timeout, unreachable server, or failed main-resource load. It can also resolve with an HTTP error response, so inspect the returned response status when the script must reject unsuccessful pages. In headless shell mode, navigation to a PDF document is not supported. page.goto()

  • Invalid URL: Include a valid scheme such as https:// and check that the address is correctly formed.
  • Navigation timeout: The page may be slow, unreachable, or waiting on an unsuitable lifecycle condition. Check the URL and server availability, then choose a more suitable readiness strategy; increase the navigation timeout only when a longer wait is justified.
  • HTTP error status: Check response.status() and handle the status explicitly rather than treating a resolved promise as success.
  • Blank or incomplete PDF: The page may need a page-specific readiness signal, or its print stylesheet may hide or rearrange content. Inspect the page’s print layout and wait for the application’s content to be ready.
  • Missing backgrounds or unexpected colors: Enable printBackground: true when background graphics are required, and remember that print CSS is used by default.
  • PDF timeout: Rendering may exceed the documented 30-second PDF timeout. Check the document and current version’s PDF options before changing the workflow.

Close the browser in a finally block, as in the example, so it is shut down after success or failure. Puppeteer does not document a universal performance or reliability figure for this workflow; actual capture time depends on the page, its resources, and readiness behavior.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Render HTML you already have

If the input is HTML already available to your script, use page.setContent(html) to set the page content before calling page.pdf(). This is not equivalent to navigating to a remote URL: it does not by itself establish a production recipe for loading external resources, handling authentication, or determining when an application is ready. page.setContent()

Or skip the browser setup

If you need a screenshot or PDF without managing Puppeteer and its browser, ScreenshotNeo provides a website screenshot API and MCP server. For a PDF, make one GET request with the URL and request PDF output as described in the API documentation. The following cURL example shows the request shape for a screenshot; adapt the output options for PDF using the docs:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
  • It accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each of those steps can be turned off.
  • Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Response headers report the page verdict and billing status.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents, including Claude, Cursor, and other MCP clients.
  • The Free plan includes 1,000 screenshots per month with no card required. Paid plans start at $5 for 3,000 screenshots; yearly billing gives two months free.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.

Frequently Asked Questions

Can Puppeteer save a PDF directly from a URL?

Yes. Navigate with page.goto() and generate the file with page.pdf().

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Does page.pdf() use screen CSS?

No. It uses print CSS by default; call page.emulateMediaType('screen') first to use screen media.

Can Puppeteer open a PDF URL with page.goto()?

Not in headless shell mode; the page.goto() documentation lists that as unsupported.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.