ScreenshotNeo

BlogGuides

Puppeteer Screenshot and PDF Examples

Capture full pages and elements with Puppeteer, or generate print-ready PDFs. Runnable examples cover key options, layout choices and common errors.

By the ScreenshotNeo team4 October 20267 min read

Puppeteer can capture a rendered page as an image with page.screenshot() and export it as a PDF with page.pdf(). Use fullPage: true for content beyond the viewport, an element handle for one component, and PDF options to control paper size, margins, orientation and print styling. These examples use JavaScript with Puppeteer.

Set up Puppeteer

Install Puppeteer in a Node.js project. The standard Puppeteer package downloads a compatible browser as part of installation.

npm init -y
npm install puppeteer

The examples below use ES modules. Add "type": "module" to package.json, or save a sample with the .mjs extension. Each script launches Chromium, closes it in a finally block, and writes output files to the current directory.

Capture a full-page screenshot

Page.screenshot() captures the page. By default, it captures the viewport; set fullPage: true to capture the full scrollable page. With a path, Puppeteer writes the image to that file.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'networkidle2' });
  await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
  await browser.close();
}

networkidle2 is one documented navigation wait option used in the Puppeteer guide. Pages that keep network connections open or update content after navigation may need a different readiness condition; choose a wait strategy that matches the page, and wait for a known selector when the content you need is identifiable.

Capture an element or a clipped region

To capture one component, wait for its selector and call screenshot() on the element handle. Puppeteer scrolls an element into view if needed. The element must remain attached to the DOM when the screenshot is taken.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'networkidle2' });
  const card = await page.waitForSelector('main');
  if (!card) throw new Error('The main element was not found');
  await card.screenshot({ path: 'main.png' });
} finally {
  await browser.close();
}

Use the page-level clip option when you need a specific rectangle rather than an element’s bounds. A clip defines the capture region; coordinates and dimensions should describe the region you intend to save.

await page.screenshot({
  path: 'region.png',
  clip: { x: 0, y: 0, width: 800, height: 600 }
});

Choose screenshot format and output

The documented default image type is PNG. When saving to a path, Puppeteer can infer the format from the file extension. Supported screenshot choices include PNG, JPEG and WebP; quality applies to JPEG and WebP, not PNG.

// JPEG with lossy quality from 0 to 100
await page.screenshot({ path: 'page.jpg', type: 'jpeg', quality: 80 });

// WebP with lossy quality
await page.screenshot({ path: 'page.webp', type: 'webp', quality: 80 });

// Transparent pixels where the page background would otherwise appear
await page.screenshot({ path: 'transparent.png', omitBackground: true });

If no path is supplied, the screenshot is returned as image bytes (a Uint8Array by default). You can request base64 encoding with the corresponding encoding option when that is more convenient for your application.

Generate a PDF

page.pdf() returns PDF bytes and can also write a file when passed a path. PDF generation uses print CSS media by default. Set printBackground: true to include background graphics.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'networkidle2' });
  await page.pdf({ path: 'page.pdf', format: 'A4', printBackground: true });
} finally {
  await browser.close();
}

To render screen styles in the PDF instead of print styles, emulate screen media before generating it:

await page.emulateMediaType('screen');
await page.pdf({ path: 'screen-layout.pdf', format: 'A4', printBackground: true });

Printing can modify colors. When exact colors matter, the page’s CSS can request them with -webkit-print-color-adjust, for example * { -webkit-print-color-adjust: exact; }. Whether this produces the desired result depends on the page styles.

Configure PDF page layout

Choose paper geometry, page orientation, margins and page range to match the output you need. format defaults to Letter and takes priority over width and height when specified. Set preferCSSPageSize: true to give a CSS @page size priority over the API’s paper dimensions.

await page.pdf({
  path: 'report.pdf',
  format: 'A4',
  landscape: false,
  margin: {
    top: '16mm',
    right: '14mm',
    bottom: '16mm',
    left: '14mm'
  },
  printBackground: true,
  preferCSSPageSize: true,
  pageRanges: '1-5, 8, 11-13',
  scale: 1,
  waitForFonts: true
});
  • format selects a named paper size. Width and height can be used for custom dimensions when no format takes precedence.
  • landscape selects landscape orientation; its default is false.
  • margin sets the page margins.
  • pageRanges restricts which pages are included, using ranges such as 1-5, 8, 11-13.
  • printBackground includes backgrounds; it defaults to false.
  • scale defaults to 1 and accepts values from 0.1 to 2.
  • waitForFonts defaults to true and waits for document.fonts.ready. A background page may need Page.bringToFront() for font readiness.

Headers and footers are off by default. Enable displayHeaderFooter and provide templates if the document needs them. The documented template classes include date, title, url, pageNumber and totalPages.

await page.pdf({
  path: 'report-numbered.pdf',
  format: 'A4',
  displayHeaderFooter: true,
  headerTemplate: '<span class="title"></span>',
  footerTemplate: '<span class="pageNumber"></span> / <span class="totalPages"></span>',
  margin: { top: '20mm', bottom: '20mm' }
});

Pick the right capture settings

Need Use Consider
Visible viewport only page.screenshot() This is the default capture extent.
Entire scrollable page fullPage: true Large pages can produce large images and take longer to process.
One component waitForSelector() then element screenshot() The selected element must still be attached to the DOM.
Fixed rectangular area clip: { x, y, width, height } Set coordinates and dimensions for the intended region.
Transparent image background omitBackground: true The option defaults to false.
Print-oriented document page.pdf() PDF generation uses print media by default.
PDF that follows screen styling emulateMediaType('screen') before page.pdf() Screen and print styles may arrange content differently.

Complete screenshot and PDF script

This combined example saves a full-page screenshot, an element screenshot and a PDF from the same page. Change the URL and selector to fit your page.

import puppeteer from 'puppeteer';

const url = 'https://example.com';
const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.goto(url, { waitUntil: 'networkidle2' });

  await page.screenshot({ path: 'full-page.png', fullPage: true });

  const main = await page.waitForSelector('main');
  if (!main) throw new Error('Could not find the main element');
  await main.screenshot({ path: 'main.png' });

  await page.pdf({
    path: 'page.pdf',
    format: 'A4',
    printBackground: true,
    margin: { top: '16mm', right: '14mm', bottom: '16mm', left: '14mm' }
  });
} finally {
  await browser.close();
}

Performance, reliability and cost

These examples generate files through Puppeteer and Chromium. Their runtime and resource use depend on the page, browser environment, capture dimensions and PDF layout; the cited API documentation provides no general benchmark. Full-page captures include more content than viewport captures, so consider the resulting image dimensions and file size when processing long pages.

For more reliable captures, wait for the page state you actually need, verify required selectors exist, and ensure the browser closes even when navigation or capture throws an error. A page may render differently under print media than screen media, and fonts or page CSS affect output. Puppeteer itself does not establish that a website will permit or consistently serve automated browser requests.

Puppeteer is software for generating digital files; no physical product is required by this workflow. The available documentation does not establish a per-capture charge or provide usage-cost figures. Your operational cost depends on where and how you run Node.js and Chromium.

Troubleshooting

Symptom Likely cause Fix
The element screenshot fails because the element is detached The page replaced or removed the element after it was selected. Wait for the page’s final state, then query the selector again immediately before capturing.
The target content is missing Navigation completion did not mean that the desired content was ready. Wait for a selector that marks the content as available, then capture.
The screenshot only shows the viewport fullPage defaults to false. Set fullPage: true for a full-page capture.
The PDF colors or layout differ from the browser view PDF uses print CSS media by default and printing can modify colors. Emulate screen media when screen styling is intended; enable background printing and use -webkit-print-color-adjust in page CSS when exact colors are needed.
PDF backgrounds are absent printBackground defaults to false. Set printBackground: true.
The PDF ignores CSS page dimensions An API format or dimensions may take priority. Use preferCSSPageSize: true when the CSS @page size should take priority.
Font appearance is unexpected The font may not be ready when PDF generation starts, or the page may render in the background. Keep waitForFonts enabled and, if needed for a background page, call Page.bringToFront().

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. A single GET request can return an image or PDF. The [ScreenshotNeo documentation](https://screenshotneo.com/docs/) describes the API.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Equivalent Python and Node.js requests:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie banners, popups and chat widgets are removed before the shot.
  • Bot checks, blank pages and failed loads are never billed; response headers report the page verdict and billing status.
  • An MCP server lets AI agents use screenshot, page-info and PDF-capture tools.
  • 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000.

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

FAQ

Does Puppeteer return screenshot data or save it to a file?

Both. Provide path to write a file, or omit it to receive image bytes; base64 output can also be requested.

Can Puppeteer make a PDF that uses screen CSS?

Yes. Call page.emulateMediaType('screen') before page.pdf().

Can a PDF contain only selected pages?

Yes. Set pageRanges to a range expression such as 1-5, 8.