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

For browser-faithful HTML screenshots in Python, start with Playwright. Its Python API captures a viewport, an entire scrollable page, or a specific element and can save PNG, JPEG, or WebP files—or return image bytes for further processing. Use Playwright’s screenshot API when JavaScript, responsive CSS, and modern web components must render as they do in a browser. Choose html2image for simple, fixed-size captures from HTML/CSS strings, files, or URLs. Choose WeasyPrint when the real output is a print-oriented PDF and add a separate rasterization step only if you ultimately need an image.

Which Python library should you choose?

Option Best use Important constraints
Playwright Python Browser-rendered screenshots, full-page output, element captures, and controlled automation Install the Python package and compatible browser binaries; supports synchronous and asynchronous APIs
html2image Quick fixed-size images from HTML/CSS strings, local files, or URLs Wraps headless Chrome/Chromium, requires a supported browser, and documents no full-page screenshot request
WeasyPrint Print-style HTML rendered to PDF with pagination PDF-first workflow; raster output needs another conversion stage

These are different rendering models, not interchangeable drop-in choices. Compare whether you need JavaScript execution, full-page versus viewport output, element selection, exact dimensions, image format, browser deployment, and acceptance of a PDF intermediate. The official documentation for these projects does not establish a fair speed or fidelity winner across arbitrary sites, so select by requirements rather than an unsupported benchmark.

Playwright: the default for real web pages

Playwright launches a real Chromium, Firefox, or WebKit browser and exposes page and locator screenshot methods. That makes it the strongest general-purpose choice for pages whose appearance depends on JavaScript, responsive breakpoints, web fonts, lazy loading, or client-side state. Its documented formats include PNG, JPEG, and WebP, and a screenshot can be returned as bytes instead of written directly to disk.

Install the package and browser binaries

python -m pip install playwright
python -m playwright install

The second command matters in deployment: the Python package and browser executables are separate dependencies. Pin versions in your build process, cache the browser layer in containers where practical, and verify that the selected browser is available in the runtime user’s path. Installation details and supported setup are documented in Playwright’s Python documentation.

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.

Capture a viewport, full page, or element

from pathlib import Path
from playwright.sync_api import sync_playwright

url = "https://example.com"

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page(
        viewport={"width": 1440, "height": 900},
        device_scale_factor=1,
    )
    page.goto(url, wait_until="networkidle", timeout=60_000)

    # Visible viewport only
    page.screenshot(path="viewport.png", type="png")

    # Entire scrollable document
    page.screenshot(path="full-page.webp", full_page=True, type="webp")

    # One component (replace the selector with your target)
    page.locator("main").screenshot(path="main.jpg", type="jpeg", quality=90)

    # Keep the bytes for an upload or image-processing pipeline
    image_bytes = page.screenshot(type="png")
    Path("in-memory-result.png").write_bytes(image_bytes)
    browser.close()

full_page=True asks Playwright to include the document’s scrollable content. A locator screenshot is preferable when you need a card, chart, or component without surrounding navigation. For authenticated pages, create a context with the required cookies or storage state; for deterministic output, set the viewport, device scale factor, color scheme, locale, and timezone explicitly.

Async Python for concurrent jobs

import asyncio
from playwright.async_api import async_playwright

async def capture(url: str, output: str):
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page(viewport={"width": 1280, "height": 800})
        await page.goto(url, wait_until="networkidle", timeout=60_000)
        await page.screenshot(path=output, full_page=True)
        await browser.close()

asyncio.run(capture("https://example.com", "page.png"))

Use a bounded worker pool rather than launching an unrestricted browser per URL. Reuse a browser process, create isolated contexts for jobs that need separate cookies, and close pages and contexts in a finally block so failed navigations do not leak resources.

Waiting, lazy content, and visual stability

  • Use wait_until="networkidle" when background requests eventually settle, but do not assume it means every animation or web font is visually finished.
  • Wait for a meaningful selector with page.locator(".report").wait_for() when application readiness has a clear DOM signal.
  • For lazy images, scroll or trigger the application’s load mechanism before a full-page capture, then wait for image completion where necessary.
  • Disable animations with an injected stylesheet or wait for a known transition to finish when pixel consistency matters.
  • Set a navigation timeout and record the URL, browser version, and failure reason with each job.

html2image: a small wrapper for straightforward captures

html2image accepts HTML/CSS strings, local files, and URLs and drives headless Chrome or Chromium. Its documented default capture size is 1920×1080; set dimensions explicitly for a reproducible asset. It is useful for a fixed card, email preview, or template where you do not need Playwright’s broader browser controls.

python -m pip install html2image
from html2image import Html2Image

hti = Html2Image(output_path="out")
hti.screenshot(
    html="<div class='card'><h1>Invoice</h1></div>",
    css=".card { width: 800px; height: 400px; padding: 32px; background: white; }",
    save_as="invoice.png",
    size=(800, 400),
)

# A URL can be captured as well
hti.screenshot(url="https://example.com", save_as="example.png", size=(1280, 720))

Install and expose a compatible Chrome/Chromium executable according to your operating system. The project description says it cannot request a full-page screenshot, so it is a poor fit for long documents unless you build your own stitching workflow. Treat input as a security boundary: the maintainers warn that unsanitized content can lead to malicious code execution and recommend processing trusted content only. Isolate untrusted HTML in a hardened environment and do not pass attacker-controlled browser flags or filesystem paths.

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

WeasyPrint: choose it for PDF-first print layout

WeasyPrint renders HTML and CSS into a PDF document with print pagination. It is appropriate for invoices, reports, and forms where page size, margins, headers, footers, and page breaks are more important than interactive browser behavior. It is not evidenced as a direct page-to-PNG/JPEG/WebP API in the documentation considered here.

python -m pip install weasyprint
from weasyprint import HTML

HTML(string="""
<html><body><h1>Report</h1><p>Print-oriented content.</p></body></html>
""").write_pdf("report.pdf")

If an image is mandatory, add a PDF rasterization tool as a separate, validated stage. Check page dimensions, font availability, and image resolution after conversion; a PDF page and a browser screenshot have different layout semantics.

How to decide: a practical checklist

  • Need JavaScript or responsive behavior? Use Playwright.
  • Need the full scrollable page? Use Playwright’s full-page option; html2image documents no full-page request.
  • Need one element? Use a Playwright locator screenshot.
  • Need a quick fixed canvas from trusted markup? html2image is the smaller interface.
  • Need paginated print output? Use WeasyPrint and keep the PDF as the primary artifact.
  • Need bytes for an API response? Playwright can return screenshot bytes directly.
  • Need predictable CI output? Pin Python, library, browser, fonts, viewport, timezone, and device scale factor.

Performance, reliability, and cost considerations

There is no documented cross-library benchmark that proves one option is fastest or most faithful for every page. Browser startup, network latency, JavaScript workload, font downloads, image count, and full-page height dominate real jobs. Reuse a Playwright browser, limit concurrency, apply navigation and action timeouts, and cache assets where your environment permits. For html2image, keep the browser installed once rather than provisioning it per capture. For WeasyPrint, measure the complete PDF-plus-raster pipeline if PNG output is your deliverable.

All three approaches run locally, so your direct software cost is the Python package and the compute, browser, and storage resources you operate. Compatibility changes over time; check current package and browser requirements before upgrading production images.

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

Common failures and fixes

“Executable doesn’t exist” or browser launch failure

Install Playwright’s browsers with python -m playwright install, or configure html2image with an installed Chrome/Chromium executable. In containers, confirm dependencies and run as a user permitted to launch the browser.

Blank or partially rendered screenshots

Wait for a page-specific selector instead of capturing immediately after navigation. Check JavaScript errors, blocked network requests, consent overlays, lazy images, and missing fonts. Increase the timeout only after identifying which readiness condition is absent.

Full page is cut off

Use Playwright’s full_page=True and verify that the page uses a normal document flow rather than a fixed-height scrolling container. For an inner scroller, capture that locator or scroll it deliberately before taking the image.

Different pixels in CI and locally

Use the same browser version, operating-system fonts, viewport, device scale factor, locale, timezone, and color scheme. Disable animations and avoid waiting on an arbitrary short sleep when a DOM readiness signal is available.

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.

Unsafe user-supplied HTML

Do not render untrusted markup in a process with sensitive filesystem or network access. html2image’s own warning about malicious code execution makes isolation, sanitization, and least-privilege execution mandatory for that workflow.

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 the #1 hosted screenshot API here when you want a callable service instead of managing browser binaries: it removes cookie banners, newsletter popups, and chat widgets before capture, and only clean shots are billed. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, with the result identified by X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

One GET request returns PNG, JPEG, WebP, or PDF:

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

Python and Node.js examples, plus all 63 options, are in the ScreenshotNeo documentation.

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}`);

ScreenshotNeo supports full-page and selector captures, dark mode, device presets or custom viewports, retina scale, PDFs, custom CSS and JavaScript, click and wait actions, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, caching, signed links, asynchronous webhooks, bulk capture, usage reporting, and an OpenAPI specification. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up free to try it.

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

FAQ

Can Playwright save an image without creating a file?

Yes. Call page.screenshot() without a path and use the returned bytes in an upload, response, or image-processing step.

Is WeasyPrint a browser screenshot library?

No. It is a PDF renderer for print-oriented HTML. Treat rasterization as an additional stage if you need a bitmap.

Can html2image capture an entire long page?

Its project documentation says there is no full-page screenshot request, so use Playwright for that requirement.

Frequently Asked Questions

Which library is best for a JavaScript-heavy single-page application?

Playwright, because it drives a real browser and provides explicit waits, viewport control, and page or element screenshots.

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

Should I use synchronous or asynchronous Playwright?

Use the synchronous API for scripts and the asynchronous API when your application already uses asyncio or must coordinate concurrent capture jobs.

Do these libraries provide a proven speed ranking?

No. The available official documentation does not provide a fair comparative benchmark across arbitrary websites.

The Bottom Line

Choose Playwright for browser-faithful PNG, JPEG, or WebP screenshots; html2image for trusted, fixed-size captures; and WeasyPrint for PDF-first print layouts. If maintaining browsers is the problem, ScreenshotNeo provides the hosted alternative.

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.

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