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.

The most dependable way to save a webpage as an image in Python is to render it in a real browser with Playwright, wait for the state you need, and call page.screenshot(). Use full_page=True for the entire scrollable document, a locator screenshot for one component, or omit path when you need the image bytes in memory.

This guide builds a runnable script, explains viewport and full-page captures, covers PNG, JPEG and WebP output, and shows how to make dynamic pages more repeatable.

What you need before writing the script

  • Python 3.8 or newer is a practical baseline for current Playwright releases.
  • A virtual environment keeps the browser automation package separate from other projects.
  • Playwright’s browser binaries must be installed once after installing the Python package.
  • A reachable webpage and a location where your process can write the resulting image.

Create and activate an environment, then install Playwright:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
python -m venv .venv
# macOS/Linux
source .venv/bin/activate
# Windows PowerShell
.venvScriptsActivate.ps1

python -m pip install playwright
python -m playwright install

The final command downloads the browser binaries used by Playwright. In a minimal Linux container you may need the operating system dependencies as well; run python -m playwright install --with-deps when your environment permits it.

#1 Best Overall
Sale
Philips 24 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 241V8LB
  • CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
  • WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
  • A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents

A complete Python webpage screenshot

This synchronous example opens a URL, waits for the page load event, captures the full document, and closes the browser even if an error occurs:

from pathlib import Path
from playwright.sync_api import sync_playwright

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

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page(viewport={"width": 1440, "height": 900}, device_scale_factor=1)
    try:
        page.goto(URL, wait_until="load", timeout=30_000)
        page.screenshot(path=str(OUTPUT), full_page=True)
    finally:
        browser.close()

print(f"Saved {OUTPUT.resolve()}")

page.goto() navigates the browser. wait_until="load" waits for the document’s load event, but it does not guarantee that client-rendered data, fonts, animations or lazy images are finished. Choose a more specific readiness condition when the site needs one.

Visible viewport versus the complete document

Without full_page=True, Playwright captures the currently visible viewport (here, 1,440 × 900 CSS pixels). With it, Playwright expands the capture to the page’s full scrollable height. A very long page can produce a very tall image, so consider an element capture or a PDF for documents that are thousands of pixels high.

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

Save to a file or keep bytes in memory

The path argument writes the image to disk. If you omit it, page.screenshot() returns bytes, which you can upload, hash, resize or pass to an image library without creating an intermediate file:

from io import BytesIO
from PIL import Image
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", wait_until="domcontentloaded")
    image_bytes = page.screenshot(type="webp", quality=82)
    image = Image.open(BytesIO(image_bytes))
    print(image.size)
    browser.close()

Install Pillow separately if you use that example: python -m pip install pillow.

Capture one element instead of the whole page

Use a locator when you need a header, chart, card or other component. The locator must resolve to the element you intend to capture:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page(viewport={"width": 1280, "height": 800})
    page.goto("https://example.com", wait_until="domcontentloaded")
    page.locator("header").screenshot(path="header.png")
    browser.close()

A locator screenshot follows the element’s rendered bounding box. For a selector that appears later, wait for it first:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB
  • CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
  • SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
page.locator(".report-card").wait_for(state="visible", timeout=30_000)
page.locator(".report-card").screenshot(path="report-card.png")

Choose format, quality and pixel scale

PNG, JPEG or WebP

  • PNG: the default inferred when the filename ends in .png; it preserves sharp text and supports transparency.
  • JPEG: useful for photographic pages and smaller files; it does not support transparency.
  • WebP: a compact modern format. Set quality when using lossy WebP.

You can make the format explicit, which is helpful when returning bytes:

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

The quality option applies to JPEG and WebP, not PNG. Lower values generally reduce file size at the cost of visible compression.

CSS pixels versus device pixels

The scale screenshot option controls output dimensions. scale="css" keeps one output pixel per CSS pixel and produces smaller high-DPI captures; scale="device" uses device pixels and produces a denser image. You can also set the browser context’s device_scale_factor:

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page(viewport={"width": 1200, "height": 800}, device_scale_factor=2)
    page.goto("https://example.com")
    page.screenshot(path="retina.png", scale="device")
    browser.close()

Use a known viewport and scale when comparing screenshots in tests. A different viewport can change responsive layout, line wrapping and lazy-loading behavior.

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

Transparent backgrounds

Set omit_background=True to preserve transparency where the page supports it. This option does not apply to JPEG, so use PNG or WebP for transparent output:

page.screenshot(path="transparent.png", omit_background=True)

Wait for the page state that matters

There is no universal “ready” signal for every website. Pick a condition tied to the content you need:

Wait for a specific element

page.goto("https://example.com/dashboard", wait_until="domcontentloaded")
page.locator("[data-testid='dashboard-loaded']").wait_for(state="visible")
page.screenshot(path="dashboard.png", full_page=True)

Wait for a short, known delay

page.goto("https://example.com", wait_until="load")
page.wait_for_timeout(1_500)
page.screenshot(path="after-delay.png")

A fixed delay is simple but can be too short on a slow run and wasteful on a fast one. Prefer a selector or application-specific signal when possible.

Rank #3
Sale
Dell 24 Monitor - SE2426H - 23.8-inch FHD (1920x1080) 144Hz 1ms Display, in-Plane Switching (IPS) Technology, AMD FreeSync™, TÜV 3-Star 2X HDMI, Tilt
  • Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
  • Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
  • Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
  • In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
  • Ultra-thin bezels: Maximize your viewing experience with thin bezels.

Reduce animation differences

Animations can make two captures differ. Playwright’s screenshot API provides animation control; disabling animations for the capture is useful for visual comparisons:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
page.screenshot(path="stable.png", animations="disabled")

If a site changes content after navigation, wait for that site’s network or application signal rather than assuming the load event means all data is complete.

Use the screenshot timeout deliberately

The documented screenshot timeout default is 30 seconds. Set a value appropriate for your job and catch timeout errors so a batch process can report the URL that failed:

page.set_default_timeout(30_000)
page.set_default_navigation_timeout(45_000)
try:
    page.goto("https://example.com", wait_until="networkidle")
    page.screenshot(path="capture.png", timeout=30_000)
except Exception as exc:
    print(f"Capture failed: {exc}")

networkidle can be a poor choice for pages with analytics, ads or persistent connections. A visible application element is often more reliable.

Reusable script with command-line arguments

This version accepts a URL, output path and optional full-page flag, making it suitable for a small utility or CI job:

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

def capture(url: str, output: Path, full_page: bool) -> None:
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page(viewport={"width": 1440, "height": 900})
        try:
            page.goto(url, wait_until="domcontentloaded", timeout=45_000)
            page.screenshot(
                path=str(output),
                full_page=full_page,
                animations="disabled",
                timeout=30_000,
            )
        finally:
            browser.close()

parser = argparse.ArgumentParser()
parser.add_argument("url")
parser.add_argument("-o", "--output", default="screenshot.png")
parser.add_argument("--full-page", action="store_true")
args = parser.parse_args()

try:
    capture(args.url, Path(args.output), args.full_page)
    print(f"Saved {args.output}")
except PlaywrightTimeoutError as exc:
    raise SystemExit(f"Timed out while loading or capturing {args.url}: {exc}")

Run it with python capture.py https://example.com --full-page -o example.png. Validate URLs and output directories before using this utility with untrusted input.

Common failures and precise fixes

“Executable doesn’t exist” or browser launch failure

Install the browser binaries after installing the package: python -m playwright install. On supported Linux images, add --with-deps if system libraries are missing.

Rank #4
Samsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor
  • CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
  • SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
  • MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
  • KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
  • INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient

The screenshot is blank or incomplete

Check that navigation actually reached the expected URL, then wait for a content selector instead of capturing immediately. For lazy content, scroll or use the page’s own load signal before taking a full-page shot. A blank result can also indicate a site-side bot check or an application error rather than a Python problem.

Timeout during navigation

Increase the navigation timeout for a slow site, use wait_until="domcontentloaded" instead of waiting for every network request, and identify a selector that proves the required content is ready. Log the final URL and exception text.

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.

Element locator matches nothing

Inspect the selector, wait for the element, and account for iframes. Content inside an iframe must be addressed through the appropriate frame rather than the top-level page. A locator that matches multiple elements may need a more specific selector or an explicit .first.

Fonts, layout or colors differ between runs

Use the same browser engine, viewport, device scale factor and color scheme. Wait for the relevant fonts and data, disable animations, and avoid capturing while a responsive breakpoint is changing. Containerized runs may render fonts differently if the required font is not installed or loaded by the page.

The output file is unexpectedly huge

Use JPEG or WebP with an appropriate quality value, capture only the needed element, reduce the viewport or use scale="css". Full-page PNGs preserve detail but can become very large on long documents.

Permission denied when writing

Write to a directory owned by the process and create it first with Path(output).parent.mkdir(parents=True, exist_ok=True). Avoid relying on the current working directory in services; use an explicit absolute path.

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.

Operational notes for reliable batches

  • Launch one browser and create a fresh page or context per job when processing several URLs; this avoids paying browser startup cost for every capture while keeping page state isolated.
  • Set explicit navigation and screenshot timeouts, record the URL and final address, and retain the exception text for retries.
  • Use a bounded concurrency level. Too many simultaneous pages can exhaust CPU, memory or network bandwidth and make captures less reliable.
  • Save to a temporary filename and rename it after a successful screenshot so downstream readers never consume a partial file.
  • Respect access controls, robots policies, authentication requirements and the website’s terms. Do not place credentials in URLs or source code; use Playwright context headers or secrets management where appropriate.
  • For visual regression, pin browser versions in your environment and compare captures at identical viewport, scale and color settings.
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 is a hosted screenshot API and MCP server. It accepts a URL in one GET request and returns 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 switched off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the page verdict and billing result in X-Page-Verdict and X-Billed headers.

Use the documented API examples at https://screenshotneo.com/docs/:

Best Value
Sale
Sceptre New 22-Inch Gaming Monitor, FHD 1080p, Up to 144Hz, HDMI, DisplayPort, Built-in Speakers, Machine Black (E225W-FW144 Series, 2026)
  • 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
  • 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
  • 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

It also supports full-page and element captures, dark mode, device presets and custom viewports, retina scale, PDF paper and page options, custom CSS and JavaScript, click and wait rules, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, selectable cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture for 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. Its MCP server provides take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients.

Pricing is Free for 1,000 shots per month with no card, then 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 gives two months free, and every feature is included on every plan. Sign up free to get 1,000 screenshots a month without a card.

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

Frequently asked questions

Can Python save a screenshot without opening a visible browser window?

Yes. Playwright launches Chromium headlessly when you pass headless=True (the default in the examples), while still rendering the page through a browser engine.

Why is my full-page image extremely tall?

Full-page mode includes the document’s entire scrollable height. Capture a specific locator, split the page into sections, or produce a PDF when a single tall bitmap is impractical.

Should I use Selenium instead?

The procedure here uses Playwright because its current Python documentation directly covers full-page, locator, in-memory and format-specific screenshot options. Selenium behavior and code should be checked against the version and driver you deploy rather than copied from older examples.

How can I send the screenshot to an HTTP response?

Omit path, keep the returned bytes, and send them with the appropriate image media type from your web framework. This avoids a temporary file and lets the caller choose how to store the result.

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

Frequently Asked Questions

Can Python save a screenshot without opening a visible browser window?

Yes. Playwright launches Chromium headlessly when you pass headless=True (the default in the examples), while still rendering the page through a browser engine.

Why is my full-page image extremely tall?

Full-page mode includes the document’s entire scrollable height. Capture a specific locator, split the page into sections, or produce a PDF when a single tall bitmap is impractical.

Should I use Selenium instead?

The procedure here uses Playwright because its current Python documentation directly covers full-page, locator, in-memory and format-specific screenshot options. Selenium behavior and code should be checked against the version and driver you deploy rather than copied from older examples.

How can I send the screenshot to an HTTP response?

Omit path, keep the returned bytes, and send them with the appropriate image media type from your web framework. This avoids a temporary file and lets the caller choose how to store the result.

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

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.