Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows 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 reinstallUse Playwright when your HTML must look like a browser page: install the Python package and its browser binaries, load the markup, then call page.screenshot(). Use WeasyPrint when the output is a paginated, document-style rendering and your HTML/CSS fits its supported feature set. The runnable examples below cover files, bytes, full pages, individual elements, dynamic content, and common deployment failures.
Choose the renderer before writing code
The right library depends on what “image from HTML” means for your project.
| Requirement | Recommended path | Important qualification |
|---|---|---|
| Browser CSS, JavaScript, responsive layout, or a page that should match Chrome | Playwright for Python | Requires the Playwright package and downloaded browser binaries. |
| A single component or region | Playwright locator screenshot | The locator must resolve to a visible, stable element. Covered content is not captured. |
| Image bytes for an in-memory pipeline | Playwright screenshot without a path | Pass the returned bytes to storage, an image processor, or an HTTP response. |
| Document-oriented layout and pagination | WeasyPrint | Confirm that the HTML and CSS you use are supported; it is not a JavaScript browser. |
There is no documented, controlled speed or visual-fidelity benchmark proving one is universally faster or better. Validate both with your actual templates, fonts, assets, and workload.
Generate a browser-rendered PNG with Playwright
1. Install Python and the browser binaries
- Create or activate a virtual environment for the project.
- Install the library:
pip install playwright. - Install its browser binaries:
playwright install. This separate download is required in addition to the Python package and affects container and deployment size. See the official setup documentation.
2. Render a complete HTML document
from playwright.sync_api import sync_playwright
html = """
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.card { padding: 24px; border-radius: 12px; background: #eef4ff; }
</style>
</head>
<body>
<div class="card"><h1>Hello from HTML</h1><p>Rendered in Chromium.</p></div>
</body>
</html>
"""
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()
set_content() loads the string directly. For a URL, use page.goto("https://example.com", wait_until="networkidle") (or another appropriate load condition) before taking the shot. full_page=True captures the complete scrollable page instead of only the viewport. The screenshot API documents PNG, JPEG, and WebP output; JPEG and WebP accept quality controls.
#1 Best Overall
3. Control viewport, device pixels, and transparency
The viewport controls CSS layout. Set device_scale_factor when you need device-pixel output (for example, a retina-style asset):
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context(
viewport={"width": 1440, "height": 900},
device_scale_factor=2,
)
page = context.new_page()
page.set_content(html)
page.screenshot(path="retina.webp", type="webp", quality=85)
browser.close()
Playwright supports CSS-pixel or device-pixel scaling. Transparent backgrounds apply to supported image types; design the page background accordingly and verify the result in your target viewer.
Capture one element instead of the whole page
Playwright’s locator screenshot is the documented way to capture a single element:
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:40px">Header</div>')
page.locator(".header").screenshot(path="header.png")
browser.close()
Playwright scrolls the target into view, but the result still reflects what is actually visible. An overlay can cover part of it, and a scrollable container contributes only the content currently scrolled into view. Use a stable selector and wait for it to be visible before capture.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesWait for fonts, images, and JavaScript
Dynamic pages can be captured before their final state. Choose an explicit readiness condition instead of relying on an arbitrary sleep.
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", wait_until="domcontentloaded")
page.wait_for_selector(".report-ready", state="visible")
page.screenshot(path="report.png", full_page=True)
browser.close()
For a page you control, add a class or data attribute after your application has loaded data. You can also wait for a bounded delay when no selector exists, but a selector is less flaky. Ensure remote fonts and images are reachable; otherwise the screenshot may contain fallback fonts or empty boxes.
Rank #2
Return image bytes instead of writing a file
Omit path and Playwright returns bytes. This is useful for an API response or object-storage upload:
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>")
png_bytes = page.screenshot(full_page=True)
with open("output.png", "wb") as f:
f.write(png_bytes)
browser.close()
The library also provides asynchronous APIs. Use the async variant in an asyncio application rather than blocking the event loop with the synchronous API.
Use WeasyPrint for document-style HTML
WeasyPrint’s Python API accepts HTML from a string, URL, filename, or file object and lays it out with render(). It is appropriate when pagination and print-like document flow matter more than browser JavaScript.
from weasyprint import HTML
html = """
<!doctype html>
<html><body>
<h1>Invoice</h1>
<p>A document-oriented rendering.</p>
</body></html>
"""
document = HTML(string=html, base_url=".").render()
# WeasyPrint is primarily a PDF renderer; write a PDF directly:
HTML(string=html, base_url=".").write_pdf("invoice.pdf")
See the WeasyPrint API reference for accepted inputs and rendering methods. If your HTML contains relative images, stylesheets, or fonts, provide an appropriate base_url (or load from a filename/URL) so those resources can be resolved. The documentation notes that long documents or specially crafted HTML can take a long time to render, so measure your real inputs. If you specifically need a PNG or JPEG, verify the current WeasyPrint API and output support for your version; for a browser-style raster screenshot, Playwright is the more direct choice.
Make output repeatable
- Pin the Playwright package and browser revision in deployment so layout changes are deliberate.
- Install the same fonts in development, CI, and production. A missing font changes line wrapping and image dimensions.
- Fix viewport size, device scale factor, timezone, locale, and data state when pixel comparison matters.
- Wait for a known readiness selector and ensure images and web fonts have finished loading.
- Close the browser and contexts in a
try/finallyblock in long-running services. - Reuse a browser process carefully for throughput, but isolate pages or contexts so cookies and state do not leak between jobs.
Troubleshoot common failures
“Executable doesn’t exist” or browser launch failure
Run playwright install in the same environment where the code runs. In a container, include the browser binaries and all required system dependencies; a package-only deployment is incomplete.
The screenshot is blank or missing images
Check the page URL, network access, authentication, and relative asset paths. For HTML strings, use absolute URLs or a correct base_url where supported. Wait for a selector that indicates the content is ready.
Recommended Free Tools
Text wraps differently on the server
Install the intended fonts and use the same browser revision, viewport, scale, and locale. Do not assume screenshots from different machines are byte-for-byte identical without controlling those inputs.
An element screenshot is clipped
Confirm the locator matches one visible element. Remove overlays, scroll the element to the required position, and remember that a scrollable element screenshot captures its currently visible content rather than every hidden row.
JavaScript content never appears
Use page.goto() with a suitable wait condition, then wait for an application-specific selector. Inspect console and network errors in a diagnostic run instead of increasing a timeout indefinitely.
WeasyPrint cannot find a stylesheet or image
Pass a valid base_url, use a filename/URL input, or convert resource references to resolvable absolute URLs. Then confirm that the CSS feature is supported by your installed WeasyPrint version.
Performance, reliability, and cost decisions
Browser startup and binary size are real deployment costs. A persistent browser process can avoid launching Chromium for every image, while separate contexts preserve isolation. Limit concurrency to what the host can support, and set practical navigation and selector timeouts so a dead upstream page does not occupy workers forever.
For visual reliability, test representative pages: long lazy-loaded pages, web fonts, cross-origin images, authenticated routes, animations, and elements inside scrollable containers. The cited documentation supplies no comparative benchmark, so choose based on your measured workload rather than a claimed universal speed advantage.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup:
ScreenshotNeo is a website screenshot API and MCP server. One request returns PNG, JPEG, WebP, or PDF and handles browser setup for you. Its capture flow can accept cookie and consent banners, then remove more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status.
Using the ScreenshotNeo API documentation, this is a complete cURL call:
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 →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)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo also supports full-page and element capture, dark mode, 12 device presets or any viewport, retina scale, PDF paper settings and page ranges, HTML/CSS input, custom JavaScript and CSS, click and wait actions, blocked requests, custom headers/cookies/user agents, timezone and geolocation, resizing, chosen cache TTLs, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage data, and an OpenAPI specification. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients. Parameter names used by other screenshot APIs also work, which can simplify migration.
The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 shots; every feature is on every plan. Create a free ScreenshotNeo account to try it without a card.
FAQ
Can I screenshot HTML without creating a temporary file?
Yes. Playwright’s page.set_content() accepts an HTML string, and omitting path returns image bytes directly.
Should I use PNG, JPEG, or WebP?
PNG is a safe default for text and transparency. JPEG and WebP can reduce file size and expose quality controls; choose based on the consuming application.
Does Playwright capture hidden page content?
full_page=True captures the page’s full scrollable document. A locator screenshot captures the selected element’s visible state, not content hidden inside a separately scrollable region.
Best Value
Can WeasyPrint execute JavaScript?
WeasyPrint is a document layout engine, not a browser runtime. If the page depends on JavaScript to create its content, use Playwright or render the data into the HTML before passing it to WeasyPrint.
Frequently Asked Questions
Can I screenshot HTML without creating a temporary file?
Yes. Playwright’s page.set_content() accepts an HTML string, and omitting path returns image bytes directly.
Should I use PNG, JPEG, or WebP?
PNG is a safe default for text and transparency. JPEG and WebP can reduce file size and expose quality controls; choose based on the consuming application.
Free tools Windows power users keep installed
One-click scans. No signup required.
Does Playwright capture hidden page content?
full_page=True captures the page’s full scrollable document. A locator screenshot captures the selected element’s visible state, not content hidden inside a separately scrollable region.
Can WeasyPrint execute JavaScript?
WeasyPrint is a document layout engine, not a browser runtime. If the page depends on JavaScript to create its content, use Playwright or render the data into the HTML before passing it to WeasyPrint.
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.




