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

Use Playwright’s page.screenshot() with a clip rectangle when you need a precise crop:

await page.screenshot({
  path: 'clipped.png',
  clip: { x: 100, y: 200, width: 600, height: 400 }
});

x and y mark the rectangle’s top-left corner in CSS pixels; width and height define its size. For one DOM element, locator.screenshot() is usually simpler because Playwright determines the element’s bounds for you.

Choose the right Playwright screenshot method

The capture API depends on what “clip” means in your case. A fixed rectangle, one element, the visible viewport and the complete scrollable page are different jobs.

Need API What it captures Coordinate work
Exact geometric crop page.screenshot({ clip }) A rectangle specified by x, y, width and height You provide all four values
One DOM element page.locator(selector).screenshot() The selected element Playwright calculates the element bounds
Current viewport page.screenshot() Only the visible viewport None
Entire page page.screenshot({ fullPage: true }) The full scrollable page None, but page height determines output

Clip a fixed rectangle in JavaScript

Minimal runnable example

import { chromium } from 'playwright';

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

await page.goto('https://example.com', { waitUntil: 'networkidle' });
await page.screenshot({
  path: 'clipped.png',
  clip: { x: 100, y: 200, width: 600, height: 400 }
});

await browser.close();

The rectangle is measured against the page’s rendered coordinate system. The top-left point is (100, 200), and the image is 600 pixels wide by 400 pixels high in CSS-pixel terms before any device-scale conversion.

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

Calculate a clip from page geometry

Hard-coded coordinates are useful for a stable layout, but responsive pages normally need coordinates calculated at runtime. Use an element’s bounding box when the crop should include surrounding space or multiple elements.

const card = page.locator('.pricing-card').first();
await card.waitFor({ state: 'visible' });

const box = await card.boundingBox();
if (!box) throw new Error('The pricing card has no visible bounding box');

const padding = 16;
await page.screenshot({
  path: 'card-with-padding.png',
  clip: {
    x: Math.max(0, box.x - padding),
    y: Math.max(0, box.y - padding),
    width: box.width + padding * 2,
    height: box.height + padding * 2
  }
});

Check the resulting rectangle against the viewport and page layout. A selector that is hidden, detached or not rendered can produce no bounding box; wait for the intended state before reading geometry.

Screenshot a single element

When the subject is one DOM node, use the locator screenshot API instead of manually copying coordinates:

const header = page.locator('.header');
await header.screenshot({ path: 'header.png' });

This approach follows the element as its size changes with text, fonts and responsive breakpoints. It is also easier to read in tests and less vulnerable to unrelated content moving elsewhere on the page.

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

Element states and lazy content

Make the page deterministic before capture. Wait for the element, trigger an interaction if necessary, and allow images or client-rendered content to finish.

const chart = page.locator('#chart');
await chart.waitFor({ state: 'visible' });
await page.waitForLoadState('networkidle');
await chart.screenshot({ path: 'chart.png', animations: 'disabled' });

If a page uses a cookie dialog, modal or sticky header, close or hide it before taking the screenshot. Otherwise the overlay can be included in an otherwise correct crop.

Viewport and full-page screenshots

Visible viewport

Omit both clip and fullPage to capture what the browser currently displays:

await page.screenshot({ path: 'viewport.png' });

Full scrollable page

Set fullPage: true when content below the fold belongs in the artifact:

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

The default for fullPage is false. A full-page image can be very tall, so use a clip or an element screenshot when a complete page is not actually required.

Output size, scale and transparency

CSS pixels versus device pixels

The scale option controls output density:

  • scale: 'css' produces one image pixel per CSS pixel. It keeps files compact and is generally convenient for layout review.
  • scale: 'device' uses device pixels. On a high-DPI context this creates a larger, sharper image and a larger file.
await page.screenshot({
  path: 'retina.png',
  clip: { x: 0, y: 0, width: 800, height: 500 },
  scale: 'device'
});

Transparent PNG output

omitBackground: true hides the default white background and allows transparency. Use PNG for this workflow; transparency does not apply to JPEG output.

await page.screenshot({
  path: 'transparent.png',
  omitBackground: true,
  type: 'png'
});

Clipping in Playwright Test visual assertions

For visual regression, use expect(page).toHaveScreenshot() with the same clipping concepts:

import { test, expect } from '@playwright/test';

test('navigation remains stable', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot('navigation.png', {
    clip: { x: 0, y: 0, width: 1000, height: 120 }
  });
});

The screenshot assertion waits until two consecutive screenshots are identical before comparing them. It is available through the Playwright test runner, not as a generic assertion in every browser script. Keep clip coordinates, viewport settings and page state stable so a genuine layout change is not confused with capture noise.

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.

Reliable clipping workflow

  1. Set a known browser context. Fix the viewport, device scale, timezone and any other settings that affect layout.
  2. Navigate to the exact state. Use an appropriate load condition and wait for client-rendered content.
  3. Choose scope. Use a locator for one element, clip for a geometric region, and fullPage only for the complete scrollable document.
  4. Remove transient UI. Close consent dialogs, menus and chat widgets or hide them with a test-only style.
  5. Choose density and format. Use CSS scale for compact artifacts, device scale for high-resolution output, and PNG when transparency is needed.
  6. Save or return the buffer. Omitting path returns image bytes, which is useful for uploads, pixel comparisons and in-memory processing.

Troubleshooting clipped screenshots

The crop is shifted

CSS coordinates are relative to the rendered page, so a changed viewport, zoom, responsive breakpoint or scroll position can move the subject. Fix the viewport and derive the rectangle from boundingBox() rather than relying on old constants.

The element screenshot is empty or fails

Verify the selector matches the intended node, wait for state: 'visible', and check that the element has rendered dimensions. Detached nodes and elements hidden by CSS do not provide a useful capture.

Content is missing below the fold

A normal screenshot captures the viewport. Use fullPage: true, scroll to trigger lazy loading before capture, or target the specific element that contains the content.

Transparent output is white

Use omitBackground: true with PNG. JPEG cannot preserve transparency.

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

Visual tests are flaky

Wait for fonts, images and application state; disable animations where appropriate; keep the browser, viewport and clip geometry consistent. The assertion’s consecutive-identical-screenshot wait helps, but it cannot stabilize a page that is still changing.

The file is unexpectedly large

Use scale: 'css', clip a smaller region, or capture an element instead of a full page. Device-pixel output and very tall documents increase memory and storage requirements.

Performance, reliability and cost considerations

Clipping reduces the pixels written to the output, but the browser still has to load and render the page. Optimize the navigation and page state first: reuse a browser when taking many screenshots, avoid unnecessary full-page captures, and wait only for the condition your application requires. For regression suites, stable geometry is more important than maximum resolution.

Playwright itself runs locally or in your chosen infrastructure, so your cost depends on browser runtime, compute and storage. A remote screenshot API can move browser maintenance and capture infrastructure out of your application.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its one-call endpoint can return PNG, JPEG, WebP or PDF, and it supports element capture, full-page shots, custom CSS and JavaScript, waits, device presets, retina scale, transparent backgrounds and more.

Cookie banners, newsletter popups and chat widgets are removed before the shot. 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 provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.

cURL

See the ScreenshotNeo documentation for all parameters. A basic request is:

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

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. Create a free ScreenshotNeo account to get started.

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.

Frequently asked questions

Can a clip include several separate elements?

Yes. Use one rectangle covering the region that contains them, or place the elements in a wrapper and capture that wrapper with a locator.

Does clipping change the page layout?

No. The clip option limits the output image; it does not remove content or reflow the page.

Should I use an element screenshot for a regression test?

Use it when the component is the unit you want to protect. Use a clipped page assertion when surrounding context, spacing or interactions are part of the visual contract.

Frequently Asked Questions

Can a clip include several separate elements?

Yes. Use one rectangle covering the region that contains them, or place the elements in a wrapper and capture that wrapper with a locator.

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

Does clipping change the page layout?

No. The clip option limits the output image; it does not remove content or reflow the page.

Should I use an element screenshot for a regression test?

Use it when the component is the unit you want to protect. Use a clipped page assertion when surrounding context, spacing or interactions are part of the visual contract.

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.