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.

Use Playwright when your HTML must look like a browser page: install the Python package and Chromium, load the markup, then call page.screenshot(). It executes JavaScript, applies browser CSS, and can save a full page, a single element, or image bytes. Use WeasyPrint instead when you need document-style pagination and PDF-like layout without a browser. The right choice depends on your CSS and JavaScript, not on an assumed speed or fidelity ranking.

Choose the renderer before writing code

Requirement Best fit Reason and limitation
Browser CSS, JavaScript, web fonts, dynamic widgets Playwright Runs a real Chromium browser. You control viewport, device scale, waits and page state. Browser binaries add installation and deployment size.
Full-page website screenshot Playwright full_page=True captures the complete page, including content below the initial viewport.
One visible component Playwright locator screenshot Captures a stable CSS-selected element. Covered content is not visible, and a scrollable element contributes only what is currently scrolled into view.
In-memory image processing Playwright without a path Returns image bytes that you can send to storage, a queue or an imaging library.
Print-oriented HTML and paginated documents WeasyPrint Its Python API lays out and paginates HTML. Check support for the HTML/CSS you use and provide a base URL for relative assets.

The official documentation does not provide a controlled Playwright-versus-WeasyPrint speed or visual-fidelity benchmark, so validate both against your actual document.

Generate a browser-rendered PNG with Playwright

1. Install Python and browser dependencies

Create a virtual environment, install Playwright, then download its browser binaries:

python -m venv .venv
# macOS/Linux
source .venv/bin/activate
# Windows PowerShell: .venvScriptsActivate.ps1
pip install playwright
playwright install

The package and browser download are separate steps. In a container or deployment image, include the browser binaries and the operating-system libraries required by Chromium. The Playwright library setup guide documents synchronous and asynchronous APIs and installation.

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

2. Load HTML and save a complete page

This runnable script renders a self-contained document and writes a PNG:

from playwright.sync_api import sync_playwright

html = """
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <style>
      body { margin: 0; font-family: Arial, sans-serif; }
      .card { width: 720px; padding: 40px; background: #f4f7fb; }
      h1 { color: #12345b; }
    </style>
  </head>
  <body>
    <main class="card">
      <h1>Hello from HTML</h1>
      <p>This page becomes a PNG.</p>
    </main>
  </body>
</html>
"""

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page(viewport={"width": 900, "height": 700})
    page.set_content(html, wait_until="load")
    page.screenshot(path="output.png", full_page=True)
    browser.close()

Playwright’s screenshot API supports PNG, JPEG and WebP. Use full_page=True for the entire document; omit it to capture only the viewport. The official screenshot documentation also documents quality controls for JPEG/WebP, CSS-pixel versus device-pixel scale, transparent backgrounds where the image type permits them, and returning bytes instead of writing a file.

3. Capture a single component

Use a stable locator when you need a card, chart or header rather than the whole page:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.set_content('<div class="header" style="padding:30px">Header</div>')
    page.locator(".header").screenshot(path="header.png")
    browser.close()

The locator must resolve to a visible, stable target. Playwright scrolls the element into view, but an overlay can cover pixels and a scrollable container is captured only at its current scroll position. If the component changes size after loading, wait for a selector, a state change or a measured condition before capturing.

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

4. Return bytes for an in-memory pipeline

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.set_content('<h1>In memory</h1>')
    image_bytes = page.screenshot(type="webp", quality=85)
    Path("output.webp").write_bytes(image_bytes)
    browser.close()

Bytes can instead be passed directly to an object-storage client, an HTTP response or Pillow. Do not set JPEG quality when requesting PNG; quality is relevant to JPEG and WebP.

Control fonts, assets and dynamic content

Wait for the page you actually want

page.set_content() returns after the requested load state, but JavaScript, images and web fonts may still be changing. For a page with a known ready marker:

page.set_content(html)
page.locator("#report-ready").wait_for(state="visible")
page.screenshot(path="report.png", full_page=True)

For network-loaded assets, wait for the relevant locator or use a deliberate short delay only when there is no observable readiness signal. A fixed delay is easy to understand but can be either wasteful or too short on a busy machine.

Make output reproducible

  • Pin the Playwright package and browser version in your deployment process.
  • Set an explicit viewport and, when needed, device_scale_factor so pixel dimensions do not depend on the host.
  • Install the same fonts everywhere; a missing font changes wrapping and therefore the image height.
  • Make external assets available and stable. For HTML strings, use absolute URLs or a controlled origin for images, stylesheets and fonts.
  • Freeze dynamic state such as clocks, randomized content and live data before capture.

Identical source HTML does not guarantee identical pixels across machines when browser versions, fonts, viewport, assets or dynamic state differ.

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

Set a dark theme or transparent background

Create the page with the desired CSS (for example, a dark color scheme), or add a class before the screenshot:

page.add_style_tag(content="body { background: #111; color: #eee; }")
page.screenshot(path="dark.png")

Transparent output is supported for applicable image types when the page background is transparent. Ensure your CSS does not paint an opaque body background if you need alpha.

Use WeasyPrint for document-style output

WeasyPrint is a Python document renderer rather than a browser automation tool. Its HTML API accepts a string, URL, filename or file object; render() lays out and paginates the document. A minimal PNG-oriented workflow is:

from weasyprint import HTML

html = """
<html>
  <body>
    <h1>Invoice</h1>
    <p>A print-oriented document.</p>
  </body>
</html>
"""

document = HTML(string=html, base_url=".").render()
# WeasyPrint is primarily a paged-document renderer; write PDF pages
# or use its documented document/page APIs for your chosen image workflow.
document.write_pdf("invoice.pdf")

When HTML is supplied as a string, pass base_url if it contains relative images, stylesheets or fonts. Confirm that the CSS and HTML features in your document are supported by your installed WeasyPrint version. Its documentation notes that long documents or specially crafted HTML can take a long time to render, so workload and asset complexity determine performance.

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

If the required deliverable is specifically a raster image of a browser application, Playwright is usually the direct path. If the deliverable is a paginated report, label sheet or invoice and JavaScript is unnecessary, evaluate WeasyPrint’s layout model first.

Common failures and fixes

“Executable doesn’t exist” or browser launch errors

Install the browser binaries with playwright install in the same environment that runs the script. In minimal Linux images, install the system dependencies listed by your Playwright setup process and verify that the runtime user can execute the browser.

The screenshot is blank or missing images

  • Use absolute asset URLs or set the correct base_url for document renderers.
  • Wait for a visible, application-specific ready selector rather than capturing immediately.
  • Check that the process can reach the asset host and that authentication cookies or headers are present.
  • Inspect the page in headed mode while debugging to see console errors and failed requests.

Fonts or layout differ between development and production

Install and pin the same font files, browser version and viewport. Avoid relying on a developer’s local font fallback. Capture only after web fonts have loaded if text metrics matter.

An element screenshot is clipped

Confirm the locator matches the intended visible element. Remove overlays, scroll the target to the desired position, and remember that a scrollable container’s screenshot reflects its currently visible scroll area rather than all of its overflow content. Use a full-page screenshot when the entire document is required.

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

Long pages take too long or consume too much memory

Reduce unnecessary DOM and image size, capture a component when a component is all you need, and avoid unbounded waits. For large document workloads, measure your real inputs; no comparative speed figure is established by the cited documentation.

Performance, reliability and output decisions

  • Startup: launching a browser and loading binaries has a larger footprint than a pure string-to-layout library. Reuse a browser process for batches, while creating isolated pages for separate jobs.
  • Page state: deterministic waits and fixed viewport settings improve repeatability more than arbitrary sleep calls.
  • Format: PNG preserves lossless detail; JPEG and WebP can reduce size and expose quality controls. Choose based on downstream storage and visual requirements.
  • Security: treat untrusted HTML and URLs as untrusted input. Restrict network access, avoid exposing credentials to page scripts, and isolate browser jobs where appropriate.
  • Validation: compare representative outputs from your production operating system, fonts, browser version and asset hosts before relying on pixel-level snapshots.
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. A single GET request returns PNG, JPEG, WebP or PDF, so your Python service does not need to install or maintain browser binaries. Cookie and consent banners are accepted and removed before capture, along with more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP tools—take_screenshot, get_page_info and capture_pdf—let Claude, Cursor and other MCP clients request captures.

Python example (see the ScreenshotNeo API 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)

The equivalent commands are:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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 includes full-page and element capture, 12 device presets plus custom viewports, retina scale, dark mode, lazy-image loading, custom CSS and JavaScript, clicks, waits, ad/tracker/request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, caching with a chosen TTL, signed links, asynchronous jobs with signed webhooks, bulk capture for 100 URLs per call, a usage API and an OpenAPI specification. Parameters commonly used by other screenshot APIs also work.

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

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; all features are available on every plan. Sign up free to start without a card.

FAQ

Can Playwright save a screenshot without creating a file?

Yes. Omit the path argument; page.screenshot() returns image bytes.

Does full-page capture include content below the fold?

Yes, set full_page=True. For a single element, capture behavior follows that element’s visibility and scroll position.

Is WeasyPrint a drop-in replacement for a JavaScript-heavy page?

No. It is intended for document layout and pagination. Test the HTML and CSS features your document requires before switching from a browser renderer.

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 creating a file?

Yes. Omit the path argument; page.screenshot() returns image bytes.

Does full-page capture include content below the fold?

Yes, set full_page=True. For a single element, capture behavior follows that element’s visibility and scroll position.

Is WeasyPrint a drop-in replacement for a JavaScript-heavy page?

No. It is intended for document layout and pagination. Test the HTML and CSS features your document requires before switching from a browser renderer.

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.