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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Use page.screenshot(full_page=True). In Playwright’s Python API, that option captures the page’s full scrollable area instead of only the visible viewport. Add a path to save an image, or omit it to receive image bytes for further processing.

This guide covers synchronous and asynchronous scripts, output formats, waiting for dynamic content, test-runner screenshots, common failures, and a browser-free API alternative.

Install Playwright and its browsers

Install the Python package, then download the browser binaries you intend to run. Chromium is sufficient for the examples below.

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

Playwright’s library workflow is documented in the Python library guide. You need Python, a Playwright browser, a URL that can be loaded, and permission to write the output file.

Capture a full page in a synchronous script

The smallest complete program is:

from playwright.sync_api import sync_playwright

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

full_page=True is the important setting. Its documented default is False, which captures only the current viewport. The full-page mode renders the page’s scrollable area as though it fit on a very tall screen; it is not the same as an ordinary viewport screenshot. See the official screenshot guide.

Wait for navigation and page state

page.goto() waits for the navigation to reach its normal load state, but modern pages can continue fetching data, fonts, or images afterward. Wait for a page-specific signal before capturing:

page.goto("https://example.com", wait_until="domcontentloaded")
page.locator("main").wait_for(state="visible")
page.screenshot(path="screenshot.png", full_page=True)

Use a locator that genuinely indicates readiness, such as a results table or article heading. A fixed delay can help with an animation or a known short transition, but a semantic wait is usually more reliable.

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

Use the asynchronous Python API

Choose async when your application already uses asyncio, an async web service, or concurrent browser work. The call is the same apart from await:

import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as playwright:
        browser = await playwright.chromium.launch()
        page = await browser.new_page()
        await page.goto("https://example.com")
        await page.screenshot(path="screenshot.png", full_page=True)
        await browser.close()

asyncio.run(main())

The sync and async APIs expose the same full-page option. Do not call the synchronous API from inside an active event loop; use the async version there. The lifecycle pattern—launch, create a page, navigate, capture, close—is described in the library documentation.

Save a file or process screenshot bytes

Write directly to disk

Set path for a simple artifact:

page.screenshot(path="artifacts/home.webp", full_page=True, type="webp", quality=85)

The screenshot API supports PNG, JPEG, and WebP. JPEG and WebP accept a quality value. Ensure the parent directory exists before writing, or create it with Python’s pathlib.

Keep the image in memory

Without path, page.screenshot() returns image bytes:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
image_bytes = page.screenshot(full_page=True, type="png")
with open("screenshot.png", "wb") as output:
    output.write(image_bytes)

Bytes are useful when uploading to object storage, attaching a test report, hashing an image, or passing it to an image-processing library without a temporary file.

Options that matter for full-page captures

Need Option or method Effect
Entire scrollable page full_page=True Captures the full page rather than the viewport.
One element locator.screenshot() Captures the element’s bounding box instead of the whole document.
Specific region clip={"x": ..., "y": ..., "width": ..., "height": ...} Restricts the capture to a rectangle.
Stable visual output animations="disabled" Disables supported CSS animations and transitions during capture.
One output pixel per CSS pixel scale="css" Avoids larger high-DPI output caused by the device scale factor.
More time for slow pages timeout=... Sets the screenshot operation timeout in milliseconds.
Format type="png", "jpeg", or "webp" Selects the encoded image format; quality applies to JPEG/WebP.

These parameters and defaults are defined in the Page API reference. Keep the viewport explicit when reproducibility matters:

page = browser.new_page(viewport={"width": 1440, "height": 900}, device_scale_factor=1)
page.goto("https://example.com")
page.screenshot(
    path="page.png",
    full_page=True,
    scale="css",
    animations="disabled",
    timeout=60_000,
)

Dynamic, lazy-loaded, and infinite-scroll pages

Full-page mode captures the page’s scrollable layout, but the screenshot documentation does not promise that the call itself scrolls through the page to trigger every lazy-loaded image or loads an infinite-scroll feed. If content appears only after scrolling, load it explicitly before taking the screenshot.

from playwright.sync_api import sync_playwright

with sync_playwright() as playwright:
    browser = playwright.chromium.launch()
    page = browser.new_page()
    page.goto("https://example.com/feed")

    previous_height = 0
    for _ in range(20):
        height = page.evaluate("document.body.scrollHeight")
        if height == previous_height:
            break
        previous_height = height
        page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
        page.wait_for_timeout(500)

    page.screenshot(path="feed.png", full_page=True)
    browser.close()

Use a bounded loop and a real completion condition for production pages. Infinite feeds may never settle; decide how many items or what maximum height you need. For lazy images, wait for a representative image selector or verify that image elements have loaded before capture.

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

Full-page screenshots in pytest

If you use Playwright’s Python pytest plugin, failure screenshots are configured at test-runner level rather than by adding full_page=True to a standalone call. The plugin’s --full-page-screenshot option requires screenshot capture to be enabled with --screenshot:

pytest --screenshot only-on-failure --full-page-screenshot

These flags apply to the test runner. For a custom artifact inside a test, call page.screenshot(path=..., full_page=True) yourself. Refer to the pytest plugin reference for the supported values and configuration.

Troubleshooting

The image contains only the visible area

Pass full_page=True to page.screenshot(). Check that you did not accidentally call locator.screenshot(), which is intended for one element.

The bottom of the page is blank or content is missing

Wait for the application’s data-ready selector, images, or fonts. If the site uses lazy loading or infinite scroll, scroll and trigger that content before capturing; full-page mode alone does not guarantee deferred content is loaded.

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.

The screenshot times out

Find the slow operation rather than immediately using an unlimited timeout. Confirm the URL is reachable, wait for a narrower selector, and then raise the screenshot timeout for a known-slow page, for example timeout=120_000. Also check for a page that never finishes its own network activity.

The file cannot be written

Use an absolute or valid relative path, create the parent directory, and check filesystem permissions. If you only need to transmit the image, omit path and handle the returned bytes.

Output dimensions or file size are unexpectedly large

A long document naturally creates a tall image. Use scale="css", JPEG/WebP with an appropriate quality value, or capture a specific element or clip. A very tall page may also be better represented as several sections or a PDF, depending on the consumer.

Sync code fails inside an async application

Replace sync_playwright with async_playwright, add await to browser, page, navigation, and screenshot calls, and run the coroutine with your application’s event loop.

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

Performance, reliability, and security notes

  • Reuse a browser process when taking many screenshots, but create isolated contexts when cookies, authentication, locale, or viewport settings must not leak between jobs.
  • Set an explicit viewport and scale when pixel dimensions are part of a visual regression comparison.
  • Close pages, contexts, and the browser in cleanup paths so failed captures do not accumulate resources.
  • Use a selector-based readiness check instead of a long arbitrary sleep whenever the page exposes a reliable state signal.
  • Be careful with authenticated pages and sensitive query strings: screenshots can contain private data, and saved files inherit the permissions of their destination.
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 provides a website screenshot API and MCP server. One GET request can return a PNG, JPEG, WebP, or PDF. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.

See the ScreenshotNeo API documentation for all options, including full-page capture, lazy-image loading, CSS-selector element capture, device presets, retina scale, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage data, and the OpenAPI specification. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

cURL

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

Python

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)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

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

Choosing the right capture method

Situation Best fit
Local debugging or browser-level interaction Playwright sync or async API
Existing asyncio service Async Playwright
Need bytes for another Python step Omit path
Automatic failure artifacts in pytest --screenshot with --full-page-screenshot
Many URLs, consent cleanup, or AI-agent access ScreenshotNeo API or MCP server

Frequently Asked Questions

Does full_page=True create a PDF?

No. It returns an image (PNG by default, or JPEG/WebP when selected). Use a PDF-capable workflow when the required artifact is a document rather than an image.

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

Can I capture a single element instead of the whole page?

Yes. Call locator.screenshot() on the element locator; use page-level full_page=True for the complete scrollable document.

Which Playwright Python versions support these APIs?

The exact available options can vary by installed Playwright release. Check the version-specific release notes and API reference when upgrading.

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.