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.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Use Playwright’s Python API when you need a browser-faithful PNG. Launch a browser, load your HTML or URL, and call page.screenshot(path="output.png"). Add full_page=True for the complete scrollable document, or capture a specific element through a locator. Playwright can also return PNG bytes for in-memory processing.

What “render HTML to PNG” means

Rendering HTML to PNG normally means asking a browser engine to lay out the HTML and CSS, execute the page’s JavaScript, load its assets, and capture the resulting pixels. This is different from parsing markup or converting text: browser layout, fonts, responsive rules, images, and scripts all affect the image.

Playwright controls Chromium, Firefox, and WebKit through one Python API. Its screenshot method supports PNG, JPEG, and WebP output, viewport or full-page captures, element screenshots, and returning image data instead of writing a file.

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

Set up a Playwright rendering environment

Install the Python Playwright package and the browser binaries required by the browser you intend to run. Use the current official Playwright installation instructions for your operating system, Python version, and deployment target; browser downloads and system-library requirements vary by platform.

In production, keep browser and page creation inside a managed lifecycle so the browser closes when work succeeds or fails. The synchronous example below uses a context manager and therefore closes resources at the end of the block.

Render an HTML string to a PNG file

This is the smallest complete workflow for HTML held in a Python string:

from playwright.sync_api import sync_playwright

html = """


  
    
    
  
  
    

Hello, world!

This paragraph is rendered by a browser and saved as PNG.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
""" with sync_playwright() as p: browser = p.chromium.launch() page = browser.new_page(viewport={"width": 1280, "height": 800}) page.set_content(html) page.screenshot(path="output.png", full_page=True) browser.close()

The viewport controls the CSS layout width and height. full_page=True expands the capture to the page’s full scrollable height instead of taking only the visible viewport.

Capture only the viewport

Omit full_page (or leave it false) when you want exactly the current viewport:

page.screenshot(path="viewport.png")

Capture one element

Use a stable CSS selector and a locator screenshot when the output should contain a card, chart, invoice, or other component rather than the entire page:

card = page.locator("#invoice")
card.screenshot(path="invoice.png")

A selector that matches nothing, matches an unintended element, or points to a component that has not been rendered will cause failures or an incorrect image. Prefer stable IDs, data attributes, or other selectors intended for automation.

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

Load a remote URL or local document

Remote URL

Navigate with page.goto before taking the screenshot:

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="example.png", full_page=True)
    browser.close()

For JavaScript applications, navigation finishing does not necessarily mean the useful content is ready. Wait for a selector that identifies the completed state, a page condition your application controls, or an appropriate delay. There is no universal wait value: dashboards, animations, third-party resources, and server rendering behave differently.

Local files and generated markup

For generated content, page.set_content(html) avoids creating a temporary file. If your application already produces a local document, load it through the browser using the file URL appropriate to your environment, then capture it. Ensure referenced stylesheets, fonts, images, and scripts are reachable from that location.

Control PNG output and image data

Save to disk or keep bytes in memory

Passing path writes the image. If you omit it, Playwright returns image bytes:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
png_bytes = page.screenshot(full_page=True)
# Pass png_bytes to an image library, object storage client, or HTTP response.

PNG is lossless and does not use a quality setting. The same API can produce JPEG or WebP when a smaller file is more important than lossless output; choose the format through the screenshot options documented by Playwright.

CSS pixels and device pixels

Screenshots can use CSS-pixel scale or device-pixel scale. A higher device scale produces a denser image but also increases memory and file size. Set the browser context or page scale deliberately when output dimensions must match a design specification.

Transparent backgrounds

Transparent capture is supported in the cases documented by Playwright. It is useful for isolated components, but page-level backgrounds, opaque containers, and images can still make the result appear non-transparent.

Make dynamic pages deterministic

  • Set the viewport: responsive breakpoints change layout when width changes.
  • Wait for meaningful readiness: target a selector or application state rather than guessing a delay.
  • Account for fonts and assets: missing fonts or blocked images change wrapping and dimensions.
  • Disable motion when appropriate: animations can capture halfway through a transition; use page-level CSS or application settings to make visual tests stable.
  • Close every browser: leaked browser processes eventually exhaust memory in a worker or web service.

For long pages, full-page screenshots can require substantial memory. Capture only the needed element or viewport when possible, and process returned bytes without making unnecessary copies.

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

Async Python version

For an asynchronous application, use Playwright’s async API and await navigation and capture:

import asyncio
from playwright.async_api import async_playwright

async def render():
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page(viewport={"width": 1280, "height": 800})
        await page.set_content("<h1>Async HTML</h1>")
        await page.screenshot(path="async-output.png", full_page=True)
        await browser.close()

asyncio.run(render())

When WeasyPrint is appropriate

WeasyPrint is a document renderer often chosen for print-oriented output. Version matters: the current stable documentation identified for this work is version 70.0 and documents PDF output, while historical version 52.5 documentation includes a write_png API. Do not copy a historical write_png example into a current project without confirming that exact version’s supported API.

Choose Playwright when JavaScript behavior, browser CSS, responsive layout, or browser-level fidelity matters. Consider a document renderer only after checking its version-specific output path and verifying the resulting visuals against your target HTML. Rendering behavior can change between releases, so pin and review versions in automated pipelines.

Troubleshooting common failures

The browser executable is missing

Cause: the Python package is installed but its browser binaries are not available in the runtime image or user account.

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.

Fix: install the browser supported by your deployment using the current Playwright setup instructions, and include required operating-system libraries in the container or host image.

The PNG is blank or captured too early

Cause: the page’s JavaScript or data request has not completed.

Fix: wait for a selector representing loaded content or for an application-specific ready condition. Check that requests, fonts, and images are not blocked.

Images or fonts are missing

Cause: asset URLs are inaccessible from the browser, require authentication, or resolve differently from the source process.

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

Fix: verify each URL from the rendering environment, provide required authentication through your application’s normal mechanism, and wait for the assets before capture.

The full-page image has the wrong size

Cause: viewport dimensions, responsive breakpoints, or late layout changes differ from expectations.

Fix: set an explicit viewport, wait until content has settled, and inspect the page’s scroll dimensions. Use an element screenshot when the document’s extra whitespace is not part of the requirement.

A locator screenshot fails

Cause: the selector is invalid, the element is absent, or it is hidden.

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

Fix: confirm the selector in the rendered page, wait for the element’s visible state, and use a stable selector rather than a generated class name.

Output differs after an upgrade

Cause: browser engines, fonts, and renderer versions affect layout.

Fix: pin versions for repeatable builds, regenerate visual baselines deliberately, and compare output after every browser or rendering-library upgrade.

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 provides a hosted screenshot API. It removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf.

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

One GET request returns PNG, JPEG, WebP, or PDF. The same service supports full-page and CSS-selector captures, device presets, custom viewport and retina scale, waits, custom CSS and JavaScript, clicks, hidden selectors, request blocking, headers, cookies, user agents, authorization, geolocation, time zones, transparent backgrounds, resizing, selectable-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, usage reporting, and an OpenAPI specification.

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

See the ScreenshotNeo documentation for request options and response headers. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

FAQ

Can Playwright render HTML without opening a visible window?

Yes. Playwright’s browser launch is suitable for headless automation; the screenshot API works without a desktop display.

Should I use a screenshot or a PDF renderer for invoices?

Use a screenshot when you need browser pixels. For print-oriented documents, evaluate a PDF-focused renderer and verify its version-specific output before choosing a PNG path.

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

Can I return the PNG directly from a web endpoint?

Yes. Omit the screenshot path, return the resulting bytes with an image/png content type, and ensure the browser lifecycle is closed after the request.

Frequently Asked Questions

Can Playwright render HTML without opening a visible window?

Yes. Playwright supports headless browser automation, so screenshots can be produced on servers without a desktop display.

Should I use a screenshot or a PDF renderer for invoices?

Use Playwright when you need browser pixels; evaluate a PDF-focused renderer for print-oriented documents and confirm its version-specific PNG support.

Can I return the PNG directly from a web endpoint?

Yes. Omit the path, return the screenshot bytes with an image/png content type, and close the browser lifecycle after the request.

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.