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 Playwright for Python: open a page, then call page.screenshot(path="page.png"). Add full_page=True to capture the full scrollable page instead of only the visible viewport. You can also save a single element, clip a rectangular region, or keep the returned image bytes in memory. The examples below show how to choose the right capture, configure the output, and handle common issues.

Set up Playwright and save your first screenshot

Playwright drives a real browser, so the screenshot reflects the page as rendered by that browser at capture time. This example uses Chromium and the synchronous Python API. It opens a page, saves a full-page PNG, and closes the browser even if navigation or capture fails.

  1. Install the Python package: python -m pip install playwright.
  2. Install a browser Playwright can launch: python -m playwright install chromium.
  3. Save this as save_page.py and run it with python save_page.py.
from pathlib import Path
from playwright.sync_api import sync_playwright

url = "https://example.com"
output = Path("page.png")

with sync_playwright() as p:
    browser = p.chromium.launch()
    try:
        page = browser.new_page()
        page.goto(url)
        page.screenshot(path=str(output), full_page=True)
        print(f"Saved screenshot to {output.resolve()}")
    finally:
        browser.close()

page.screenshot() writes the file directly; a separate image-writing step is not needed. The file extension determines the image format. The example requests a full-page image; omit full_page=True when you only want the current viewport. The Playwright guide also shows WebKit, and the documentation lists Chromium and Firefox as browser choices. See the Playwright Python screenshot guide and the Page API reference for options and version-specific defaults.

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

Choose the browser and context deliberately

A browser page has a viewport and browser context that affect rendering. For a simple capture, browser.new_page() is convenient. If you need a particular viewport or device behavior, create a context with the relevant settings and then open a page in it. Browser choice can also matter: a site may render differently in Chromium, Firefox, or WebKit. A screenshot is evidence of what the selected browser rendered, not a guarantee that every visitor or personalized session sees the same result.

Choose what part of the webpage to capture

Use the capture scope that matches the image you need. These are different outputs, not interchangeable ways of describing the same screenshot.

Need Playwright call What it captures
Visible viewport page.screenshot(path="page.png") The current visible browser page area; this is the default.
Full scrollable page page.screenshot(path="page.png", full_page=True) The page’s full scrollable content, laid out as one tall image.
One element page.locator(".header").screenshot(path="header.png") The rendered element matched by the locator.
Rectangular region page.screenshot(path="region.png", clip={"x": 0, "y": 0, "width": 800, "height": 600}) The specified page-coordinate rectangle.

Capture only the visible viewport

Use the default when you want a view of the page at a particular scroll position and viewport size. A viewport capture does not mean “the whole browser window”: it captures the page area. Set the viewport before navigation if the output needs a consistent width and height. For example:

page = browser.new_page(viewport={"width": 1280, "height": 800})
page.goto("https://example.com")
page.screenshot(path="viewport.png")

Capture the full scrollable page

Set full_page=True to request one screenshot of the full scrollable page, as if it fit on a very tall screen. This is useful for a long article or landing page when one tall image is acceptable. It is not a capture of browser chrome, and the result can be much taller than the viewport. For a very long page, consider whether your destination can handle a large image; a viewport or element capture may be more practical.

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

Capture one element or a clipped region

For one component, use a locator and call its screenshot method. Replace .header with a selector that identifies the element you need:

page.goto("https://example.com")
page.locator(".header").screenshot(path="header.png")

If the selector matches no element, or matches the wrong one, the capture will not produce the intended component. Inspect the page and use a selector specific enough for the target. For a fixed rectangle rather than an element, pass a clip dictionary with x, y, width, and height. Coordinates and dimensions should describe the region you actually want within the page.

Select image format, quality, and pixel scale

Playwright documents PNG, JPEG, and WebP screenshot output. The path extension determines the format when saving to a path. Choose based on how the image will be used: PNG is commonly useful when you want lossless output; JPEG and WebP offer a quality setting. The documented quality option applies to JPEG and WebP, not PNG, and ranges from 0 to 100. Lower quality can reduce file size at the cost of visible image detail.

page.screenshot(path="page.webp", type="webp", quality=85)
page.screenshot(path="page.jpg", type="jpeg", quality=85)
page.screenshot(path="page.png", type="png")

The scale option controls whether the output uses CSS pixels or device pixels. CSS scale produces one image pixel per CSS pixel; device scale uses device pixels and can create a larger image on high-DPI displays. Choose CSS scale when predictable CSS-sized dimensions matter, and device scale when higher pixel density is useful. Check the API reference for the Playwright version installed before relying on an option or default.

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

Save bytes instead of a file

Without a path, page.screenshot() returns image bytes. This lets you pass the result to another library or service, or write it later:

image_bytes = page.screenshot(full_page=True)

with open("page.png", "wb") as image_file:
    image_file.write(image_bytes)

For in-memory processing, pass image_bytes directly to the relevant consumer rather than creating an intermediate file. The returned bytes still represent the screenshot format selected by the screenshot options.

Use async Python when the rest of your code is asynchronous

Playwright has an asynchronous Python API as well as the synchronous one. Use it when your application already uses asyncio or needs to coordinate browser work with other async operations. The capture method is awaited:

import asyncio
from playwright.async_api import async_playwright

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

asyncio.run(main())

Do not call asyncio.run() inside a context that already manages an event loop, such as some notebook environments. In that case, adapt the example to the host environment and await main() there.

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

Control timing and page appearance

A screenshot captures a rendered state. A site may still be loading images, displaying a consent dialog, showing a personalized page, or waiting on delayed content when the capture occurs. Playwright’s screenshot API includes controls such as timeout, animations, and style; consult the versioned API reference for the available behavior and defaults. The Page API documents a default screenshot timeout of 30,000 milliseconds, but defaults can change across versions, so check the reference for the version you use.

For dynamic pages, decide what “ready” means for your use case. You might wait for a specific element your application expects, or add an intentional delay if the page content is known to appear later. A delay is not a universal readiness test: third-party scripts, personalization, bot checks, and network conditions can still change what appears. The documentation does not establish that every website will expose the same stable state or that every delayed asset will load before capture.

Other useful documented screenshot options include omit_background (not applicable to JPEG), clip, and the style option. Use the API reference rather than assuming a setting behaves identically across all Playwright releases.

Troubleshoot common screenshot problems

  • Browser launch fails: install the browser binary for the browser you selected with python -m playwright install chromium, or select a browser you have installed through Playwright. If you installed or upgraded Playwright, install its corresponding browser binaries again.
  • Navigation times out: the site may be slow, unreachable, or waiting on activity that does not finish. Check the URL and network access, and set an intentional navigation timeout where appropriate. Avoid masking a real failure by blindly increasing timeouts.
  • The image is blank or incomplete: confirm the page loaded and that the relevant content is present before capture. If the site renders content after navigation, wait for a meaningful page element or known delay. A screenshot cannot guarantee content that the page never rendered in that session.
  • Lazy-loaded images are missing: full-page capture requests a tall page image, but it does not establish that every site will load all deferred content automatically. Inspect the page’s loading behavior and use an appropriate page interaction or wait strategy before capture.
  • Element screenshot fails or captures the wrong thing: verify the locator identifies the intended element and that it exists and is visible at capture time. Prefer a stable selector over one that depends on changing page structure.
  • Image type or quality is unexpected: make the filename extension and requested format agree, and use quality only for JPEG or WebP. Quality does not apply to PNG.
  • Output is unexpectedly large: full-page height and device-pixel scaling can increase dimensions. Try viewport or element capture, CSS pixel scale, or JPEG/WebP with an appropriate quality value.
  • Transparent output is not as expected: check the omit_background option and remember it does not apply to JPEG. Use a format and setting suitable for transparency.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If you do not want to install and operate a browser for each capture, ScreenshotNeo offers a screenshot API and MCP server. One GET request can return an image or PDF; see the ScreenshotNeo API documentation for parameters and response details.

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.
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)

The same endpoint can be called from a shell or Node.js:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
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 removes cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, and failed loads are never billed; an MCP server lets AI agents take screenshots; and the Free plan includes 1,000 screenshots per month without a card, with paid plans starting at $5 for 3,000. Sign up for free and get 1,000 screenshots a month with no card.

Keep captures reliable and costs predictable

For a local Playwright workflow, browser execution and image handling are part of your application: you manage browser installation, navigation, capture timing, storage, and retries. Reuse a launched browser for multiple pages when appropriate rather than paying its startup cost for every capture, and close pages and browsers when finished. If captures run in parallel, account for memory use, especially with tall full-page images or device-pixel output.

For repeatable output, make the URL, browser, viewport, capture scope, format, scale, and timing strategy explicit. Record failures separately from successful image writes, and avoid treating an image file’s existence as proof that the page displayed the intended content. When using a hosted screenshot service instead, understand the response format, authentication requirements, failure reporting, and billing rules before integrating it into a production workflow.

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

Frequently Asked Questions

Can Playwright save a screenshot without writing a local file?

Yes. Call `page.screenshot()` without a `path`; it returns image bytes that you can pass to another tool or store yourself.

Does a full-page screenshot include browser tabs and address bar?

No. `full_page=True` captures the page’s scrollable content, not the browser interface.

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.