Use Playwright’s page.screenshot() method to capture the current viewport, the full scrollable document, or a clipped rectangle. Use locator.screenshot() for one element. The method can write an image to disk and also returns the image bytes, so the same capture can be uploaded, processed, or compared in memory.
This guide shows runnable JavaScript examples, deterministic-capture techniques, Playwright Test settings and visual assertions, output-format choices, failure fixes, and an API alternative when you do not want to maintain browser automation.
Install Playwright and create a page
Install the library in your project, then install at least one supported browser.
npm install -D playwright
npx playwright install chromium
A minimal script launches Chromium, opens a URL, saves a screenshot, and closes the browser:
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 problems#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.goto('https://example.com', { waitUntil: 'networkidle' });
await page.screenshot({ path: 'example.png' });
await browser.close();
})();
path writes the file. Without path, page.screenshot() returns a Buffer containing the image.
Capture the visible viewport
The default is a screenshot of the viewport currently visible in the page. Set the viewport before navigation when exact dimensions matter.
await page.setViewportSize({ width: 1280, height: 720 });
await page.goto('https://example.com');
await page.screenshot({ path: 'viewport.png' });
The resulting image represents the visible browser area, not content below the fold. A page’s responsive layout, device scale factor, and loaded fonts can change the pixels, so define those inputs deliberately for repeatable output.
Capture the full scrollable page
Pass fullPage: true to capture the entire scrollable document rather than only the viewport.
await page.goto('https://example.com');
await page.screenshot({ path: 'full-page.png', fullPage: true });
This is useful for documentation, previews and archival images. It is not the same as scrolling a user-visible viewport and taking one frame: Playwright produces an image covering the page’s scrollable height. Lazy-loaded content may still need to be triggered first.
Make lazy content appear
Wait for a known section, scroll through the page, or use an application-specific readiness signal before capturing.
await page.goto('https://example.com/catalog');
await page.locator('.product-grid').waitFor();
await page.evaluate(async () => {
await new Promise(resolve => {
let last = 0;
const timer = setInterval(() => {
window.scrollBy(0, 600);
const now = document.documentElement.scrollTop;
if (now === last || now + innerHeight >= document.documentElement.scrollHeight) {
clearInterval(timer);
window.scrollTo(0, 0);
resolve();
}
last = now;
}, 100);
});
});
await page.screenshot({ path: 'catalog-full.png', fullPage: true });
Prefer a deterministic application signal over a fixed delay when possible; network responses, font loading and client-side rendering can otherwise finish at different times.
Capture a rectangle with clip
Use clip when you need coordinates rather than a DOM element. The rectangle is expressed in page coordinates with x, y, width and height.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
await page.goto('https://example.com');
await page.screenshot({
path: 'hero-region.png',
clip: { x: 0, y: 120, width: 900, height: 420 }
});
Coordinates are sensitive to viewport size, responsive breakpoints and page layout. For a component that has a stable selector, an element screenshot is usually less fragile.
Capture one element with a locator
Use locator.screenshot() for current element-based code. Playwright waits for the locator’s actionability checks and scrolls the element into view before capturing it.
await page.goto('https://example.com');
const header = page.locator('header');
await header.screenshot({ path: 'header.png' });
A covered element may not appear as you expect because an overlay can obscure it. For a scrollable container, the screenshot contains the content currently visible inside that container, not automatically every item hidden behind its internal scroll position.
Element screenshots versus discouraged handles
Locator screenshots remain tied to a selector and Playwright’s waiting behavior. The API reference marks ElementHandle.screenshot() as discouraged; use a locator instead:
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →await page.locator('[data-testid="invoice"]').screenshot({ path: 'invoice.png' });
Choose PNG, JPEG, WebP and pixel scale
PNG is the default and preserves lossless detail. JPEG and WebP can reduce file size; the quality option applies to those formats, not PNG. The documented JPEG default quality is 80. WebP quality 100 is lossless, while lower values are lossy.
await page.screenshot({ path: 'card.webp', type: 'webp', quality: 85 });
await page.screenshot({ path: 'photo.jpg', type: 'jpeg', quality: 80 });
Set omitBackground: true for transparency when using a format that supports it. It does not apply to JPEG.
await page.screenshot({ path: 'logo.png', omitBackground: true });
scale: 'css' creates roughly one image pixel per CSS pixel, keeping high-DPI files smaller. scale: 'device' produces device-pixel output, which can be twice as large or more on a high-density display.
await page.screenshot({ path: 'css-scale.png', scale: 'css' });
await page.screenshot({ path: 'device-scale.png', scale: 'device' });
Make screenshots repeatable
A screenshot is only as stable as the page state behind it. Set the browser engine, viewport, locale, timezone, authentication state and test data intentionally. Then use screenshot controls for known sources of variation.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
Disable animation and hide the caret
await page.screenshot({
path: 'stable.png',
animations: 'disabled',
caret: 'hide'
});
With animations disabled, Playwright fast-forwards finite animations to completion and cancels infinite animations at their initial state for the capture, then resumes them. caret: 'hide' is the default, but specifying it documents the intent.
Mask changing or sensitive regions
Pass locators in mask to cover variable content. Masks cover each matched element’s bounding box, including invisible matched elements; maskColor changes the overlay color.
await page.screenshot({
path: 'masked.png',
mask: [page.locator('.timestamp'), page.locator('.avatar')],
maskColor: '#777'
});
maskColor is documented from Playwright v1.35. Check the documentation for your installed release before relying on version-specific options.
Inject capture-only CSS
The style option applies a stylesheet only during the screenshot. It can hide rotating banners or normalize a component. The documented behavior pierces Shadow DOM and applies to inner frames.
Recommended Free Tools
await page.screenshot({
path: 'no-cookie-banner.png',
style: `
.cookie-banner, .chat-widget { display: none !important; }
* { caret-color: transparent !important; }
`
});
Style and animation controls do not make every page deterministic. Network-loaded data, fonts, browser engine, viewport and application state can still differ. Establish the state first, and mask or style only the regions that should not participate in the image.
Version-sensitive options
The official reference labels screenshot style as added in v1.41 and signal in v1.62. Playwright Test’s reducedMotion setting is documented from v1.50. Verify the version installed in your project before using these options.
Use screenshots in Playwright Test
Playwright Test can save screenshots automatically. In the configuration, use.screenshot defaults to 'off'. It also accepts 'on', 'only-on-failure' and 'on-first-failure', plus options such as fullPage and omitBackground.
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
screenshot: 'only-on-failure',
viewport: { width: 1280, height: 720 }
}
});
Use 'only-on-failure' when you want diagnostic artifacts without writing an image for every passing test. Use 'on' when every test needs an artifact.
Compare images with toHaveScreenshot()
A file capture and a visual assertion have different purposes. page.screenshot() creates an image. expect(page).toHaveScreenshot() compares the current rendering with a stored expectation and is available with the Playwright test runner.
Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
import { test, expect } from '@playwright/test';
test('home page matches its visual baseline', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveScreenshot('home.png', {
fullPage: true,
animations: 'disabled',
maxDiffPixelRatio: 0.01
});
});
The assertion waits until two consecutive screenshots are identical, then compares the last image with the expected snapshot. Set tolerances such as maxDiffPixels or maxDiffPixelRatio deliberately: an overly broad tolerance can hide a real regression. A locator can be asserted similarly:
await expect(page.locator('.checkout-summary')).toHaveScreenshot('summary.png');
Capture bytes instead of writing a file
Omit path and keep the returned buffer for an upload, hash, or in-memory transform.
const image = await page.screenshot({ type: 'png' });
console.log(`captured ${image.length} bytes`);
// Example: await storage.put('runs/home.png', image);
This avoids temporary files in serverless jobs and lets your application decide where the artifact belongs.
Common failures and fixes
The image stops at the viewport
Cause: fullPage was omitted or false. Fix: pass fullPage: true. If content is still missing, trigger lazy loading and wait for the relevant section before capture.
A locator screenshot times out
Cause: the selector matches nothing, the element is not actionable, or navigation has not reached the expected state. Fix: use a stable test ID, call locator.waitFor(), and verify the URL and application readiness signal.
The element is hidden behind a popup
Cause: a consent dialog, modal or chat widget covers the target. Fix: close it through the same UI path a user would, wait for it to disappear, or use capture-only CSS when hiding it is part of the intended artifact.
Full-page output contains blank or stale sections
Cause: lazy images, web fonts or client rendering finished after the capture. Fix: wait for a meaningful selector or network/application signal, scroll to activate lazy content, and ensure fonts and data are loaded before calling screenshot().
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, 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 minuteVisual tests fail on harmless pixels
Cause: animation, timestamps, ads, random data, fonts or a changed browser/viewport. Fix: freeze test data, disable animations, mask dynamic regions, define the viewport and browser consistently, and use a narrow diff tolerance only after identifying the source of variation.
Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
The file is unexpectedly large
Cause: device-pixel scale or lossless PNG output. Fix: try scale: 'css', WebP with an appropriate quality, or JPEG for photographic content. Keep PNG for sharp text, diagrams and transparency.
An option is rejected as unknown
Cause: the project uses an older Playwright release. Fix: check the installed version and consult that release’s API reference before depending on options such as style, maskColor or signal.
Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP or PDF, so you do not need to install Playwright browsers for a straightforward URL capture.
Free tools Windows power users keep installed
One-click scans. No signup required.
Use the API documentation at https://screenshotneo.com/docs/ for authentication and options. This cURL example saves a WebP:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
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)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Before capture, ScreenshotNeo accepts cookie and consent banners and removes more than 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 are not billed, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Other options include full-page and element capture, dark mode, device presets, retina scale, PDF controls, custom CSS and JavaScript, clicks, waits, blocking, headers, cookies, user agent, timezone, geolocation, resizing, chosen cache TTL, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage data and an OpenAPI specification.
Create a free ScreenshotNeo account to use the 1,000 monthly screenshots without a card.
Frequently Asked Questions
Can Playwright take a screenshot without saving a file?
Yes. Omit the path option; page.screenshot() returns a Buffer that you can upload or process in memory.
Which method should I use for a component?
Use locator.screenshot() with a stable selector. It waits for the element and scrolls it into view, unlike a coordinate clip that depends on layout.
Does toHaveScreenshot() work in a plain Playwright script?
No. It is a Playwright Test visual assertion and compares the rendering with a stored expectation; use page.screenshot() for ordinary file or buffer capture.
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.

