Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The Playwright method for taking a screenshot is page.screenshot(). It captures the current page viewport and returns an image buffer; add a path to save the file. For one element, use page.locator(selector).screenshot(). Use fullPage: true when you need the entire scrollable document.

The direct answer: page.screenshot()

Playwright’s Page API provides page.screenshot() for explicit page captures. This minimal example writes a PNG to disk:

import { chromium } from 'playwright';

const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'screenshot.png' });
await browser.close();

With no path, the method returns a buffer instead of creating a file:

const imageBuffer = await page.screenshot();

You can pass that buffer to an image-processing library, upload it, or write it yourself. The supported output formats are PNG, JPEG and WebP. When a path is supplied, Playwright can infer the format from the filename extension; you can also set type explicitly.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The official API reference documents this method at Playwright’s Page API.

Choose the right screenshot method

Need Method or option Result
Capture the visible page page.screenshot() The current viewport; full-page capture is off by default.
Save an image page.screenshot({ path: 'screenshot.png' }) Writes the image to the specified path.
Capture the entire document page.screenshot({ fullPage: true }) Captures all scrollable page content.
Capture one component page.locator('.header').screenshot({ path: 'header.png' }) Captures the area occupied by the matched locator.
Capture a rectangle page.screenshot({ clip: { x, y, width, height } }) Restricts the output to page coordinates.
Process image data in memory const buffer = await page.screenshot() Returns image bytes without saving a file.

Capture a viewport screenshot

A normal call captures what is currently inside the browser viewport. Set the viewport when you need repeatable dimensions:

const page = await browser.newPage({
  viewport: { width: 1440, height: 900 },
  deviceScaleFactor: 1
});
await page.goto('https://example.com', { waitUntil: 'networkidle' });
await page.screenshot({ path: 'viewport.webp', type: 'webp', quality: 85 });

deviceScaleFactor controls device-pixel output. A scale of 1 produces one image pixel per CSS pixel; higher values produce a denser, retina-style image. The exact dimensions and loading state matter when comparing screenshots, so set them deliberately rather than relying on defaults.

Take a full-page screenshot

Use the fullPage option for content below the fold:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.screenshot({
  path: 'full-page.png',
  fullPage: true
});

Playwright scrolls and assembles the page’s scrollable content. Pages that lazy-load images may need an explicit scroll or a wait for the images before capture. A full-page image can also become very large; choose JPEG or WebP, reduce the scale, or capture sections if the resulting file is too big.

Capture a specific element with a locator

For a component, card, chart or header, prefer the locator API:

await page.locator('.header').screenshot({ path: 'header.png' });
await page.getByRole('button', { name: 'Buy now' }).screenshot({ path: 'buy-button.png' });

locator.screenshot() performs actionability checks and scrolls the matched element into view. This is generally safer than querying an element handle directly. The ElementHandle API marks elementHandle.screenshot() as discouraged and recommends locator-based screenshots; see the Locator API and ElementHandle API.

If the target is covered by another element, the covered area will not become visible merely because it matched a selector. For a scrollable element, the screenshot contains the content currently visible inside that element, not every possible scroll position.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Control format, quality and transparency

PNG, JPEG and WebP

await page.screenshot({ path: 'image.jpeg', type: 'jpeg', quality: 80 });
await page.screenshot({ path: 'image.webp', type: 'webp', quality: 80 });
await page.screenshot({ path: 'image.png', type: 'png' });

Quality applies to JPEG and WebP, not PNG. PNG is lossless and useful for text-heavy visual tests; JPEG and WebP can reduce transfer and storage size.

CSS pixels versus device pixels

The scale screenshot option can produce output at device-pixel scale or CSS-pixel scale. Use CSS scale when stable, predictable dimensions matter; use device scale when you need a high-density image for a display.

Animations and backgrounds

Screenshot options include animation handling, masking and background behavior. Setting animations: 'disabled' helps visual comparisons by stopping CSS animations and transitions. mask can cover changing regions, while omitBackground: true can preserve transparency where the page supports it. Use these options consistently in both baseline and comparison runs.

Clip a rectangle

await page.screenshot({
  path: 'chart-area.png',
  clip: { x: 120, y: 180, width: 640, height: 360 }
});

The rectangle is expressed in page coordinates. A clip is useful when a selector is unavailable, but a locator is usually more resilient to layout changes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Make captures deterministic

A screenshot records the rendered state at one moment. Stabilize that state before calling the method:

  1. Navigate and wait for the page’s required content, preferably with a targeted locator rather than an arbitrary long delay.
  2. Set a fixed viewport, device scale and color scheme when those values affect layout.
  3. Wait for fonts, images or application data that the screenshot must contain.
  4. Disable or mask animations, timestamps, rotating banners and other changing regions.
  5. Use a consistent locale, timezone and test account when text or formatting can vary.
await page.goto('https://example.com/dashboard');
await page.getByRole('heading', { name: 'Dashboard' }).waitFor();
await page.screenshot({
  path: 'dashboard.png',
  animations: 'disabled',
  fullPage: true
});

A very broad waitUntil: 'networkidle' can be inappropriate for applications that keep analytics or WebSocket connections open. Waiting for the content that proves the page is ready is often more reliable.

Playwright Test screenshots and visual assertions

There are two related but different features. In ordinary browser code, call page.screenshot() yourself. In Playwright Test, the use.screenshot setting can capture test artifacts automatically with modes such as on, only-on-failure and on-first-failure. Configure it in the test runner:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    screenshot: 'only-on-failure'
  }
});

Visual assertions are a separate test-runner facility:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { test, expect } from '@playwright/test';

test('homepage stays visually stable', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot('homepage.png');
});

toHaveScreenshot() waits for consecutive screenshots to stabilize before comparing them. It is intended for regression testing, whereas a direct screenshot call is the method to use when your application needs an image file or buffer. See the TestOptions API and PageAssertions API.

Complete runnable example with common options

import { chromium } from 'playwright';

const browser = await chromium.launch();
const page = await browser.newPage({
  viewport: { width: 1280, height: 800 },
  deviceScaleFactor: 1
});

try {
  await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
  await page.locator('h1').waitFor();

  await page.screenshot({
    path: 'example-full.webp',
    fullPage: true,
    type: 'webp',
    quality: 85,
    animations: 'disabled'
  });

  const headingBuffer = await page.locator('h1').screenshot();
  console.log(`Heading bytes: ${headingBuffer.length}`);
} finally {
  await browser.close();
}

Install Playwright with your project’s package manager, install the browser binaries, and run the file as an ES module. Keep the browser in a finally block so failures do not leave processes running.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting screenshot failures

The file is blank or missing content

Cause: the capture ran before the application rendered, or the page is blocked behind a login or consent dialog. Fix: wait for a meaningful locator, authenticate before navigation, and handle required dialogs. For lazy content, scroll or wait for the relevant image or section before using fullPage.

The screenshot is only the viewport

Cause: fullPage defaults to false. Fix: pass fullPage: true, or capture individual sections when one very tall image is impractical.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A locator screenshot times out

Cause: the selector matches nothing, the element is hidden, or actionability checks never complete. Fix: use a stable role, label or test identifier; wait for the locator; confirm the element is visible; and inspect whether an overlay covers it.

The image changes between runs

Cause: animations, fonts, network data, time, locale or rotating content differ. Fix: control those inputs, disable animations, wait for the exact ready state and mask genuinely dynamic regions.

The output format or quality is wrong

Cause: the extension and type disagree, or quality was applied to PNG. Fix: choose one of PNG, JPEG or WebP, keep the filename consistent, and remember that quality affects only JPEG and WebP.

The capture is unexpectedly huge

Cause: full-page output combined with a large viewport or device scale. Fix: use CSS-pixel scale, lower the device scale, choose WebP or JPEG, clip the required region, or divide the page into sections.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Or skip the browser setup

If you need an HTTP endpoint rather than a Playwright runtime, ScreenshotNeo takes a URL and returns a PNG, JPEG, WebP or PDF. It removes cookie and consent banners, newsletter popups and chat widgets before capture; bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.

One-call cURL example (see the ScreenshotNeo documentation):

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}`);

Every plan includes the same feature set, including full-page and element capture, device presets, custom CSS and JavaScript, waits, blocking controls, headers and cookies, geolocation, resizing, caching, signed links, asynchronous webhooks, bulk capture and a usage API. The Free plan includes 1,000 screenshots each month without a card; paid plans start at $5 for 3,000. Sign up for the free ScreenshotNeo plan.

Frequently Asked Questions

Does Playwright use a separate screenshot class?

No. The primary page method is page.screenshot(); element captures use locator.screenshot().

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What does Playwright return when no path is supplied?

It returns a buffer containing the captured image, which you can process or upload in memory.

Is page.screenshot() the same as toHaveScreenshot()?

No. page.screenshot() creates an image directly. toHaveScreenshot() is a Playwright Test visual assertion that compares stabilized screenshots.

The Bottom Line

Use await page.screenshot() for a page, add path to save it, set fullPage: true for the complete document, and use locator.screenshot() for a specific element.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.