ScreenshotNeo

BlogHow-to

How to Fix Full-Page Screenshot Clipping in Playwright

Set Playwright’s `fullPage: true` for a page-level capture, then check for a clipping rectangle, an element screenshot, or a pixel-scale mix-up.

By the ScreenshotNeo team4 October 20265 min read

The usual fix is to enable Playwright’s fullPage option on a page screenshot:

await page.screenshot({ path: 'page.png', fullPage: true });

By default, fullPage is false, so page.screenshot() captures only the current viewport. If the result is still clipped, check whether the call includes a clip rectangle or whether it is an element screenshot rather than a page screenshot. Those capture different areas.

1. Use a page-level full-page screenshot

With Playwright Test, a complete runnable example can look like this:

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

test('capture the full page', async ({ page }) => {
  await page.goto('https://example.com');
  await page.screenshot({ path: 'page.png', fullPage: true });
});

For a standalone Node.js script:

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  try {
    const page = await browser.newPage();
    await page.goto('https://example.com');
    await page.screenshot({ path: 'page.png', fullPage: true });
  } finally {
    await browser.close();
  }
})();

Use the equivalent API in Python:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    try:
        page = browser.new_page()
        page.goto("https://example.com")
        page.screenshot(path="page.png", full_page=True)
    finally:
        browser.close()

In Python, the option is spelled full_page with an underscore. In JavaScript and TypeScript, it is fullPage.

2. Check what area Playwright is capturing

Capture call What it captures What to check
page.screenshot() The current viewport by default Set fullPage: true (Python: full_page=True) for the full scrollable page.
page.screenshot({ fullPage: true }) A page-level full-page capture Remove or correct any clip bounds that restrict the output.
locator.screenshot() or an element screenshot The target element’s area Use a page screenshot if you need the whole document. For a scrollable element, an element screenshot shows only its currently scrolled content.
page.screenshot({ scale: 'css' }) One output image pixel per CSS pixel scale changes pixel density; it does not enable full-page capture.
page.screenshot({ scale: 'device' }) Output at device pixel density Expect a larger image on high-DPI settings. Use fullPage separately to capture the full scrollable page.

Playwright describes a full-page screenshot as capturing the full scrollable page as though it fit on a very tall screen. See the official Screenshots guide and Page API.

Review the screenshot options

  • fullPage: Set to true for the full scrollable page. The default is false.
  • clip: An optional rectangle with x, y, width, and height. Check that the rectangle matches the intended output; remove it when you want the full page without explicit bounds.
  • scale: Choose 'css' for CSS-pixel output or 'device' for device-pixel output. This controls density, not page extent.
  • Capture target: A page-level screenshot and an element screenshot have different bounds and scroll behavior.

For the full list of supported screenshot options, consult the Playwright Page API.

3. Fix visual screenshot assertions

If the clipping happens in a Playwright visual assertion, set the option on the assertion itself:

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

test('compare the full page', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot({ fullPage: true });
});

The page screenshot assertion waits for two consecutive screenshots to match before comparing. Keep the page in a stable state when taking the assertion. Playwright’s PageAssertions API documents the assertion options.

4. Troubleshoot remaining clipping

Symptom Likely cause Fix
Only the visible screen appears fullPage was omitted, so it remains false. Use page.screenshot({ fullPage: true }) or Python’s page.screenshot(full_page=True).
The image stops at a rectangular boundary A clip rectangle limits the captured output. Remove clip for a full-page capture, or set its coordinates and dimensions to the intended bounds.
A panel or component is cut off The call captures an element, not the page, or the element is internally scrollable. Use a page-level full-page screenshot for document content. Element screenshots only include the element’s area; for a scrollable element, only its currently scrolled content is visible in the screenshot. See the ElementHandle API.
The image has unexpected dimensions scale changes output pixel density, or an explicit clip changes the output area. Choose the intended scale and bounds. Do not use scale as a substitute for fullPage.
Content differs or appears missing between captures The page content may change while the screenshot is taken, or the layout may depend on the rendering environment. Inspect the particular page structure and capture call. The cited API documentation does not prescribe a universal workaround for changing pages or every nested scroll container.

For screenshot comparisons, use a consistent browser and host environment. Playwright notes that rendering can vary with the operating system, browser version, settings, hardware, power source, and headless mode; it advises using the environment that created the baseline. See Visual comparisons.

5. Performance, reliability, and cost

A full-page capture produces a taller image than a viewport capture, and scale: 'device' can increase its pixel dimensions further. If you only need a region, an intentional clip or element screenshot can reduce the output area. The cited Playwright sources do not provide a universal runtime, memory, or cost figure for full-page captures, so measure against your own page and environment.

For repeatable visual assertions, keep the rendering environment consistent and make sure the page has reached the state you intend to compare. If the page changes during capture, the API description alone does not establish a universal fix; diagnose the page and call together.

Or skip the browser setup

If you need a screenshot without managing Playwright and a browser, ScreenshotNeo provides a website screenshot API. See the API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests

r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits cost nothing, and response headers say which result occurred. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for ScreenshotNeo’s free 1,000 screenshots a month, with no card.

FAQ

Does fullPage: true include content below the fold?

Yes. It requests a page-level screenshot of the full scrollable page.

Does fullPage work with an element screenshot?

fullPage is the page screenshot option discussed here. Element screenshots use the element’s bounds and have their own scroll behavior.

Should I use scale: 'css' or scale: 'device' to fix clipping?

Neither changes the capture extent. Set fullPage to capture the full page, and use scale only to choose output pixel density.