Fix Clipped Full-Page Screenshots of Long Competitor Pages in Playwright
Diagnose clipped Playwright screenshots by checking full-page capture, clipping, scale, and whether long-page content was present when the capture ran.
If a Playwright screenshot stops before the bottom of a long page, first confirm that the screenshot call sets fullPage: true and does not also constrain the capture with clip. Then check whether the missing content actually existed in the page when the screenshot ran, and compare image dimensions using the configured screenshot scale. Playwright documents full-page capture as taking a screenshot of the full scrollable page; the option defaults to false. Playwright screenshot guide · Page screenshot API.
1. Set full-page capture explicitly
For Playwright’s JavaScript API, set fullPage: true in the screenshot options. This runnable example opens a page, waits for the document load event, records the document dimensions, and saves a full-page PNG.
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
try {
await page.goto('https://example.com/long-page', { waitUntil: 'load' });
const dimensions = await page.evaluate(() => ({
scrollWidth: document.documentElement.scrollWidth,
scrollHeight: document.documentElement.scrollHeight,
bodyScrollHeight: document.body?.scrollHeight ?? null
}));
console.log('Document dimensions in CSS pixels:', dimensions);
await page.screenshot({ path: 'full-page.png', fullPage: true });
} finally {
await browser.close();
}
})();
Replace the example URL with the page you are diagnosing. If your project uses ES modules, use import { chromium } from 'playwright'; and retain the same capture options. The key setting is fullPage: true; a screenshot without it captures the viewport by default.
Python binding
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={"width": 1440, "height": 900})
try:
page.goto("https://example.com/long-page", wait_until="load")
dimensions = page.evaluate("""() => ({
scrollWidth: document.documentElement.scrollWidth,
scrollHeight: document.documentElement.scrollHeight,
bodyScrollHeight: document.body?.scrollHeight ?? null
})""")
print("Document dimensions in CSS pixels:", dimensions)
page.screenshot(path="full-page.png", full_page=True)
finally:
browser.close()
In Python the option is spelled full_page=True. Consult the Python screenshot guide for the binding’s current syntax.
2. Compare the image with the page that was captured
A screenshot can only include content that was present and part of the document when capture ran. Before changing browser settings, compare the bottom edge of the image with the live page and with the dimensions reported by the page itself.
- Record the exact URL, Playwright version, browser engine, viewport width and height, and screenshot options.
- Record
document.documentElement.scrollWidthandscrollHeightimmediately before the screenshot. Also inspectdocument.body.scrollHeightif the page uses unusual layout structure. - Open the saved image and compare its pixel dimensions with the document dimensions, accounting for screenshot scale.
- Check whether the missing section is in the DOM and rendered before capture. If it appears only after scrolling, an interaction, or more loading, reproduce that behavior and wait for the page-specific condition before taking the screenshot.
There is no universal lazy-loading remedy established by the reviewed Playwright sources. Treat late content as a page-specific loading or rendering condition: inspect the page, trigger the behavior it requires if appropriate, and wait for a reliable selector or application state before capture.
3. Check options that bound or change the output
| Option or setting | What to check | Why it matters |
|---|---|---|
fullPage / full_page |
Set it to true in JavaScript or True in Python. |
It requests the full scrollable page; the documented default is false. |
clip |
Remove it for an initial full-page diagnostic, or verify its x, y, width, and height. | A clip rectangle limits the captured region. A rectangle that covers only the viewport or a section can make output appear cut short. |
scale |
Compare at the same scale. The API supports "css" and "device". |
"css" gives one image pixel per CSS pixel. "device" gives one pixel per device pixel, so high-DPI output can be larger than the CSS dimensions. |
| Viewport | Keep viewport dimensions constant while comparing runs and note the installed Playwright version. | Viewport affects page layout and is useful reproduction data. It does not by itself establish the cause of clipping. |
type, quality, output format |
Use a lossless PNG while diagnosing dimensions; if using JPEG or WebP, check format and quality settings. | The API’s quality option applies to JPEG and WebP, not PNG. Compression quality changes image fidelity, not the page’s scroll height. |
Use the current API reference for supported options and binding-specific names. Avoid setting a clip rectangle while trying to capture the entire page unless you deliberately want only a region.
4. Make comparisons reproducible
When a fix appears to work in one run, capture again with the same inputs to confirm that the result is repeatable. Keep the following values together with each capture:
- Target URL and relevant page state, including any interaction needed to reveal content.
- Playwright version and browser engine.
- Viewport width and height.
- Full-page setting and any clip rectangle.
- Screenshot scale and output format.
- Document dimensions measured immediately before capture, and the resulting image dimensions.
This makes it possible to distinguish a bounded capture from content that was not yet rendered, and to compare like with like across runs. Do not infer that a particular browser engine or viewport is generally defective from one page’s output.
5. Diagnose a viewport-related report carefully
A historical Playwright issue reported screenshots being cut off with an explicitly configured viewport on Linux using Playwright 1.20.2. The report was opened in April 2022. It is a reproduction clue for a similar setup, not evidence that current Playwright releases have a general viewport clipping bug. Historical issue #13339.
If your setup resembles that report, create a minimal reproduction on your installed version. Capture the same URL once with the explicit viewport and once with the default viewport, keeping the browser engine and other screenshot settings fixed. Record the resulting document and image dimensions. This can show whether the behavior is tied to your reproduction; it cannot establish a general cause from the historical report alone.
6. Troubleshooting common outcomes
| Symptom | Likely explanation to check | Next step |
|---|---|---|
| Image ends near the viewport bottom | fullPage was omitted, misspelled, or not passed to the screenshot call. |
Set fullPage: true (JavaScript) or full_page=True (Python) on the actual call that writes the image. |
| Image always ends at the same custom boundary | A clip rectangle limits capture dimensions. |
Remove clip for the diagnostic run, or adjust its x, y, width, and height intentionally. |
| Image dimensions look too large or small | The measured CSS dimensions are being compared with device-scaled pixels, or viewport/layout differs. | Check the scale setting and compare CSS pixels with "css" scale output; keep viewport fixed. |
| Bottom section is missing in both screenshot and document measurements | The section may not have loaded or entered the document before capture, or the page may render it only after interaction or scrolling. | Inspect the page state immediately before capture; wait for a page-specific selector or trigger the required behavior, then remeasure. |
| Only one page or environment clips | The issue may depend on that page’s layout, content timing, version, browser engine, or viewport. | Reduce it to a minimal reproduction and change one recorded variable at a time. |
| JPEG or WebP looks visually degraded | Lossy encoding or its quality setting affects fidelity. | Use PNG for the diagnosis, or set an appropriate JPEG/WebP quality. Quality does not correct a missing page region. |
7. Performance, reliability, and cost
A full-page capture produces an image covering the full scrollable document, so a long page can produce a much larger file than a viewport capture. Image pixel dimensions depend on the page dimensions and scale; "device" can increase dimensions on high-DPI displays. Choose the output format and scale based on the fidelity and storage needs of your workflow, and avoid capturing full pages when only a specific region is needed.
For reliable results, wait on an explicit page condition that represents the content you need, capture after measuring the document, and preserve the reproduction settings. A generic load event may not prove that content rendered later by page-specific behavior is present. The reviewed sources provide no benchmark comparing browser engines for this clipping issue, so performance and reliability should be measured with your own page and capture settings.
Self-hosted Playwright has no per-screenshot API fee described by the cited sources; account for the browser runtime, compute, image storage, and the engineering time needed to maintain capture code in your own environment. If you use a screenshot service, compare its documented billing rules and capture behavior against your workload rather than assuming that every response is billed the same way.
8. Or skip the browser setup
For a one-request screenshot without maintaining browser automation, ScreenshotNeo accepts a URL and returns an image or PDF. See the ScreenshotNeo API documentation.
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)
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}`);
ScreenshotNeo accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers say whether the page was clean and whether it was billed. Its MCP server lets AI agents, including Claude and Cursor, take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000, and yearly billing gives two months free. Every feature is available on every plan. Learn more about ScreenshotNeo, then sign up for 1,000 free screenshots a month with no card.
FAQ
Does full-page capture change the viewport height?
The documented behavior is to capture the full scrollable page rather than only the visible viewport. Keep the viewport recorded because it can affect page layout, and consult the API docs for the installed version.
Can I use clip and fullPage together?
For diagnosing a clipped whole-page image, first remove clip. A clip is a rectangle and can bound the output; use it only when you intentionally need a region.
Does a high-DPI screenshot mean the page is taller?
No. Device scale changes the relationship between CSS pixels and image pixels. Compare dimensions at the same scale before concluding that page content is missing.
Which browser engine fixes clipped long-page screenshots?
The reviewed sources do not establish a generally superior engine for this failure mode. Reproduce with your installed version and compare engines only while holding the page, viewport, and options constant.


