ScreenshotNeo

BlogHow-to

How to Capture a Full-Page Screenshot in Playwright with a Specific Viewport

Set Playwright’s viewport before navigation, then capture the full scrollable page with `fullPage: true`. Here are runnable JavaScript and Python examples, fixes for common issues, and an API alternative.

By the ScreenshotNeo team4 October 20267 min read

Set the viewport width and height before navigating to the page, then pass fullPage: true to Playwright’s screenshot method. The viewport controls the page’s CSS-pixel layout and responsive breakpoints; fullPage controls how much of the scrollable page is captured.

import { chromium } from 'playwright';

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

try {
  await page.goto('https://example.com', { waitUntil: 'load' });
  await page.screenshot({ path: 'full-page.png', fullPage: true });
} finally {
  await browser.close();
}

The 1440 × 900 dimensions are examples, not Playwright defaults. Replace them with the CSS viewport your screenshot needs. The resulting image can be much taller than 900 pixels because fullPage captures the full scrollable page.

1. Understand viewport size and full-page extent

These settings answer different questions:

  • Viewport: At what CSS-pixel width and height should the browser lay out the page? This affects responsive breakpoints, column widths, and other layout choices.
  • Full-page extent: Should the screenshot show the current viewport or the entire scrollable page? In JavaScript, fullPage: true requests the full scrollable page.

Playwright describes full-page capture as taking a screenshot of the full scrollable page instead of the currently visible viewport. It does not mean the page was laid out at a viewport as tall as the final image, and it does not select the viewport width. See the Page API screenshot options and the Playwright Screenshots guide.

2. Capture a full page in JavaScript

Install Playwright

npm init -y
npm install playwright

Save this as screenshot.mjs and run it with node screenshot.mjs. The first run may require installing the browser binaries for your Playwright setup; use the install instructions for the version you have installed.

import { chromium } from 'playwright';

const url = 'https://example.com';
const viewport = { width: 1440, height: 900 };
const browser = await chromium.launch();

try {
  const page = await browser.newPage({ viewport });
  await page.goto(url, { waitUntil: 'load', timeout: 30_000 });

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

Setting the viewport when creating the page ensures it is in place before navigation and page layout. If you already have a page, configure its viewport with the page viewport API before navigating or capturing. The Page API documents the screenshot options, including path, fullPage, clip, and screenshot output as a buffer when no path is provided.

Return the screenshot as bytes

For an upload or an in-memory workflow, omit path and use the returned buffer:

const image = await page.screenshot({ fullPage: true });
// For example, pass image to your storage or upload code.

3. Use Python’s Playwright binding

Python uses snake_case argument names, including full_page=True and viewport dimensions on the browser context. Install the Python package and its browser binaries using the commands for your environment:

python -m pip install playwright
python -m playwright install chromium
from playwright.sync_api import sync_playwright

with sync_playwright() as playwright:
    browser = playwright.chromium.launch()
    try:
        page = browser.new_page(viewport={"width": 1440, "height": 900})
        page.goto("https://example.com", wait_until="load", timeout=30_000)
        page.screenshot(path="full-page.png", full_page=True)
    finally:
        browser.close()

For asynchronous Python applications, use async_playwright and await the browser, navigation, and screenshot calls. Keep the same sequence: choose the viewport, navigate, then take the full-page screenshot.

4. Handle content that loads on scroll

fullPage requests a capture of the full scrollable page, but it does not promise that every site-specific lazy image or dynamically inserted section has loaded. Some pages fetch content only after a scroll, an interaction, or a particular wait condition.

  1. Navigate and wait for the page state your task needs. load waits for the load event; it does not guarantee that every later request or application update is finished.
  2. If the site loads content as you scroll, scroll through the page in increments and wait for the content to appear. Use a site-specific selector or other condition where possible.
  3. Take the full-page screenshot after the required content is present.
  4. Inspect the result for missing content, fixed or sticky elements appearing unexpectedly, and layout changes at the chosen viewport.

There is no universal wait that can infer when every website’s lazy-loading logic has completed. Choose a condition that matches the page being captured, and avoid assuming that a successful navigation alone means all below-the-fold content is ready.

5. Choose the right screenshot extent

Need Use What it changes
Whole scrollable document fullPage: true in JavaScript or full_page=True in Python Captures beyond the visible viewport.
Only the visible screen Default screenshot options Captures the viewport area.
A particular element Locator or element screenshot Captures the selected element instead of the whole page.
A specific rectangular region clip screenshot option Limits the captured area to the requested rectangle.

For a very long page, an element or clipped screenshot may better fit the task and produce a smaller output. Consult the Page API for the options supported by your installed Playwright version.

6. Or skip the browser setup

If you do not want to install and run a browser for each capture, ScreenshotNeo is a website screenshot API and MCP server. Its API accepts a URL and can return an image or PDF. See the ScreenshotNeo API documentation for parameters, including viewport and full-page capture.

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,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

Cookie banners, popups, and chat widgets are removed before the shot; each cleanup step can be turned off. Bot checks, blank pages, and failed loads are never billed, and response headers report the page verdict and billing status. An MCP server lets AI agents use screenshot tools. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account to get started.

7. Troubleshooting

Symptom Likely cause Fix
Screenshot shows only the first screen Full-page mode was omitted or set to false. Pass fullPage: true in JavaScript or full_page=True in Python.
Page has the wrong desktop or mobile layout The viewport was not set to the intended dimensions before layout. Set width and height on the page or context before navigation. Remember dimensions are CSS pixels.
Images or sections below the fold are missing The site loads them only after scrolling or another site-specific event. Trigger the required scroll or interaction, wait for the content, and capture afterward.
Code rejects the screenshot option JavaScript and Python use different option spellings, or the installed version differs. Use fullPage in JavaScript and full_page in Python; check the documentation matching your installed version.
Capture takes too long or navigation times out The page is slow, waits on remote resources, or the chosen readiness condition does not occur. Set a task-appropriate navigation timeout and wait for a specific page condition instead of assuming every external request will finish.
Output is unexpectedly huge The full scrollable document can be very tall. Capture a locator or clipped region if the task only needs part of the page.

8. Performance, reliability, and output considerations

  • Page height affects the capture: full-page output includes the page’s scrollable extent, so long documents can take more resources and create large image files.
  • Viewport affects layout: choose the target width before navigation. Changing the viewport can change responsive content and the page’s document height.
  • Wait for the right condition: use a selector, state, or deliberate scroll tied to the page. A generic navigation event cannot establish that every site-specific lazy load has completed.
  • Close the browser reliably: use a finally block so browser processes are closed even when navigation or capture raises an error.
  • Check the artifact: verify expected lower-page content and watch for sticky headers or other fixed elements in the tall result.
  • Cost: Playwright is a browser automation library; the capture code itself does not state a service price. Account for the infrastructure and browser execution you choose to run it on. If using ScreenshotNeo, its Free plan is 1,000 shots monthly without a card; published paid tiers start at $5 for 3,000 shots, with every feature on each plan.

9. FAQ

Does full-page mode make the viewport taller?

No. The viewport still sets the browser layout dimensions. Full-page mode changes the screenshot extent to the full scrollable page.

Should I set the viewport before or after navigation?

Set it before navigation so the page lays out at the intended responsive size from the start.

Can I capture the full page at a mobile width?

Yes. Set the viewport width and height to the CSS-pixel dimensions you want, then enable full-page capture. The page’s responsive layout follows that viewport width.

Will full-page capture automatically load every lazy image?

Do not assume so. If the site loads images or sections after scrolling, trigger that behavior and wait for the content before capturing.

Can I save the screenshot without writing directly to a file?

Yes. In JavaScript, omit path and use the returned buffer; in Python, use the screenshot call’s returned bytes if your binding version supports that workflow.