ScreenshotNeo

BlogHow-to

Playwright Screenshot Not Full Page: Causes and Fixes

If a Playwright screenshot shows only the viewport, check the capture API, fullPage option, element boundaries, clipping, and page readiness.

By the ScreenshotNeo team4 October 20266 min read

If a Playwright screenshot shows only the visible viewport, explicitly pass fullPage: true to page.screenshot(). The option defaults to false, so viewport-only output is expected otherwise. If that does not fix it, check whether you are capturing a page or an element, whether a clip rectangle crops the image, and whether the missing content has rendered before capture.

1. The direct fix: set fullPage to true

For a page screenshot, use:

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

fullPage captures the full scrollable page instead of only the current viewport. Its default is false. See the Playwright Page screenshot API.

A complete Node.js example using Playwright’s library:

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

(async () => {
  const browser = await chromium.launch();
  try {
    const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
    await page.goto('https://example.com', { waitUntil: 'load' });
    await page.screenshot({ path: 'full-page.png', fullPage: true });
  } finally {
    await browser.close();
  }
})();

Install the package with npm install playwright and install its browser with npx playwright install chromium. Use a URL you control or are authorized to capture. If the application renders important content after the page’s load event, wait for an application-specific ready signal before taking the screenshot.

2. Confirm which screenshot API you are using

Playwright offers different screenshot paths with different capture boundaries. First identify the method in the code that produced the image.

Capture method What to check
page.screenshot() Pass fullPage: true for the full scrollable page.
locator.screenshot() or an element screenshot The capture is bounded by the element. Use a page screenshot if you need the whole document.
page.screenshot({ clip }) Remove or adjust the rectangle if it crops the desired content.
Playwright Test automatic screenshot Configure the screenshot option in the test runner, including fullPage.
expect(page).toHaveScreenshot() Pass fullPage: true to the assertion if the comparison should cover the full page.

Playwright documents fullPage for page screenshots, screenshot assertions, and test screenshot configuration.

3. Fix screenshots in Playwright Test

If your test calls page.screenshot() directly, use the same option there. If Playwright Test creates screenshots automatically after a test failure, configure its use.screenshot setting:

// playwright.config.js
const { defineConfig } = require('@playwright/test');

module.exports = defineConfig({
  use: {
    screenshot: {
      mode: 'only-on-failure',
      fullPage: true
    }
  }
});

For a visual assertion, set the option on the assertion itself:

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

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

toHaveScreenshot() waits for two consecutive screenshots to match before comparing. For the complete assertion behavior, see the PageAssertions API.

4. Check element screenshots and clipping

Page screenshot versus element screenshot

An element screenshot captures an element’s bounds, not the whole document. A screenshot of a scrollable element can show only the content at its current scroll position. If your goal is the entire page, take a page screenshot with fullPage: true. Playwright recommends locator-based screenshots over the older ElementHandle.screenshot() method; see the ElementHandle screenshot reference.

Check for a clip rectangle

The clip option defines a rectangle for the screenshot output. An explicit clip can make a page screenshot look truncated even when fullPage is enabled. Review the options passed at the call site and remove the clip or expand its dimensions to cover the intended area. The Page API documents both options.

5. When fullPage is true but content is still missing

fullPage: true captures the page’s full scrollable area; it does not guarantee that an application has finished rendering every piece of content. If the lower part is blank or absent, check whether the page has populated it by the time the screenshot is taken.

  1. Wait for the specific content that should appear, such as a results container or a known section, with await page.locator('.results').waitFor().
  2. For content populated after an interaction, perform the interaction and wait for the resulting state before capturing.
  3. For lazy-loaded images or sections that load as the user scrolls, determine whether the application has loaded them before capture. Inspect the rendered page and network behavior for your site; there is no universal workaround guaranteed for every application.
  4. Save a screenshot after the relevant ready condition and inspect its dimensions and lower sections. This helps distinguish an unloaded page from an incorrect capture boundary.

Prefer an application-specific readiness condition over an arbitrary fixed delay when one is available. A delay can be useful for a known animation or delayed response, but it may be too short on a slow run and unnecessarily long on a fast one.

6. Troubleshooting checklist

Symptom Likely cause Fix
Image is exactly the viewport size fullPage was omitted and defaults to false. Set fullPage: true on the page screenshot call.
Only a component appears The code screenshots a locator or element. Use page.screenshot({ fullPage: true }) for the document.
Image stops at a straight rectangular boundary A clip option limits the capture. Remove or revise clip.
Top of page appears, but lower content is empty Content may not have rendered or loaded when capture ran. Wait for the site’s relevant content or ready state, then inspect the rendered page.
Direct screenshots work, failure screenshots do not The test runner’s automatic screenshot configuration is separate from the direct call. Set use.screenshot.fullPage in the Playwright Test configuration.
Visual snapshot differs across machines Browser rendering can vary with OS, browser version, settings, hardware, power source, and headless mode. Keep the baseline and comparison environment consistent. See Playwright’s visual comparisons guide.

7. Reliability, performance, and visual comparisons

A full-page capture contains more document area than a viewport capture, so the resulting image can be taller and larger. Use viewport screenshots when the test only concerns what a user sees in the initial viewport; use full-page screenshots when below-the-fold content is part of the requirement. Avoid capturing more area than the assertion needs.

For reliable visual comparisons, keep the browser and rendering environment consistent. Playwright notes that screenshots can vary by host OS, browser version, settings, hardware, power source, and headless mode. Dynamic page content can also make images differ between runs. Use screenshot styles or application setup to hide or stabilize elements that are expected to change, as described in the visual comparisons documentation.

When a full-page screenshot is unexpectedly huge or slow, check the document height and whether the page contains unusually long content. Narrow the test to the relevant page state or component if full-document coverage is not needed. There is no benchmark here that predicts capture time for every page; it depends on the content and rendering environment.

8. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. One GET request returns an image or PDF. See the ScreenshotNeo API documentation for options.

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 or consent banners like a visitor 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 are not billed, and response headers report the page verdict and billing status. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.

9. FAQ

Does fullPage change the browser viewport?

It changes the screenshot scope to the full scrollable page. Set the viewport separately when you need a particular responsive layout.

Should I use fullPage for every visual test?

No. Use it when below-the-fold content matters to that test. A viewport capture is simpler when only the visible area is under comparison.

Why does the full-page snapshot change between runs?

Check for changing page content and differences in the browser environment. Keep the rendering setup consistent and stabilize dynamic elements that are outside the behavior under test.