Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
browser automation

How to Screenshot Webpages as PNG in Python (Playwright Guide)

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

Use Playwright’s Python API: install the package and browser binaries, open the URL in a headless browser, then call page.screenshot(path="screenshot.png"). PNG is Playwright’s default screenshot format, so this saves a rendered page as a PNG without image-conversion code.

This guide covers viewport and full-page captures, element screenshots, synchronous and asynchronous programs, reproducibility, common failures, and a hosted alternative when you do not want to maintain browser binaries.

Install Playwright and its browsers

Playwright needs two installations: the Python package and the browser binaries that it controls. Run both commands in the environment where your script will execute:

pip install playwright
playwright install

The second command downloads the browsers. Playwright supports Chromium, Firefox and WebKit; launching Chromium is the shortest path for a standard PNG capture.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

Save a webpage as a PNG

Create a file such as capture.py with this synchronous example:

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="screenshot.png")
    browser.close()

Run it with python capture.py. The browser runs headless by default, page.goto() loads the address, and the screenshot is written relative to the process’s current directory. Supply an absolute path if another process must find the file reliably:

page.screenshot(path="/tmp/example-home.png")

Use a URL you are authorized to access. A successful navigation does not prove that every image, chart or client-rendered component has reached its final state; choose a wait condition that matches the page, as described below.

Choose the capture area

Viewport screenshot

With no extra options, Playwright captures the currently visible viewport. Set its dimensions when the responsive breakpoint matters, and do so before navigation:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page(viewport={"width": 1440, "height": 900})
    page.goto("https://example.com")
    page.screenshot(path="desktop.png")
    browser.close()

Creating the page with a fixed viewport makes desktop, tablet or mobile layouts predictable. For phone emulation, establish the viewport before calling goto, otherwise the page may have already selected a different responsive layout.

Full scrollable page

Pass full_page=True to include the page’s entire scrollable height:

page.screenshot(path="full-page.png", full_page=True)

Very long documents can produce large images and consume more memory. If you only need a visible section, an element capture is usually smaller and easier to process.

One element

Locate the component with a CSS selector (or another Playwright locator) and call its screenshot method:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
card = page.locator("article.product-card").first
card.screenshot(path="card.png")

The locator must resolve to an element that is present and visible. If the selector matches several nodes, select the intended one with .first, .nth(index) or a more specific selector.

Control PNG output and image fidelity

PNG, JPEG and WebP

PNG is the documented default. You can request another format when storage or transfer size matters:

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

The quality option applies to JPEG and WebP, not PNG. Keep PNG when you need lossless text, transparency or pixel comparison.

CSS pixels versus device pixels

Screenshot scale controls whether output follows CSS pixels or device pixels. scale="css" keeps high-density captures smaller; scale="device" preserves the device-pixel dimensions and can create a larger file:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
page.screenshot(path="css-scale.png", scale="css")
page.screenshot(path="device-scale.png", scale="device")

Choose one scale consistently if images are compared in tests or committed as visual baselines.

Hide or restyle unstable content

The screenshot API accepts a stylesheet option. You can hide clocks, rotating banners or other elements that make repeated captures differ:

page.screenshot(
    path="stable.png",
    style=".live-clock, .carousel { visibility: hidden !important; }"
)

This changes only the capture’s presentation. It does not alter your production site.

Wait for the content you actually need

Playwright’s screenshot API documents a default timeout of 30,000 milliseconds. Navigation finishing is not a universal signal that lazy images, charts or client-side data are ready. Use a targeted wait that represents the page state required by your image.

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

Wait for a selector

page.goto("https://example.com/dashboard")
page.wait_for_selector("main.dashboard-ready")
page.screenshot(path="dashboard.png")

Wait for a fixed delay

page.goto("https://example.com/animation")
page.wait_for_timeout(1500)
page.screenshot(path="animation.png")

A delay is simple but tied to one site’s timing. Prefer a selector or another observable condition when possible.

Use network idle carefully

page.goto("https://example.com", wait_until="networkidle")
page.screenshot(path="network-idle.png")

Pages with analytics, polling or streaming connections may never become truly idle. In those cases, wait for the specific content instead of making network idle your only readiness test.

Disable animation for repeatable images

Combine a stylesheet that turns off transitions and animations with a deterministic viewport and wait condition:

page.screenshot(
    path="comparison.png",
    style="*, *::before, *::after { animation: none !important; transition: none !important; }"
)

Capture in an asyncio application

If your program already uses asyncio, use Playwright’s asynchronous API rather than blocking the event loop:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page(viewport={"width": 1280, "height": 800})
        await page.goto("https://example.com")
        await page.screenshot(path="async-shot.png", full_page=True)
        await browser.close()

asyncio.run(main())

Every browser, page and navigation operation is awaited. Keep the synchronous API for scripts and worker code that does not run inside an event loop.

Capture bytes instead of writing a file

Omit path and the screenshot method returns image bytes. This is useful for HTTP responses, object storage or an image-processing pipeline:

png_bytes = page.screenshot(full_page=True)
with open("in-memory-copy.png", "wb") as output:
    output.write(png_bytes)

The same pattern works with the asynchronous method by awaiting it.

A production-ready example

This script fixes the viewport, waits for a page-specific marker, disables motion and uses an explicit timeout:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from pathlib import Path
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeoutError

URL = "https://example.com"
OUTPUT = Path("artifacts/example.png")

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page(viewport={"width": 1366, "height": 900})
    page.set_default_timeout(30_000)
    try:
        page.goto(URL, wait_until="domcontentloaded", timeout=30_000)
        page.wait_for_selector("body", state="visible")
        page.screenshot(
            path=str(OUTPUT),
            full_page=True,
            scale="css",
            style="*, *::before, *::after { animation: none !important; transition: none !important; }",
        )
    except PlaywrightTimeoutError as exc:
        raise RuntimeError(f"Timed out while capturing {URL}") from exc
    finally:
        browser.close()

Create the artifacts directory before running this version, or change the output path to an existing directory. Replace the body wait with a selector that proves your application’s data is ready.

Troubleshoot common failures

“Executable doesn’t exist” or browser launch errors

The Python package is installed but the browser binaries are missing. Run playwright install in the same environment, container image or virtual environment that runs the script. In restricted build systems, install the binaries during image creation rather than at request time.

The file is blank or missing page content

Check the URL, wait for a page-specific selector and inspect whether the site requires a login, consent interaction or JavaScript data request. A completed navigation alone does not guarantee that late content has rendered.

Timeouts

The documented screenshot timeout is 30 seconds by default. Slow pages, blocked resources and selectors that never appear can all trigger it. Increase the timeout only when the site genuinely needs longer; first verify the selector and URL, and use a narrower readiness condition than perpetual network activity.

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

Only the visible portion was captured

Add full_page=True. If you need one component rather than the whole document, use a locator screenshot instead.

Mobile layout is wrong

Set the viewport before goto. A desktop-sized initial viewport can cause the site to select desktop CSS before you resize it.

Images or animations differ between runs

Fix the viewport and screenshot scale, wait for the content that matters, and disable animations or hide changing selectors with the stylesheet option. Avoid assuming a universal delay works for every site.

Output cannot be opened

Confirm that the parent directory exists and that your process can write to it. When returning bytes from a web service, send the PNG bytes with an image/png content type rather than treating them as text.

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

Playwright, Selenium and a hosted API

Playwright is the best default when you need current browser automation, full-page or element captures, sync or asyncio integration, and control over viewport, scale and repeatability. Selenium can be reasonable when your project already uses it, but the Selenium Python Bindings PDF located for this topic is a Release 2 reference. Its screenshot method names should therefore be checked against current Selenium documentation before you copy them into a new project.

Choose a hosted service when downloading browsers, handling concurrency and maintaining a rendering environment are more work than the screenshot itself. Compare options by the browser stack you need, whether captures are viewport, full-page or element-specific, how much page-state control is exposed, and how failures are reported.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP or PDF, so Python code does not need to install or launch Playwright browsers. Its clean-shot workflow accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each step can be disabled.

Only clean shots are billed. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and response headers identify the page verdict and whether the request was billed. An MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.

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

For Python, use the API call below (the complete parameter reference is in the ScreenshotNeo documentation):

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)

The API supports full-page captures with lazy images loaded, CSS-selector element captures, dark mode, 12 device presets or any viewport, retina scale, PDF paper and page-range controls, custom CSS and JavaScript, pre-capture clicks, hidden selectors, waits for selectors, delays or network idle, request and resource blocking, custom headers, cookies, user agents and Authorization, timezone and geolocation, transparent backgrounds, image resizing, user-selected cache TTLs, signed public-image links, 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 are accepted to ease migration.

Pricing starts with 1,000 screenshots per month free without a card. Paid plans are Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000 and Business $249 for 1,000,000; yearly billing provides two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to try the 1,000 monthly shots without a card.

Operational checklist

  • Install both playwright and its browser binaries.
  • Set the viewport before navigation when responsive layout matters.
  • Choose viewport, full-page or locator capture deliberately.
  • Use PNG unless JPEG/WebP size or quality controls are required.
  • Pick CSS-pixel or device-pixel scale and keep it consistent.
  • Wait for the content your use case needs, not merely for navigation to finish.
  • Disable motion and hide unstable selectors for visual comparisons.
  • Close the browser in a finally block in long-running or failure-prone jobs.

Frequently Asked Questions

Can Playwright save a screenshot directly as PNG?

Yes. PNG is the default screenshot type, and page.screenshot(path="screenshot.png") writes the image directly.

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.

How do I return the screenshot from a Python web endpoint?

Omit path so Playwright returns bytes, then send those bytes with an image/png response type.

Which Playwright browser should I launch?

Chromium is a practical default; Playwright also provides Firefox and WebKit when your compatibility target requires them.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

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

Read next

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.