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

Use Playwright for Python: open the URL, call page.screenshot(), and close the browser. Add full_page=True for the complete scrollable document, or use a locator when you need one element. The method writes PNG, JPEG, or WebP files, and it can also return image bytes for in-memory processing.

What you need before taking a screenshot

  • Python 3.8 or newer is a practical baseline for current Playwright releases.
  • A virtual environment keeps Playwright separate from other projects.
  • The Playwright package and at least one browser binary (Chromium, Firefox, or WebKit) must be installed.
  • The target page must be reachable from the machine running the script. A screenshot reflects the page state that browser can load, including authentication, personalization, delayed content, and overlays.
python -m venv .venv
# macOS/Linux
source .venv/bin/activate
# Windows PowerShell
.venvScriptsActivate.ps1

pip install playwright
playwright install chromium

Playwright documents Chromium and Firefox as alternatives to the WebKit example used in its guide. Install the browser you intend to launch; installing the Python package alone does not download browser binaries.

Save a basic webpage screenshot

The synchronous API is the shortest path from a URL to a file. The extension in path determines the documented image format.

from playwright.sync_api import sync_playwright

url = "https://example.com"

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto(url)
    page.screenshot(path="page.png")
    browser.close()

This captures the visible viewport because full_page defaults to False. The browser is closed in the context manager even if the script exits with an exception after launch.

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

Capture the complete scrollable page

from playwright.sync_api import sync_playwright

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

full_page=True asks Playwright to render the full scrollable page as one image, rather than only the current viewport. It is not a capture of browser tabs, toolbars, or other window chrome. Very long documents can create large files and may expose layout limits in the site or image viewer.

Choose exactly what to capture

Use the smallest scope that answers your need. The Page API supports a viewport, a full page, a rectangular clip, or a locator-selected element.

Goal Call Result
Visible viewport page.screenshot(path="page.png") Current viewport; the default.
Full scrollable page page.screenshot(path="page.png", full_page=True) One image covering the document’s scrollable content.
One element page.locator(".header").screenshot(path="header.png") The element matched by the locator.
Rectangular region page.screenshot(path="region.png", clip={"x": 0, "y": 0, "width": 800, "height": 500}) The specified CSS-pixel rectangle.
In-memory image data = page.screenshot() Image bytes instead of direct file output.

Capture an element

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://example.com")
    page.locator("header").screenshot(path="header.png")
    browser.close()

Replace header with a CSS selector that identifies the component you want. If it matches multiple nodes, make the locator more specific so the intended element is unambiguous.

Capture a clipped region or process bytes

from pathlib import Path
from playwright.sync_api import sync_playwright

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

    region = page.screenshot(
        clip={"x": 20, "y": 80, "width": 900, "height": 600},
        type="png",
    )
    Path("region.png").write_bytes(region)

    image_bytes = page.screenshot(type="webp", quality=85)
    Path("page.webp").write_bytes(image_bytes)
    browser.close()

Without path, the method returns bytes. That lets you upload directly to storage, pass the data to an image library, or calculate a digest without creating an intermediate file.

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

Control format, quality, scale, and background

The documented screenshot options let you trade file size, fidelity, and compatibility.

Option How to use it Important detail
Format Use a .png, .jpg, or .webp path, or set type="png", "jpeg", or "webp". The path extension infers the image type when you save to a path.
JPEG/WebP quality quality=0 through quality=100. Applies to JPEG and WebP, not PNG.
Pixel scale Set the API’s scale option to CSS-pixel or device-pixel output. Device pixels can produce a larger image on high-DPI displays.
Transparent background Use omit_background=True. Not applicable to JPEG, which has no alpha channel.
Animation handling Use the documented animations option. Choose the behavior appropriate for repeatable captures.
Styling Supply the documented style option. Useful when a temporary style is needed only for the screenshot.
Timeout Set timeout in milliseconds. The documented default is 30,000 milliseconds.

PNG is a sensible default for text and interface screenshots. JPEG can be smaller for photographic pages, while WebP offers a modern compressed format when your downstream system accepts it. Test the chosen format against the reader, storage, or publishing system that will consume it.

Use the asynchronous API

Async Playwright is useful when screenshot work is already part of an asynchronous service. The calls mirror the synchronous API, but each browser and page operation is awaited.

import asyncio
from playwright.async_api import async_playwright

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

asyncio.run(save_page())

Do not mix synchronous Playwright calls into an event loop. Pick the API style that matches the rest of your application and close the browser when the job finishes.

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

Make captures more repeatable

A screenshot records a particular render, not an abstract page design. A site may show different content because of login state, cookies, geolocation, responsive layout, ads, animations, or content that arrives after navigation.

  • Set the browser context or page viewport deliberately when a fixed layout is required.
  • Navigate to the exact URL, including any path or query parameters that select the intended state.
  • For delayed content, use Playwright’s documented waiting and timeout controls and verify that the required element exists before capturing.
  • Use a locator screenshot for a component instead of relying on coordinates that change with responsive layouts.
  • Use clip only when a fixed rectangle is genuinely the requirement; coordinate clips are sensitive to viewport and page changes.
  • Check the saved image dimensions and format in your pipeline rather than assuming every page has the same size.

The official references describe the screenshot controls, but no API can guarantee that every personalized or delayed website state will be reproduced identically on every run.

Troubleshoot common failures

“Executable doesn’t exist” or browser launch failure

Install a browser binary with playwright install chromium (or the browser you launch). In restricted environments, also confirm that the process is allowed to start a headless browser and that required system libraries are present.

Navigation or screenshot timeout

The documented screenshot timeout default is 30 seconds. Increase it for a legitimately slow page, reduce the page scope, or investigate a URL that never finishes loading. A longer timeout does not fix an unreachable host or a page waiting on an unavailable resource.

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

The image is blank or missing content

Confirm the URL is correct and that the page is reachable without an interactive login. Check whether content is injected after navigation, hidden behind a consent dialog, or blocked by a network policy. Capture a specific locator after the expected element is available when a full-page image is not useful for diagnosis.

The element locator fails

The selector may be wrong, may match no node, or may refer to content that has not rendered yet. Inspect the page’s actual HTML, use a more stable selector, and apply an appropriate wait before calling locator.screenshot().

JPEG transparency or quality behaves unexpectedly

omit_background does not apply to JPEG. Use PNG or WebP when an alpha channel is required. The quality setting has no effect on PNG.

The full-page image is enormous

Long documents naturally produce tall images. Consider an element or clipped capture, a lower device-pixel scale, or a format with compression. If the page itself uses lazy or virtualized content, verify that the captured document contains what readers are expected to see.

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

Performance, reliability, and operating cost

Launching a browser is heavier than writing an existing image file, so a batch service should avoid unnecessary launch-and-close cycles where its architecture permits. Reuse a browser process safely, create isolated pages or contexts for separate jobs, and close them when finished. Keep navigation and screenshot timeouts explicit so a single problematic URL cannot hold a worker indefinitely.

Screenshot quality and size are coupled: device-pixel output and full-page captures consume more memory than a viewport capture at CSS-pixel scale. JPEG or WebP quality controls can reduce transfer size, while PNG preserves crisp interface text without a lossy quality setting. Measure the output characteristics that matter to your storage and delivery path; the Playwright documentation does not provide a universal file-size or speed benchmark.

Playwright itself is software you run and maintain. You supply the browser binaries, execution environment, scheduling, retries, storage, and monitoring. That control is useful for private pages and custom browser state, but it also means you must handle browser failures and site-specific rendering differences.

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server when you prefer one HTTP request over managing Playwright and browser binaries. It accepts a URL and returns PNG, JPEG, WebP, or PDF. Before capture, it accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled.

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

Only clean shots are billed. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the result with X-Page-Verdict and X-Billed. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.

See the ScreenshotNeo API documentation for authentication and parameters. A minimal cURL request is:

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

The same request in Python:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

And in Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', data));

Options available when an API call is a better fit

ScreenshotNeo offers 63 options across common automation needs: full-page capture with lazy images loaded; CSS-selector element capture; dark mode; 12 device presets or any viewport; retina scale; PDF paper size, margins, landscape, and page ranges; HTML/CSS-to-image; custom CSS and JavaScript; click-before-capture; hidden selectors; waits for a selector, delay, or network idle; ad, tracker, request, and resource-type blocking; custom headers, cookies, user agent, and Authorization; timezone and geolocation; transparent backgrounds; image resizing; a TTL you choose for caching; signed links for public <img> tags; asynchronous jobs with signed webhooks; bulk capture of up to 100 URLs per call; a usage API; and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration.

Plans

Plan Allowance and price
Free 1,000 shots per month; no card.
Starter $5 for 3,000 shots.
Growth $15 for 15,000 shots.
Pro $39 for 60,000 shots.
Scale $99 for 250,000 shots.
Business $249 for 1,000,000 shots.

Yearly billing gives two months free, and every feature is included on every plan. If you want clean captures without installing a browser, sign up for ScreenshotNeo; the free plan includes 1,000 screenshots a month with no card.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

FAQ

Can I save a screenshot without writing a file first?

Yes. Omit path from page.screenshot() and use the returned bytes in memory or write them with your own storage code.

Does full_page=True include the browser toolbar?

No. It covers the webpage’s scrollable document, not browser chrome.

Which browser engine should I choose?

Playwright supports Chromium, Firefox, and WebKit. Use the engine that best matches the rendering environment you need to represent, and install that engine before launching it.

Is Playwright the only Python screenshot option?

No. It is the method documented here because its Python API covers viewport, full-page, element, clipped, and byte-oriented screenshots. Other libraries may suit different automation requirements.

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

Bottom line

For a local Python script, install Playwright, navigate with page.goto(), and call page.screenshot(). Select full_page=True, a locator, or clip according to the image you actually need; choose format and scale deliberately; and treat dynamic page state as part of the capture problem. For an HTTP workflow that removes common overlays and charges only for clean shots, ScreenshotNeo is the browser-free alternative.

Frequently Asked Questions

Can I save a screenshot without writing a file first?

Yes. Omit path from page.screenshot() and use the returned bytes in memory or write them with your own storage code.

Does full_page=True include the browser toolbar?

No. It covers the webpage’s scrollable document, not browser chrome.

Which browser engine should I choose?

Playwright supports Chromium, Firefox, and WebKit. Use the engine that best matches the rendering environment you need to represent, and install that engine before launching it.

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

Is Playwright the only Python screenshot option?

No. It is the method documented here because its Python API covers viewport, full-page, element, clipped, and byte-oriented screenshots. Other libraries may suit different automation requirements.

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.