Playwright screenshot versus page.pdf: which should you use for a web page?
Use Playwright screenshots for visual evidence and PDFs for paginated documents. Learn the output, CSS, and option differences, with runnable examples.
Use page.screenshot() when you need an image of the page as rendered in a browser; use page.pdf() when you need a paginated document for printing or sharing. A screenshot captures the viewport by default, or the full scrollable page as one tall image with fullPage: true. PDF generation uses print CSS by default and has page-size, margin, and pagination controls. These are different deliverables, so neither is universally better.
1. The practical difference: image or paginated document
| Question | page.screenshot() |
page.pdf() |
|---|---|---|
| What do you get? | An image, such as PNG or JPEG | A PDF buffer containing a paginated document |
| Default page extent | The current viewport | Pages laid out for printing |
| Full content | fullPage: true captures the scrollable page in one tall image |
Content flows across PDF pages according to print layout and page settings |
| CSS media | Screen-rendered page | Print media by default; screen media can be emulated first |
| Typical use | Visual inspection, visual comparisons, image previews, or a visual record | Printable, paginated, or document-style sharing |
A full-page screenshot is not a PDF without page breaks: it is one tall image of the scrollable page. Conversely, a PDF is not guaranteed to look exactly like a screenshot, since print styles, pagination, page geometry, and print color handling can change its appearance.
2. Choose the method that matches the deliverable
Choose a screenshot for visual evidence
Use a screenshot for a visual regression artifact, an image preview, or a record of what the browser displayed. The default captures only the visible viewport. Set fullPage: true to include the full scrollable page, or use a clip or element capture when only one region matters.
Choose a PDF for a document
Use page.pdf() when the reader needs page boundaries, paper sizes, margins, or a file suitable for printing. Decide whether the output should follow the site’s print stylesheet or its screen styling. The PDF API supports paper formats and dimensions, margins, page ranges, background graphics, and CSS page-size preference.
Use screen media when the PDF should follow screen CSS
Playwright generates PDFs with print CSS media by default. To use screen CSS for PDF generation, emulate screen media before calling page.pdf(). This changes the media mode; it does not promise pixel-for-pixel identity with a screenshot.
3. Runnable Node.js examples
Install Playwright and its browser binaries using the official Playwright installation guide. Save the following as capture.mjs and run it with Node.js after installation.
Capture the viewport or full page
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
try {
await page.goto('https://example.com', { waitUntil: 'networkidle' });
// Viewport image:
await page.screenshot({ path: 'page.png' });
// Or capture the entire scrollable page as one tall image:
await page.screenshot({ path: 'page-full.png', fullPage: true });
} finally {
await browser.close();
}
Save a paginated PDF
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com', { waitUntil: 'networkidle' });
await page.pdf({
path: 'page.pdf',
format: 'A4',
printBackground: true,
margin: { top: '12mm', right: '12mm', bottom: '12mm', left: '12mm' }
});
} finally {
await browser.close();
}
Save a PDF using screen CSS
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com', { waitUntil: 'networkidle' });
await page.emulateMedia({ media: 'screen' });
await page.pdf({ path: 'page-screen-styles.pdf', format: 'A4', printBackground: true });
} finally {
await browser.close();
}
For a visual comparison that should be reproducible, keep the viewport, browser environment, page state, and capture timing consistent. For a PDF, explicitly set the intended page geometry and print options rather than assuming the browser defaults match your document requirements.
4. Screenshot options that affect the result
The screenshot API exposes controls for the captured region, image format, and pixel scale. Check the Playwright Page API reference for the full option list for your installed version.
| Option | Use | What to consider |
|---|---|---|
fullPage: true |
Capture the full scrollable document in one image | The output can be very tall; it remains a single image, not paginated pages. |
clip |
Capture a specified rectangle | Useful for stable regions or targeted visual checks; ensure the clip is within the rendered page. |
type |
Choose an image format such as PNG or JPEG | Choose based on the image’s intended use and quality needs. |
scale |
Choose CSS-pixel or device-pixel image scaling | CSS scale produces one image pixel per CSS pixel; device scale uses device pixels. A higher pixel count also means a larger output. |
For one element rather than a page region, Playwright’s locator screenshot API can capture that element. See the official screenshot guide for viewport, full-page, buffer, and element capture examples.
5. PDF options that affect the result
PDF options control document geometry and print behavior rather than screenshot framing. Common choices include:
formatfor a paper preset such as A4, orwidthandheightfor explicit dimensions.marginfor the printable page margins.pageRangesto include selected pages.printBackgroundto include background graphics.preferCSSPageSizeto prefer page sizing specified by CSS.page.emulateMedia({ media: 'screen' })before PDF creation when screen CSS should apply.
PDF printing can adjust colors for print by default. If exact CSS colors matter, the API documentation points to the CSS property -webkit-print-color-adjust. Confirm the actual rendered PDF because print styles and pagination can still affect layout.
6. Wait for the page state you intend to capture
Both methods capture the browser state at the time the capture runs. If the page has client-rendered content, images, fonts, or animations still loading, a capture made too early can be incomplete. Navigate using an appropriate load condition, then wait for a meaningful page-specific signal when necessary:
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.locator('main article').waitFor({ state: 'visible' });
await page.screenshot({ path: 'article.png', fullPage: true });
Choose a selector that indicates the content you need, rather than relying on an arbitrary delay where possible. Some sites continue background network requests indefinitely, so networkidle may not be appropriate for every page. If a page uses lazy loading, scroll or otherwise trigger the content before a full-page capture when that content must appear. Keep dynamic content stable when comparing images.
7. Common problems and fixes
| Problem | Likely cause | Fix |
|---|---|---|
| The screenshot shows only the top portion | Viewport capture is the default. | Set fullPage: true, or capture the desired clip or element. |
| The PDF looks different from the browser page | PDF generation uses print CSS by default; print layout, pagination, and color treatment differ. | Use print CSS intentionally, or call page.emulateMedia({ media: 'screen' }) before PDF generation if screen CSS is needed. Inspect page breaks and colors in the resulting PDF. |
| PDF backgrounds or colors are missing or changed | Background graphics may be omitted, and printing adjusts color output. | Set printBackground: true. For exact CSS colors, review -webkit-print-color-adjust and the rendered output. |
| The image is unexpectedly large or small | Viewport dimensions and CSS-pixel versus device-pixel scale affect output dimensions. | Set the viewport deliberately and choose the screenshot scale that matches the consumer’s needs. |
| Content is missing from either artifact | The capture ran before the page or a particular component became ready. | Wait for a meaningful selector or state before capturing; trigger lazy content if required. |
| Full-page image is unwieldy | The page is much taller than the viewport, while full-page capture creates one tall image. | Capture a specific region or element, or choose PDF if the required artifact is a paginated document. |
8. Performance, reliability, and cost considerations
The Playwright documentation does not establish a general speed or memory winner between screenshots and PDFs. The practical workload depends on the page, browser, output dimensions, and document length. A very tall screenshot can create a large image; a long PDF can contain many pages. Choose the output geometry you need and account for its resulting file size and processing needs.
For reliable captures, wait for the content that matters, use a consistent viewport and browser state for image comparisons, and set PDF page and print options explicitly. Recheck outputs when site CSS or content changes. Playwright itself is browser automation software; operating and maintaining the browser environment is part of a self-managed capture workflow.
9. Or skip the browser setup
If you need an image or PDF without running Playwright and maintaining browser setup, ScreenshotNeo is a website screenshot API and MCP server. Its API can return PNG, JPEG, WebP, or PDF; see the ScreenshotNeo API documentation.
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,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(({ writeFile }) => writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));
Cookie banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, timeouts, and failed loads are not billed; response headers report the page verdict and billing status. An MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for free and get 1,000 screenshots a month with no card.
10. FAQ
Can a full-page screenshot be split into pages?
fullPage: true makes a tall image of the scrollable page. Use PDF output when page boundaries and pagination are part of the deliverable.
Does emulating screen media guarantee the PDF matches a screenshot?
No. It selects screen CSS for PDF generation, but PDF page geometry, pagination, and color handling still differ from an image capture.
Which should I use for a visual regression check?
Use a screenshot image, usually at a fixed viewport or for a fixed element. Use full-page capture only when the whole scrollable page is part of the comparison.
Which should I send to someone who needs to print the page?
Use page.pdf(), and set the paper size, margins, print backgrounds, and media mode to suit the intended document.
