Puppeteer Snapshot Options for Capturing a Page
Choose Puppeteer’s screenshot, HTML, accessibility, or PDF snapshot method, then configure scope, format, readiness, and output for your use case.
In Puppeteer, “snapshot” can mean several different outputs. For a rendered page image, use page.screenshot(); for one DOM element, use elementHandle.screenshot(); for serialized markup, use page.content(); for the accessibility tree, use page.accessibility.snapshot(); and for a document, use page.pdf(). A page screenshot captures the viewport by default. Set fullPage: true to request the full page.
This guide covers the practical screenshot options and the other snapshot-like outputs, with runnable examples. The API details cited here come from the Puppeteer reference labeled version 25.12.0; check the matching reference for the version installed in your project.
1. Install Puppeteer and take a page screenshot
The examples use Node.js and Puppeteer. Install the package, save the script below as capture.mjs, and run it with Node. Puppeteer’s screenshot guide demonstrates navigation followed by capture. Choose a readiness condition appropriate to the page; network idle is an example, not a guarantee that every application has finished rendering.
npm install puppeteer
# Save as capture.mjs
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();
}
For a viewport-only capture, omit fullPage or set it to false. The default is false. The screenshot call returns binary image data when no base64 encoding is requested; supplying path writes the result to a file. See the Puppeteer screenshot guide, Page.screenshot() reference, and ScreenshotOptions reference.
2. Choose screenshot scope and options
The main decision is what part of the rendered page you need. The documented options below control the image scope, format, and output behavior.
| Option | Use | Default or caveat |
|---|---|---|
fullPage |
Request a capture of the full page instead of the viewport. | false. |
clip |
Restrict the screenshot to a rectangular page region. | Consult the installed version’s reference for the coordinate shape and interactions with other settings. |
captureBeyondViewport |
Control whether capture can extend beyond the viewport. | Defaults to false without clip, and true when clip is supplied. |
type |
Select the image format. | png. |
quality |
Set lossy-image quality. | 0–100; does not apply to PNG. |
omitBackground |
Hide the default white background for transparency. | false; use a format that supports transparency. |
encoding |
Choose binary or base64 output. | binary; base64 returns a string. |
path |
Save the screenshot to a file. | If omitted, it is not saved to disk. The file extension can determine the type. |
fromSurface |
Capture from the surface rather than the view. | true. |
optimizeForSpeed |
Choose the speed-oriented capture option. | false. |
Viewport, full page, and a clipped region
// Viewport-sized screenshot
await page.screenshot({ path: 'viewport.png' });
// Full-page screenshot
await page.screenshot({ path: 'full-page.png', fullPage: true });
// Rectangular clip: confirm the clip shape and coordinate units
// against the reference for your installed Puppeteer version.
await page.screenshot({
path: 'region.png',
clip: { x: 0, y: 0, width: 800, height: 600 },
captureBeyondViewport: true
});
The reference documents clip as the region selector and the conditional default for captureBeyondViewport. It does not establish every edge-case combination with fullPage; avoid relying on combinations without checking your installed version’s API documentation.
Format, quality, and transparent backgrounds
// Lossy image example. Check supported types in your installed version.
await page.screenshot({ path: 'page.jpeg', type: 'jpeg', quality: 80 });
// Transparent background where the selected format supports it.
await page.screenshot({ path: 'page.png', omitBackground: true });
quality applies to lossy formats and has no effect on PNG. omitBackground: true hides the default white background; whether transparency survives also depends on the chosen format. Use PNG when transparency is required.
Return bytes or base64
const bytes = await page.screenshot();
console.log(bytes.constructor.name); // Uint8Array
const base64 = await page.screenshot({ encoding: 'base64' });
console.log(typeof base64); // string
If you only need a file, pass path. If another process consumes the result in memory, use the returned bytes; choose base64 only when the receiving interface expects a string representation.
3. Capture one element
Use an element handle when you want a particular component instead of a viewport or whole page. Puppeteer scrolls the element into view if needed. Capture can fail if the element has been detached from the DOM before the screenshot completes.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
const element = await page.waitForSelector('main article');
if (!element) throw new Error('Target element was not found');
await element.screenshot({ path: 'article.png' });
} finally {
await browser.close();
}
Use a selector that identifies the intended element uniquely. If a framework replaces that DOM node during rendering, wait for the final state and reacquire the handle immediately before capturing. See ElementHandle.screenshot().
4. Save an HTML snapshot
page.content() returns the page’s full HTML, including the DOCTYPE. This is serialized markup, not a rendered image or a guarantee that external assets and runtime state have been bundled into a portable archive.
import { writeFile } from 'node:fs/promises';
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
const html = await page.content();
await writeFile('page.html', html, 'utf8');
} finally {
await browser.close();
}
For source and caveats, see the Page.content() reference.
5. Capture an accessibility-tree snapshot
The accessibility snapshot represents the browser’s current accessibility tree. It is useful for inspecting accessible structure, but the output is platform-specific and does not promise identical results across operating systems or screen readers. By default, interestingOnly is true and filters out nodes considered uninteresting. Set it to false for the full tree. includeIframes defaults to false; root can scope the snapshot to an element.
import { writeFile } from 'node:fs/promises';
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
const tree = await page.accessibility.snapshot({
interestingOnly: false,
includeIframes: true
});
await writeFile('accessibility-tree.json', JSON.stringify(tree, null, 2));
} finally {
await browser.close();
}
See Accessibility.snapshot() for the options and version-specific API details.
6. Generate a PDF
page.pdf() generates a PDF using print media by default. If you want screen styles, emulate screen media before generating it.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
// Uncomment this when the PDF should use screen media styles.
// await page.emulateMediaType('screen');
await page.pdf({ path: 'page.pdf' });
} finally {
await browser.close();
}
The supplied reference identifies Page.pdf() and print-media behavior; that page is under the “next” API reference, so confirm details against the release you use.
7. Make captures reliable
- Navigate to the intended URL. Choose a navigation readiness condition based on the page’s expected asynchronous work. The Puppeteer guide demonstrates
networkidle2, but no single condition guarantees that every page’s dynamic content is ready. - Wait for application-specific content. If a particular element signals readiness, wait for that selector before capturing. A delay can be appropriate for known animation or deferred rendering, but a fixed delay alone may be brittle.
- Capture the final DOM state. For element screenshots, ensure the target remains attached until capture finishes.
- Use a fresh handle after re-rendering. If the page replaces a node, reacquire the element rather than screenshotting a stale handle.
- Close the browser in a
finallyblock. This ensures the browser is closed even if navigation or capture throws.
These are implementation practices, not performance or reliability benchmarks. The cited official material does not compare speed, image size, cross-browser parity, or capture reliability.
8. Troubleshooting common failures
| Symptom | Likely cause | What to do |
|---|---|---|
| Screenshot only shows the initial viewport. | fullPage is unset or false. |
Set fullPage: true when you need the full page. |
| Element screenshot throws because the element is detached. | The page updated or replaced the node before capture. | Wait for the final UI state, locate the element again, then capture promptly. |
| Element screenshot fails to find a target. | The selector does not match, or the element has not appeared yet. | Check the selector and wait for the relevant element before taking a handle. |
| Clip behavior differs from expectation. | Clip and beyond-viewport settings affect the capture region; version-specific combinations may matter. | Check the installed version’s ScreenshotOptions reference and set captureBeyondViewport explicitly when needed. |
| Expected JPEG output is PNG, or the file is not saved. | The requested type or path was omitted; the extension can determine the type when a path is supplied. | Set the intended type and path, and confirm your installed version’s accepted formats. |
| Quality changes do not affect the file. | quality does not apply to PNG. |
Use a supported lossy format if quality adjustment is needed. |
| Transparent output has a solid background. | The default background was not omitted, or the selected format does not support transparency. | Set omitBackground: true and use a transparency-capable format such as PNG. |
| The capture shows incomplete page content. | The application had not finished its asynchronous rendering when the screenshot ran. | Wait for a page-specific readiness signal, then capture. Treat network-idle waits as a page-dependent choice. |
| PDF uses unexpected styles. | page.pdf() uses print media by default. |
Call page.emulateMediaType('screen') first if screen styles are required. |
| Accessibility output omits nodes. | interestingOnly defaults to true. |
Use interestingOnly: false when the full tree is needed, and check iframe inclusion. |
9. Performance, reliability, and cost considerations
Choose the smallest scope and representation that serves the task: viewport image, full-page image, element image, HTML, accessibility tree, or PDF. PNG ignores the quality setting; a supported lossy format with an appropriate quality may be more suitable when image size matters. The research sources provide no benchmark for capture time or resulting file size, so measure those in your own pages and deployment environment.
For reliability, make readiness conditions specific to the page and guard browser cleanup with try/finally. A full-page or region capture can produce a different scope than a viewport capture, so review the output for the intended downstream use. Keep Puppeteer’s installed version aligned with the API reference you rely on.
Self-hosted Puppeteer has no per-screenshot price stated by the sources used for this article. Your operating cost depends on the infrastructure and workload you choose; no cost or performance figures are asserted here.
10. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. One GET request returns a screenshot or PDF. Its clean-capture flow accepts cookie and consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers say which outcome occurred. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. Plans include 1,000 screenshots a month free with no card; paid plans start at $5 for 3,000.
Install a browser and make a direct request with cURL, Python, or Node.js. Replace YOUR_API_KEY with your key and the target URL as needed. See the ScreenshotNeo API documentation for options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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}`);
It is a practical alternative when you want a screenshot without managing a browser, especially when clean captures, explicit billing verdicts, or an MCP workflow matter. Start free: get 1,000 screenshots a month with no card.
11. Frequently asked questions
Does Puppeteer have a single “snapshot” method?
There are different APIs for image screenshots, serialized HTML, accessibility-tree output, and PDFs. Choose based on the output you need.
Does fullPage: true capture one DOM element?
No. Use an element handle’s screenshot() method for a single element.
Does a screenshot include the page’s original HTML?
A screenshot is rendered pixels. Use page.content() when you need serialized HTML.
Which snapshot is best for accessibility checks?
Use page.accessibility.snapshot() to inspect the browser’s accessibility-tree representation, with the understanding that the API documents platform-specific behavior.


