ScreenshotNeo

BlogHow-to

How to Capture a Playwright Screenshot with a CSS Clip Rectangle

Use Playwright’s page.screenshot({ clip }) to save a rectangular page region. Learn how coordinates, pixel scale, output formats, and alternatives work.

By the ScreenshotNeo team4 October 20267 min read

Use page.screenshot({ clip }) to capture a rectangular region of a Playwright page. The rectangle has numeric x, y, width, and height fields. To make its dimensions correspond to CSS pixels in the output, set scale: 'css' explicitly:

await page.screenshot({
  path: 'clip.png',
  clip: { x: 100, y: 80, width: 400, height: 250 },
  scale: 'css',
});

This saves a 400-by-250 CSS-pixel region starting at page coordinate (100, 80). Without a path, Playwright returns an image buffer. See the official Playwright Page API and ScreenshotNeo API documentation.

1. Set up a runnable Playwright script

The following Node.js example launches Chromium, navigates to a page, waits for a target selector, captures a rectangular region, and closes the browser even if capture fails.

// capture-clip.js
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  try {
    const page = await browser.newPage({ viewport: { width: 1280, height: 900 } });
    await page.goto('https://example.com', { waitUntil: 'load' });
    await page.locator('h1').waitFor({ state: 'visible' });

    const clip = { x: 100, y: 80, width: 400, height: 250 };
    await page.screenshot({ path: 'clip.png', clip, scale: 'css' });
  } finally {
    await browser.close();
  }
})();

Install Playwright and its Chromium browser in your project using the commands for your package manager. For npm:

npm install playwright
npx playwright install chromium
node capture-clip.js

For applications that already have a page, only the page.screenshot() call and any needed readiness checks are required.

2. Understand the clip rectangle and pixel scale

Option Meaning Practical guidance
x Horizontal coordinate of the rectangle’s top-left corner. Use the page coordinate system; the value is not the rectangle’s right edge.
y Vertical coordinate of the rectangle’s top-left corner. Use the page coordinate system; the value is not the rectangle’s bottom edge.
width Rectangle width. Specify a positive numeric dimension.
height Rectangle height. Specify a positive numeric dimension.
scale Output pixel scaling: 'css' or 'device'. Choose 'css' for one output pixel per CSS pixel. The Page API defaults to 'device'.

The clip option defines the crop rectangle. It does not itself select a “CSS mode”; scale separately determines output pixel scale. With device scale, a high-DPI page can produce more output pixels than the CSS dimensions suggest. Use scale: 'css' when downstream comparisons, storage, or display expect dimensions in CSS pixels.

For a buffer instead of a file, omit path and handle the returned bytes:

const imageBuffer = await page.screenshot({
  clip: { x: 100, y: 80, width: 400, height: 250 },
  scale: 'css',
});
// imageBuffer is a Node.js Buffer.

3. Pick the right screenshot API

Need Use What it captures
An arbitrary rectangular page region page.screenshot({ clip }) The specified rectangle.
The entire scrollable page page.screenshot({ fullPage: true }) A full-page screenshot rather than just the visible viewport.
One specific element locator.screenshot() The locator’s element, scrolling it into view as needed.
A visual regression check expect(page).toHaveScreenshot({ clip }) A clipped screenshot compared with a stored expectation by Playwright Test.

These options address different targets and jobs. The Page API documents clip and fullPage as separate options; check the installed Playwright version before relying on a particular result from combining them. For element screenshots, prefer locator-based capture over the discouraged ElementHandle screenshot method. A locator screenshot waits for actionability and scrolls the element into view; covered content is still covered, and a scrollable element shows only its currently scrolled content. See the ElementHandle API.

For assertions, toHaveScreenshot({ clip }) is provided by Playwright Test, not the standalone page screenshot call. It waits for two consecutive screenshots to match before comparing the capture with the expectation. Screenshot assertions default to disabled animations, while a direct Page screenshot defaults to allowing animations. See the PageAssertions API.

4. Choose file type and useful capture options

Playwright’s direct screenshot output supports PNG, JPEG, and WebP. PNG is the default. When a path is supplied, Playwright can infer the type from its extension; otherwise, set type explicitly if you need a specific format.

await page.screenshot({
  path: 'clip.webp',
  type: 'webp',
  quality: 85,
  clip: { x: 100, y: 80, width: 400, height: 250 },
  scale: 'css',
});

Quality applies to lossy image output. The documented JPEG default is 80; WebP quality 100 is lossless, while lower WebP quality is lossy. For consistent visual output, also consider these options:

  • animations: 'disabled' stops CSS animations and transitions; finite and infinite animations are handled differently. A direct Page screenshot otherwise defaults to 'allow'.
  • caret: 'hide' is the default, so a text caret does not appear in the screenshot.
  • style can apply a stylesheet for the capture. This can help make a known page state easier to reproduce.
  • mask can cover matching locators when dynamic content should not affect a capture.

Check the current Page API option definitions for supported values and version-specific details.

5. Make captures repeatable

  1. Set the viewport deliberately. Viewport size can affect responsive layout and therefore what falls within a page-coordinate rectangle.
  2. Wait for the state you need. Navigate, then wait for a meaningful selector or application-specific ready condition before capturing. A successful navigation alone may not mean asynchronous content is ready.
  3. Keep the rectangle stable. If the page layout shifts between runs, the same coordinates can select different content. Wait for fonts, images, or app data that affect the target region when those matter to your capture.
  4. Control visual motion. Disable animations for repeatable snapshots when motion is not part of the desired result.
  5. Use the right purpose-specific method. For an element, use its locator; for a baseline comparison, use Playwright Test’s screenshot assertion.

Large captures and device-pixel output can produce larger image files and require more memory to handle than a small CSS-scale crop. A clip is useful when you need only a region. Playwright runs a browser locally or in your chosen execution environment; runtime and reliability depend on that environment, the page, and its network requests. No fixed capture time or cost applies to every setup.

6. Troubleshoot common problems

Symptom Likely cause Fix
Output dimensions are larger than expected. The Page screenshot default is scale: 'device', so device pixels can exceed CSS pixels. Set scale: 'css' when you want one output pixel per CSS pixel.
The crop shows the wrong area. The rectangle’s x and y are page coordinates, or the viewport/layout differs from the values used to choose them. Confirm the page state and viewport, then adjust the top-left coordinates and dimensions.
The region is blank or incomplete. The page or target content was not ready when capture began. Wait for a meaningful selector or application-specific ready condition before calling screenshot().
The saved file format is unexpected. The path extension or explicit type does not match the expected format. Use a matching extension or specify type: 'png', 'jpeg', or 'webp'.
A popup or overlay obscures the target. The page visibly contains the overlay at capture time. Handle the overlay as part of the page workflow, or use the ScreenshotNeo option below if you want known consent banners, newsletter popups, and chat widgets removed before capture.
A screenshot assertion differs from a direct screenshot. Screenshot assertions have different default animation behavior and perform visual stabilization. Account for the assertion API’s disabled-animation default and compare captures made under the same conditions.
Combining clip and fullPage gives an unclear result. The cited API reference treats them as separate options and does not specify their combined behavior. Use the single option that expresses the intended target, or verify the behavior for your installed Playwright version.

7. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. A single GET request can return an image or PDF; for a URL screenshot, use the API request below. See the API documentation for options and setup.

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}`);
const image = Buffer.from(await res.arrayBuffer());
require('node:fs').writeFileSync('shot.webp', image);
  • Cookie and consent banners are accepted like a visitor and removed before the shot; newsletter popups and chat widgets are removed too, and each step can be turned off.
  • Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Response headers say which page verdict applied and whether it was billed.
  • An MCP server lets AI agents using Claude, Cursor, or another MCP client call take_screenshot, get_page_info, and capture_pdf.
  • The free plan includes 1,000 screenshots a month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is on every plan.

Sign up for 1,000 free screenshots a month, with no card required.

8. Frequently asked questions

Does “CSS clip rectangle” mean the coordinates are always CSS pixels?

The rectangle specifies the region; the separate scale option controls output pixel scaling. Set scale: 'css' for one output pixel per CSS pixel.

Can I use a clip with a screenshot assertion?

Yes. Playwright Test’s expect(page).toHaveScreenshot({ clip }) accepts the same rectangle fields. It is a visual assertion rather than a file-saving call.

Which format should I use?

Use PNG when you want the documented default and lossless output. Choose JPEG or WebP when their compression and quality settings fit your storage or delivery needs.

Should I clip an element or use a locator screenshot?

Use a locator screenshot when the target is a particular element. Use clip when you need an arbitrary page rectangle that may include multiple elements or surrounding space.