Free tools Windows power users keep installed
One-click scans. No signup required.
Use Playwright for Python to render HTML in a real browser and save the result as a PNG. For an HTML string, load it with page.set_content(); for a website, navigate with page.goto(). Then call page.screenshot()—with full_page=True for the full scrollable page, or on a locator to capture one element.
Why use a browser library to render HTML?
HTML-to-PNG conversion is a rendering task: the program has to interpret markup, apply CSS, load fonts and images, and possibly run JavaScript before it can produce pixels. A browser automation library is a practical choice when your page relies on modern CSS or JavaScript. Playwright can launch Chromium, Firefox, or WebKit, and its Python interface supports both synchronous and asynchronous code.
The examples below use Playwright with Chromium. A browser is launched headlessly by default, so no visible browser window is required. Playwright also needs its browser binaries installed in the environment where the script runs; the Python package alone does not provide a ready-to-launch browser installation.
Install Playwright and its browser
In a fresh Python environment, install the package and then install a browser binary. This example uses Chromium:
Recommended Free Tools
#1 Best Overall
python -m pip install playwrightpython -m playwright install chromium
Run the commands in the same environment that will run your script. In a container or deployment environment, make sure the installed browser and its operating-system dependencies are available there too. Playwright can launch Firefox or WebKit instead; install the corresponding browser binary and replace p.chromium with p.firefox or p.webkit.
Convert an HTML string to a PNG file
Use page.set_content() when the markup is already available as a Python string. This complete synchronous example writes the rendered page to output.png:
from playwright.sync_api import sync_playwright
html = """<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body { font-family: sans-serif; padding: 24px; }
h1 { color: #1769aa; }
</style>
</head>
<body>
<h1>Hello from HTML</h1>
<p>This page is rendered by a browser.</p>
</body>
</html>"""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={"width": 1280, "height": 800})
page.set_content(html, wait_until="networkidle")
page.screenshot(path="output.png", type="png", full_page=True)
browser.close()
set_content() assigns the markup to the page; it does not fetch a website URL. If your HTML refers to external images, stylesheets, or fonts, those resources still need to be reachable and load successfully for the screenshot to include them.
Convert a website URL to PNG
For an existing web page, navigate to its URL with page.goto() instead of assigning a string:
Rank #2
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="networkidle")
page.screenshot(path="website.png", type="png", full_page=True)
browser.close()
networkidle waits for network activity to become idle before continuing. It is useful for pages that load content after navigation, but some sites keep making background requests; in those cases, choose a more suitable readiness condition or wait for a specific element instead of assuming the network will become idle.
Return PNG bytes instead of writing a file
Omit the path argument and page.screenshot() returns the image as bytes. You can write those bytes yourself, pass them to an image-processing library, or return them from an application endpoint:
from playwright.sync_api import sync_playwright
html = "<!doctype html><html><body><h1>Hello</h1></body></html>"
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.set_content(html, wait_until="networkidle")
png_bytes = page.screenshot(type="png", full_page=True)
with open("output.png", "wb") as image_file:
image_file.write(png_bytes)
browser.close()
Use binary mode ("wb") when writing the result. The returned value is already encoded as a PNG image; it is not a text string or a base64 string.
Choose the capture area and image settings
Capture the full scrollable page
Set full_page=True to capture the entire scrollable document rather than only the visible viewport. This is useful for long pages, but the resulting image can be tall and may use more memory than a viewport-sized capture.
Capture one element
Use a locator’s screenshot method to capture a specific element, such as a card, chart, or header:
page.locator(".header").screenshot(path="header.png")
The locator must match an element that exists in the rendered page. If it is created by JavaScript, wait for it before taking the screenshot; otherwise the capture can fail because the target is not present yet.
Set the viewport and device scale
The viewport controls the browser’s CSS-pixel layout dimensions. Set it when creating the page, as in browser.new_page(viewport={"width": 1280, "height": 800}). This affects responsive breakpoints and therefore the layout in the image. Playwright’s screenshot API also supports device scaling, clipping, and timeouts; use these controls when you need a specific output scale, a crop, or a longer allowance for a slow capture.
Select the output format carefully
PNG is lossless and is usually appropriate for text, diagrams, and interface screenshots. Playwright can also return or write JPEG and WebP screenshots. Its JPEG-only quality setting does not apply to PNG, so changing that parameter will not make a PNG smaller. If you need PNG output, specify type="png" or use a .png path.
Use Playwright’s asynchronous API
In an asyncio application, use the async Playwright API and await each browser operation. The browser should be closed after the capture so its process and resources are released:
import asyncio
from playwright.async_api import async_playwright
async def render_html():
html = "<!doctype html><html><body><h1>Hello</h1></body></html>"
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(html, wait_until="networkidle")
png_bytes = await page.screenshot(type="png", full_page=True)
with open("output.png", "wb") as image_file:
image_file.write(png_bytes)
await browser.close()
asyncio.run(render_html())
In a web service or other process that already has an active event loop, call and await the coroutine from that loop rather than starting a second one with asyncio.run(). Keep browser lifecycle management aligned with your application: close pages and browsers when the work is finished, and do not leave a new browser process running for every request without managing its lifetime.
Alternative: render HTML with Pyppeteer
Pyppeteer is an unofficial Python port of Puppeteer. Its reference documents setting markup with setContent() and taking PNG screenshots. Here is a minimal async example:
import asyncio
from pyppeteer import launch
async def render():
browser = await launch()
page = await browser.newPage()
await page.setContent("<html><body><h1>Hello</h1></body></html>")
await page.screenshot({"path": "output.png", "type": "png", "fullPage": True})
await browser.close()
asyncio.run(render())
Its documented screenshot options include full-page capture, clipping, omitting the background, and binary or base64 encoding. Choose it when its interface fits an existing project; for a new project that needs a documented choice of browser engines and sync or async Python APIs, Playwright is the more direct fit. Neither library’s API options alone establish a comparative speed or image-fidelity advantage.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Best Value
Or skip the browser setup
If you would rather request a screenshot than install and operate a browser, ScreenshotNeo provides a website screenshot API and MCP server for developers. This one-call cURL example returns an image file:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. It accepts a URL and can return PNG, JPEG, WebP, or PDF. Cookie banners are accepted and removed before capture, along with known consent platforms, newsletter popups, and chat widgets; those cleanup steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Every feature is available on every plan. Sign up for free and try 1,000 screenshots a month with no card.
Troubleshooting common problems
- Playwright reports that an executable is missing. The Python package is installed, but the browser binary is not available in this environment. Run
python -m playwright install chromiumin the same environment, or install the browser engine you intend to launch. - The screenshot is blank or missing images and fonts. Check that external resources are reachable and that the page has had time to render them. For dynamic pages, wait for a meaningful selector or loading state rather than capturing immediately after assigning the HTML.
networkidlenever completes. A page may continue making background network requests. Use a different navigation readiness condition and wait for the specific content your screenshot needs.- The capture is cut off at the viewport. Add
full_page=Truefor a full-document capture. If the output should include only a component, use a locator screenshot instead. - The layout differs from the browser you use manually. Match the viewport dimensions and browser engine to the intended rendering context. Responsive CSS changes with viewport size, and Playwright’s Chromium, Firefox, and WebKit engines can be selected explicitly.
- The output file is corrupted or empty. For byte output, write the returned bytes with a binary file handle such as
open("output.png", "wb"). If using a path, ensure the destination directory exists and the running process can write there. - A long full-page screenshot consumes too many resources. Capture only the needed element or viewport, or reduce the page’s rendered dimensions. Full-page captures include the entire scrollable document and can be substantially larger than viewport captures.
Performance, reliability, and cost considerations
These libraries render through browser processes, so account for installing browser binaries and their dependencies wherever the code runs. Close the browser when a standalone script finishes; in a service, manage browser and page lifetimes deliberately rather than leaking processes. A longer page, more loaded content, or a page that never reaches the chosen readiness condition can increase the time and memory required for a capture.
Playwright’s documentation describes the screenshot controls and browser APIs, but does not provide a benchmark comparing its speed or fidelity with Pyppeteer. Actual time depends on the page, browser engine, external resources, and chosen wait condition, so measure the workload that matters to your application rather than relying on an unsupported universal performance figure. The library route has no per-screenshot service charge stated here, but it does require you to operate the browser environment; a hosted API trades that setup for an external request and its plan limits.
Frequently Asked Questions
Can I use Playwright to screenshot HTML without saving a file?
Yes. Call page.screenshot() without a path; it returns the PNG as bytes.
Does Pyppeteer provide a synchronous API?
The documented Pyppeteer example uses asyncio and awaited calls; use its async pattern or choose Playwright if you need a documented synchronous interface.
Can Playwright return formats other than PNG?
Yes. Its screenshot API supports JPEG and WebP as well as PNG.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →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.

