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.
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
});
formatselects a named paper size. Width and height can be used for custom dimensions when no format takes precedence.landscapeselects landscape orientation; its default is false.marginsets the page margins.pageRangesrestricts which pages are included, using ranges such as1-5, 8, 11-13.printBackgroundincludes backgrounds; it defaults to false.scaledefaults to 1 and accepts values from 0.1 to 2.waitForFontsdefaults to true and waits fordocument.fonts.ready. A background page may needPage.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.


