Use Playwright’s Python library to render HTML in a real browser, then call page.screenshot(). This handles local markup, JavaScript applications and public URLs, and can produce viewport, full-page or element images. If you do not want to install and operate a browser, a hosted renderer such as ScreenshotNeo can return an image from one HTTP request.
Choose the rendering route first
“HTML to image” can mean two different jobs:
- Render HTML in a browser that your Python process controls, giving you local control over files, cookies, scripts and timing.
- Send HTML or a URL to a remote rendering service, delegating browser infrastructure to that service.
Playwright is the primary local route documented for Python. Its library exposes synchronous and asynchronous APIs and can launch Chromium, Firefox or WebKit. A hosted API is useful when your deployment should not maintain browser processes, but it introduces API credentials, network access and a service dependency. The available documentation does not establish a universal winner for speed, price, fidelity, privacy or reliability.
Render HTML to a PNG with Playwright
Install and create a minimal script
Install the Python package and the browser binaries required by your installed Playwright release, following the current Playwright library documentation. The basic synchronous program is:
from playwright.sync_api import sync_playwright
html = """
Rendered in Python
This file is captured by a browser, not by an HTML parser.
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.
"""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.set_content(html)
page.screenshot(path="output.png")
browser.close()
The screenshot guide documents this same page.screenshot(path="screenshot.png") operation. Because Chromium lays out the document, CSS and browser-supported JavaScript can affect the result. The output path’s extension determines the file type when you use a path.
Capture an existing URL
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")
browser.close()
For an application whose layout depends on JavaScript or external assets, navigate and wait for the page’s actual ready condition before taking the shot. There is no single wait setting that guarantees correctness for every site: a font, image, chart or API response may finish at a different time.
Use asynchronous Python
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()
await page.goto("https://example.com")
await page.screenshot(path="example-async.png")
await browser.close()
asyncio.run(main())
The asynchronous API is appropriate when screenshot work is part of an async web service or job queue. Close each browser you launch so processes do not accumulate.
Control what gets captured
Viewport versus full page
A normal screenshot captures the current viewport. To capture the complete scrollable document, use the documented full_page=True option:
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →page.screenshot(path="whole-page.png", full_page=True)
Full-page capture is a browser operation that stitches the page’s scrollable content into one image. Very long pages can create large files and consume substantial memory; consider capturing sections or resizing after capture when a single huge image is not required.
Rank #2
Capture one element
card = page.locator(".card")
card.screenshot(path="card.png")
The locator screenshot is useful for product cards, invoices, charts or social-card components. A selector that matches no element, or matches an element that is not ready, will fail; make the locator specific and ensure the component is rendered before calling it.
Keep the image in memory
image_bytes = page.screenshot()
# Send image_bytes to object storage, an HTTP response, or an image library.
Omitting the path returns image bytes instead of writing a file. This avoids a temporary file in pipelines that immediately upload or transform the image.
Format, quality, scale and transparency
The current Playwright Page API documents PNG, JPEG and WebP output. PNG is the documented default. JPEG and WebP accept a quality value from 0 to 100; the documented JPEG default quality is 80, while WebP quality 100 is lossless and lower values are lossy. The API also documents CSS-pixel or device-pixel scaling, transparent backgrounds and masks. Check the API reference for the version installed in your environment because option details can change.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →# JPEG with explicit quality
page.screenshot(path="preview.jpg", type="jpeg", quality=85)
# WebP output
page.screenshot(path="preview.webp", type="webp", quality=90)
# Render at device-pixel scale
page.screenshot(path="retina.png", scale="device")
# Hide sensitive or unstable content with a mask
page.screenshot(path="masked.png", mask=[page.locator(".email")])
Use PNG for crisp text and transparency, JPEG for photographic previews where a smaller file matters, and WebP when your consumers support it and you want a modern size/quality trade-off.
Make captures deterministic
- Set the viewport. Responsive breakpoints change layout, so use an explicit width and height for repeatable output.
- Wait for real readiness. Wait for a selector your application renders, a known API completion, or another application-specific condition. A fixed delay can be useful for a simple page but is not a universal guarantee.
- Control data and credentials. Supply the same test data, cookies and authentication state for every run when visual consistency matters.
- Handle external assets. Missing fonts, blocked images and third-party scripts can change dimensions or leave blank regions. Diagnose network and console errors rather than hiding them with a longer delay.
- Choose a browser deliberately. Playwright can launch Chromium, Firefox or WebKit; use the engine that matches the rendering behavior you need.
Hosted HTML-to-image rendering
html2img documents two relevant operations: an HTML endpoint that accepts supplied markup and a screenshot endpoint for a valid, publicly accessible URL. Its documentation lists width and height, a full-page flag, device-pixel ratio, CSS injection and waiting for a selector. Requests require an API key, and the service documents synchronous and asynchronous Python clients. See the html2img getting-started documentation for its current request shape.
Rank #3
This route avoids running a local browser, but your HTML may need to be reachable by the service, and private pages require whatever authentication mechanism that provider supports. Evaluate where sensitive markup is processed, how credentials are stored, and what happens when the remote service is unavailable. No measured comparison with Playwright is established here.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP or PDF. Before capture it accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers report the page verdict and whether the request was billed.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11It also offers an MCP server for Claude, Cursor and other MCP clients, with take_screenshot, get_page_info and capture_pdf tools. Options include full-page and CSS-selector captures, dark mode, device presets or custom viewports, retina scale, PDF settings, custom CSS and JavaScript, click-before-capture, selector or network-idle waits, request blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API 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
Python:
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)
Node.js:
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 parameters and response headers. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots, and every feature is included on every plan. Create a free ScreenshotNeo account to try it.
Playwright options at a glance
| Need | API shape | Result |
|---|---|---|
| Visible viewport | page.screenshot(path="view.png") |
Current viewport |
| Entire scrollable page | full_page=True |
Full-page image |
| One component | page.locator(selector).screenshot(...) |
Element image |
| Pipeline upload | Omit path |
Image bytes |
| Format | type="png"|"jpeg"|"webp" |
Selected raster format |
Troubleshooting
The browser executable is missing
Playwright is installed separately from its browser binaries. Follow the browser-install step in the current library documentation for your release, then rerun the script. In CI, install browsers during the image-build stage rather than at every job.
The screenshot is blank or incomplete
Check that navigation succeeded, the page is not waiting on a failed API request, and required assets are reachable. Wait for a concrete selector or application-ready condition. For a lazy-loaded page, scroll or use the application’s own loading trigger before capture.
Fonts or layout differ between machines
Use the same browser engine, viewport, device scale and font environment. A missing web font can change line wrapping and therefore the entire image height.
Full-page output is unexpectedly large
Measure the document height before capture, split very long content into sections, or resize the resulting bytes. Full-page mode intentionally includes the complete scrollable document.
An element locator fails
Confirm the selector matches after navigation and that the element is visible. Dynamic class names, frames and shadow DOM require a selector strategy that reflects the page’s actual structure.
Remote rendering cannot reach the page
A hosted URL screenshot endpoint generally needs a publicly accessible URL. For private or local pages, use Playwright in the same network or the hosted provider’s documented HTML/authentication mechanism.
Recommended Free Tools
Cost, performance and reliability decisions
- Local Playwright: no per-shot API charge is established in the cited material, but you own browser installation, process lifecycle, memory, concurrency and network access.
- Hosted rendering: less browser operations work in your application, but requests depend on credentials, connectivity and the provider’s current terms and limits.
- Throughput: do not assume a speed advantage. Benchmark your URLs, browser engine, image dimensions and concurrency under production-like conditions.
- Security: treat HTML, cookies, Authorization headers and rendered screenshots as sensitive data. Keep secrets out of source code and restrict where remote services may fetch private content.
FAQ
Can Python convert HTML without a browser?
A browser renderer is the documented route here because it evaluates CSS and JavaScript. A parser alone will not reproduce browser layout; choose a renderer when visual fidelity matters.
Can I capture a public webpage instead of inline HTML?
Yes. Navigate Playwright to the URL with page.goto(), or use a hosted screenshot endpoint that accepts publicly reachable URLs.
Which image format should I send to another service?
PNG is the documented default and preserves crisp text. Use JPEG or lossy WebP when your downstream system favors smaller photographic previews, and verify that it accepts the chosen format.
Frequently Asked Questions
Does Playwright support browsers other than Chromium?
Yes. The Python library documents launching Chromium, Firefox and WebKit; select the engine explicitly when cross-browser rendering matters.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesHow do I capture only a chart or card?
Locate it with page.locator("...") and call that locator’s screenshot() method instead of capturing the page.
What does ScreenshotNeo bill?
Only clean shots are billed. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the verdict and billing status in headers.
Quick Recap
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.

