Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Use await page.screenshot(options) for ordinary captures. Set fullPage: true for the entire scrollable document, clip for a rectangle, and mask for locator-selected content. For stable output, disable animations, hide the caret, normalize dynamic styles, and choose scale: 'css' or 'device' deliberately. Playwright Test’s toHaveScreenshot() adds snapshot comparison and has different animation defaults.
The screenshot option model
Playwright’s page API is intentionally composable: scope the capture, make it deterministic, then choose output encoding and file behavior. The core call is:
await page.screenshot({ path: 'dashboard.png' });
If path is supplied, Playwright infers the image format from its extension. You can also set type explicitly to png, jpeg, or webp. The following table collects the options that matter most in production scripts and visual-regression suites.
| Option | What it controls | Important default or constraint |
|---|---|---|
path |
Destination filename | Extension determines format when a path is used |
type |
PNG, JPEG, or WebP encoding | Use with quality for JPEG/WebP |
quality |
Compression quality | 0–100; ignored for PNG |
fullPage |
Viewport versus complete scrollable page | false by default |
clip |
Rectangular output region | { x, y, width, height } |
mask |
Locator regions covered in the image | Masking uses locator bounding boxes |
maskColor |
Overlay color for masks | #FF00FF by default; available from v1.35 |
omitBackground |
Transparent background | Works for PNG/WebP, not JPEG |
scale |
Output pixel density | device is the page-screenshot default |
animations |
CSS and Web Animations behavior | allow for page screenshots |
caret |
Text-caret visibility | hide by default |
style |
Stylesheet text applied during capture | Pierces Shadow DOM and inner frames; available from v1.41 |
timeout |
Maximum screenshot wait | 0 (no timeout) for page screenshots |
signal |
Abort cancellation | Available from v1.62 |
Capture a viewport or the entire page
Viewport screenshot
With no scope option, Playwright captures the currently visible viewport. This is useful when the viewport itself is the test subject, such as a responsive breakpoint.
#1 Best Overall
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.goto('https://example.com');
await page.screenshot({ path: 'viewport.png', type: 'png' });
await browser.close();
Full scrollable-page screenshot
Set fullPage: true to capture the full scrollable page rather than only what is visible. This is the direct answer to “How do I take a full-page screenshot in Playwright?”:
await page.screenshot({
path: 'full-page.webp',
fullPage: true,
type: 'webp',
quality: 85
});
Full-page capture does not make dynamic content deterministic by itself. Lazy images, carousels, clocks, and animated banners can still change while the page is being rendered; combine it with the stability techniques below.
Capture an element or rectangle
Element bounding box to clip
The screenshot API clips rectangles, not locators directly. Resolve the element’s bounding box and pass its coordinates to clip. A missing box usually means the element is detached, not rendered, or otherwise unavailable, so fail explicitly instead of writing a misleading image.
const card = page.locator('[data-testid="pricing-card"]');
await card.waitFor();
const box = await card.boundingBox();
if (!box) throw new Error('pricing-card has no visible bounding box');
await page.screenshot({
path: 'pricing-card.png',
clip: box,
animations: 'disabled'
});
Explicit coordinates
For a fixed region, provide x, y, width, and height directly. Coordinates are page coordinates in CSS pixels before output scaling.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →await page.screenshot({
path: 'hero-region.png',
clip: { x: 40, y: 120, width: 960, height: 540 },
scale: 'css'
});
Keep the rectangle inside the rendered page and account for sticky headers or scrolling when choosing coordinates. If the target is a DOM element, a fresh bounding box is safer than hard-coded numbers across responsive layouts.
Make captures deterministic
Disable animations and transitions
animations: 'disabled' stops CSS animations, CSS transitions, and Web Animations. Finite animations are fast-forwarded to completion; infinite animations are canceled to their initial state during capture and resumed afterward.
await page.screenshot({
path: 'stable.png',
fullPage: true,
animations: 'disabled',
caret: 'hide'
});
The direct page API defaults to animations: 'allow', so set the option whenever motion could affect pixels. The caret defaults to hidden; keep that default unless a text-editing state is what you are documenting.
Mask volatile or private data
Use mask with locators to cover user names, timestamps, rotating ads, or other content that should not appear in a baseline. The mask covers each locator’s bounding box. Invisible elements are also eligible, so make the locator strategy visibility-aware when that distinction matters.
await page.screenshot({
path: 'account-baseline.png',
mask: [
page.locator('[data-testid="user-name"]'),
page.locator('.last-updated')
],
maskColor: '#222222'
});
maskColor was added in Playwright v1.35 and defaults to bright pink (#FF00FF). Choose a neutral color if the image is customer-facing, but remember that the covered pixels are intentionally not evidence of the underlying value.
Rank #2
Inject capture-only CSS
The style option accepts stylesheet text applied only while the screenshot is taken. It pierces Shadow DOM and inner frames, which makes it useful for hiding clocks, blinking cursors, or third-party widgets that you cannot conveniently address in page code.
await page.screenshot({
path: 'normalized.png',
style: `
[data-volatile], .live-chat, .cursor { visibility: hidden !important; }
*, *::before, *::after { animation: none !important; transition: none !important; }
`,
animations: 'disabled'
});
The screenshot stylesheet option was added in v1.41. Verify the Playwright version in the package and CI image before putting it in a shared helper.
Choose pixels, format, and file size
css versus device scale
scale: 'css' produces one output pixel per CSS pixel, so a 1440-CSS-pixel viewport remains 1440 pixels wide even on a high-DPI display. scale: 'device' uses device pixels and is the default for page.screenshot(); on a retina context it creates a larger, denser image. Use CSS scale for compact, comparable baselines and device scale when preserving physical display detail is more important.
Free tools Windows power users keep installed
One-click scans. No signup required.
PNG, JPEG, and WebP
- PNG: lossless and suitable for text-heavy regression baselines. The
qualityoption has no effect. - JPEG: smaller files for photographic content, but no transparent background. Set
qualityfrom 0 to 100. - WebP: supports quality control and can retain transparency when
omitBackground: trueis used.
await page.screenshot({
path: 'logo.webp',
type: 'webp',
quality: 90,
omitBackground: true,
scale: 'css'
});
omitBackground: true removes the default white background for transparent PNG or WebP output. It does not provide transparent JPEG output.
Use screenshots in Playwright Test visual assertions
expect(page).toHaveScreenshot() is a Playwright Test assertion, not merely a file-saving call. It waits until two consecutive screenshots match and then compares the result with the expected snapshot. Shared capture controls such as fullPage, clip, mask, style, scale, and omitBackground can be used with the assertion.
import { test, expect } from '@playwright/test';
test('checkout is stable', async ({ page }) => {
await page.goto('https://example.com/checkout');
await expect(page).toHaveScreenshot('checkout.png', {
fullPage: true,
animations: 'disabled',
style: '.live-chat, [data-clock] { visibility: hidden !important; }',
maxDiffPixels: 100,
maxDiffPixelRatio: 0.001,
threshold: 0.2
});
});
Assertions default to animations: 'disabled', unlike direct page screenshots. maxDiffPixels permits an absolute number of changed pixels, maxDiffPixelRatio expresses the allowance as a proportion, and threshold controls per-pixel comparison sensitivity. Set the smallest tolerances that reflect real rendering variation; broad thresholds can hide regressions.
For a maintainable suite, put normalization rules in the assertion stylesheet (or stylePath, available from v1.41), mask user-specific regions, and keep viewport, browser, and scale consistent across baseline and comparison runs.
Recommended Free Tools
Rank #3
Timeouts, cancellation, and version compatibility
Timeout behavior
Page screenshots have a default timeout of 0, meaning no screenshot-specific timeout. Set timeout when a hung page must fail within a bounded interval:
await page.screenshot({
path: 'bounded.png',
fullPage: true,
timeout: 30_000
});
This does not replace navigation or locator waits; make sure the page has reached the state you intend to capture before calling the screenshot API.
Abort a capture
The signal option accepts an AbortSignal and was added in v1.62. It lets a job manager cancel work that has exceeded a larger application-level deadline.
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 20_000);
try {
await page.screenshot({ path: 'cancelable.png', signal: controller.signal });
} finally {
clearTimeout(timer);
}
Because maskColor, style/stylePath, and signal arrived in different releases, check the installed Playwright version before sharing option objects between local development and CI.
Practical recipes and decision guide
- Document page:
fullPage: true, usually withanimations: 'disabled'and a capture stylesheet. - Component handoff: resolve a locator’s
boundingBox(), then pass the result toclip. - Privacy-safe baseline: mask volatile locators and hide remaining dynamic selectors with
style. - Small, portable files:
scale: 'css'plus WebP quality control. - Pixel-perfect high-DPI evidence: retain
scale: 'device'and use PNG when compression artifacts would matter. - Regression testing: use
toHaveScreenshot(), normalize motion, and set explicit diff limits.
Troubleshooting common failures
The image is only the visible viewport
Cause: fullPage is false by default. Fix: pass fullPage: true; if you need only one region, use a measured clip instead.
An element clip throws or produces the wrong area
Cause: the locator has no bounding box, the layout changed, or coordinates were measured before the component rendered. Fix: wait for the locator, call boundingBox() immediately before capture, reject a null box, and avoid hard-coded coordinates for responsive components.
Visual tests fail intermittently
Cause: animations, transitions, carets, clocks, ads, or personalized data differ between runs. Fix: disable animations, hide or mask dynamic regions, inject a normalization stylesheet, and keep scale and viewport fixed. Remember that assertion screenshots already disable animations by default, while direct screenshots do not.
Rank #4
- Used Book in Good Condition
Masked content still appears
Cause: the locator selected a different node, or an invisible matching node was masked while the visible node was not. Fix: inspect the locator, make visibility part of the locator strategy, and verify the element’s bounding box.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Transparent output is white
Cause: omitBackground was omitted or JPEG was selected. Fix: use PNG or WebP with omitBackground: true.
Images are unexpectedly huge
Cause: scale: 'device' preserves high-DPI pixels. Fix: choose scale: 'css' for one output pixel per CSS pixel, or use JPEG/WebP quality controls when their encoding trade-offs are acceptable.
A newer option is rejected
Cause: the installed Playwright release predates the option. Fix: check the version in the runtime and CI image; maskColor requires v1.35 or newer, style/stylePath v1.41 or newer, and signal v1.62 or newer.
Or skip the browser setup
If you need a URL rendered without maintaining a Playwright browser, ScreenshotNeo provides a website screenshot API and MCP server. It accepts a consent banner like a visitor, removes more than 60 known consent platforms plus newsletter popups and chat widgets, and lets each cleanup step be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; response headers identify the page verdict and whether the shot was billed.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsOne GET request returns PNG, JPEG, WebP, or PDF. The full option set includes full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, PDF paper and margin controls, custom CSS and JavaScript, pre-capture clicks, hidden selectors, selector/delay/network-idle waits, request and resource blocking, custom headers/cookies/user agents/Authorization, timezone and geolocation, transparent backgrounds, resizing, user-selected cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, usage reporting, and an OpenAPI specification. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
See the ScreenshotNeo documentation for parameter details. The same request can be made from cURL, Python, or Node.js:
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}`);
The Free plan includes 1,000 shots per month with no card. Paid plans are Starter ($5 for 3,000), Growth ($15 for 15,000), Pro ($39 for 60,000), Scale ($99 for 250,000), and Business ($249 for 1,000,000); yearly billing gives two months free, and every feature is included on every plan. Create a free ScreenshotNeo account to start without a card.
Best Value
FAQ
Can a screenshot be canceled after it starts?
Yes. On Playwright versions that support it, pass an AbortSignal through signal and abort the controller from your job deadline or shutdown handler.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallDoes masking alter the page itself?
No. Masking covers locator bounding boxes in the captured image; it is a screenshot-time overlay and does not modify page state.
Why do direct screenshots and visual assertions behave differently with motion?
The direct page API allows animations by default, whereas toHaveScreenshot() disables them while it obtains comparable screenshots. Set the option explicitly in shared helpers when you use both workflows.
Frequently Asked Questions
Can a screenshot be canceled after it starts?
Yes. On Playwright versions that support it, pass an AbortSignal through signal and abort the controller from your job deadline or shutdown handler.
Does masking alter the page itself?
No. Masking covers locator bounding boxes in the captured image; it is a screenshot-time overlay and does not modify page state.
Why do direct screenshots and visual assertions behave differently with motion?
The direct page API allows animations by default, whereas toHaveScreenshot() disables them while it obtains comparable screenshots. Set the option explicitly in shared helpers when you use both workflows.
Quick Recap
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.




