Use Playwright when you need a PNG that reflects browser layout, CSS, and JavaScript. In Python, load a URL with page.goto() or supply HTML with page.set_content(), then call page.screenshot(path="output.png"). Set full_page=True to capture the full page rather than just the viewport.
Choose the right way to render the HTML
The best approach depends on what the HTML needs in order to render correctly. A browser-based screenshot is a natural fit when the page uses JavaScript, browser layout, or external assets and you want an image of what a browser displays. Playwright’s Python API can launch Chromium, Firefox, or WebKit; browsers run headlessly by default.
If your input is document-like and does not need browser automation, a document-rendering library may fit better. WeasyPrint’s version 52.5 tutorial documents PNG output, but that is an older reference; do not assume that its current API still matches that tutorial without checking current documentation and release notes. There is no formal performance or fidelity benchmark established here, so choose based on the page behavior and output you need rather than assuming one library is universally better.
- Use Playwright for a URL, JavaScript-driven content, browser-faithful layout, a full-page capture, or a specific element.
- Consider a document renderer for document-style HTML when browser automation is unnecessary, after confirming that the current version supports the output you need.
Install Playwright and its browser
Install the Playwright Python package and the browser engine you intend to use by following Playwright’s current installation instructions for your operating system. Playwright needs both the Python library and a browser runtime; installing only the package may not be enough to launch a browser. System dependencies can vary by platform, so use the instructions for the environment where the script will run instead of copying a version-specific command from an unrelated setup.
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 →#1 Best Overall
For simple scripts, the synchronous API is straightforward. If the rest of your application uses asyncio, use Playwright’s asynchronous API instead. The examples below use the synchronous API and Chromium.
Convert an HTML string to a PNG file
Use page.set_content() when your HTML is already in Python. The following example writes a full-page PNG to the current working directory:
from playwright.sync_api import sync_playwright
html = """
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body { font-family: sans-serif; margin: 32px; }
h1 { color: #155eef; }
</style>
</head>
<body>
<h1>Hello from Python</h1>
<p>This page will be rendered as a PNG.</p>
</body>
</html>
"""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.set_content(html)
page.screenshot(path="output.png", full_page=True)
browser.close()
The output format is inferred from the .png extension; you can also specify the screenshot type explicitly with type="png". The screenshot call saves the image to the path you provide. If another part of your program needs the image directly, omit path and use the returned bytes instead.
Capture a web page from a URL
For an existing website, navigate to its URL with page.goto() before taking the screenshot. A new page uses a viewport, so without full_page=True the capture represents the visible viewport, not necessarily the entire document.
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 glitchesRank #2
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})
page.goto(url)
page.screenshot(path="page.png", full_page=True)
browser.close()
For a screenshot of only the viewport, leave out full_page=True. Navigation and screenshot readiness are separate concerns: a page can finish its initial navigation while images, client-rendered content, or other assets are still changing. Wait for the content you actually need before capture rather than assuming a fixed delay always means the page is ready.
Capture one element instead of the page
Use a locator screenshot when the output should contain one element, such as a chart, card, or report section:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com")
card = page.locator(".report-card")
card.screenshot(path="report-card.png")
browser.close()
Replace .report-card with a selector that identifies the element on your page. A locator screenshot captures that element as displayed. If the element itself has an internal scrollbar, the screenshot shows its currently scrolled content; it does not automatically capture the full contents of that inner scroll area.
Control readiness and repeatability
For a stable result, wait for the specific content or state your screenshot needs. Playwright supports waiting for a selector and other page conditions; a selector wait is often more meaningful than an arbitrary sleep when a particular element signals readiness. A network-idle state may be unsuitable for pages that keep polling or streaming, so select a condition that matches the page.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →- Dynamic content: wait for the result element or application state to appear before capture.
- Images and fonts: if their final appearance matters, ensure they have loaded before taking the screenshot.
- Animations: use screenshot animation controls when you need a repeatable capture rather than a frame during motion.
- Timeouts: the documented default screenshot timeout is 30 seconds. Set an appropriate timeout for your workload if the default is unsuitable, and handle timeouts as failures rather than treating them as valid images.
No single wait guarantees that every website has finished rendering. A page may continue updating after initial navigation, and external resources can fail or change independently.
Useful screenshot options
| Need | Playwright approach | What to expect |
|---|---|---|
| Whole document | full_page=True |
Captures the page beyond the visible viewport. |
| One component | page.locator("selector").screenshot(...) |
Captures the element; an inner scroll area is limited to its current scroll position. |
| Image bytes in memory | Call page.screenshot() without path |
Returns screenshot bytes for another part of the program to store or process. |
| Transparent background | omit_background=True |
Omits the page background for supported PNG output; this option is not applicable to JPEG. |
| Browser engine choice | Launch Chromium, Firefox, or WebKit | Choose the engine relevant to the browser rendering you need to represent. |
| Readiness before capture | Wait for the relevant selector or page condition | Lets the script coordinate capture with content that is not ready immediately. |
Use async Python when your application needs it
Playwright provides both synchronous and asynchronous Python APIs. The browser and screenshot steps are the same in principle, but the async API lets you await operations from an asyncio-based application:
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.set_content("<h1>Hello</h1>")
await page.screenshot(path="output.png", full_page=True)
await browser.close()
asyncio.run(main())
Use one style consistently in a given flow: calls in the asynchronous API need await, while the synchronous example does not.
Troubleshoot common failures
Browser launch fails
Likely cause: the browser runtime is not installed, or the host is missing a dependency required by that browser. Fix: follow Playwright’s current browser-install and operating-system dependency instructions for the machine running the script. Confirm that the chosen engine is installed before debugging page code.
The PNG is blank or missing content
Likely cause: the screenshot was taken before client-rendered content appeared, or the target page did not load as expected. Fix: wait for a page-specific selector or state, and inspect the page or navigation outcome before saving the image. A fixed sleep may help diagnose timing but is not a general readiness guarantee.
The screenshot is only the top part of the page
Likely cause: the screenshot uses the default viewport capture. Fix: add full_page=True for the full document. For a locator inside a scrollable container, remember that its screenshot does not automatically expand the container’s inner scroll area.
The output file is not where expected
Likely cause: a relative path is resolved from the script’s current working directory. Fix: use an explicit output path or print the working directory when diagnosing where the file was written.
The screenshot times out
Likely cause: rendering, navigation, or the target page’s behavior exceeded the relevant timeout. Fix: identify which operation timed out, use an appropriate timeout for that operation, and wait on a meaningful page condition. Do not treat a timed-out capture as a successful PNG.
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 matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallBest Value
Or skip the browser setup
If you would rather request a screenshot from an API, ScreenshotNeo returns a PNG, JPEG, WebP, or PDF from a GET request. Its screenshot options and API details are in the ScreenshotNeo documentation.
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and responses identify the page verdict and billing status in headers. It also provides an MCP server for AI agents, including Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month with no card.
Performance, reliability, and cost considerations
With local Playwright, your script launches and runs a browser, so the machine executing it must have the required browser runtime and resources available. Capture time depends on the page, its assets, and the readiness condition; no universal timing figure is established. Reuse and lifecycle choices should match your application, but always close the browser when the work is done, including when an exception occurs. In production code, use structured cleanup such as a try/finally block so a failed navigation does not leave a browser process behind.
For reliable automation, decide what counts as a valid result: a page that navigated, the required element appeared, and the screenshot file or bytes were produced. Handle navigation errors, missing selectors, and timeouts explicitly. External websites can change markup, block automated traffic, or fail to serve assets, so selectors and page-specific readiness checks may need maintenance. A screenshot library does not make a remote website dependable.
Playwright itself does not impose a per-shot service price in the workflow shown here, but running browsers has compute and operational costs in your environment. A hosted screenshot API instead trades local browser management for a service request and its plan limits or billing rules. Compare the actual capture needs, volume, operational workload, and the service’s current terms before choosing; there is no performance comparison established between these approaches.
Frequently Asked Questions
Can Playwright return a PNG without writing a file?
Yes. Call page.screenshot() without a path argument and use the returned bytes in your program.
Can I make a transparent PNG?
Playwright documents omit_background=True for a transparent background in PNG output; it is not applicable to JPEG.
Does a locator screenshot include the entire scrollable contents of that element?
No. It captures the element as currently displayed, so an inner scroll area is limited to its current scroll position.
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.

