What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
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 WeasyPrint when your input is ordinary HTML and CSS; use Playwright when the page needs a real browser to run JavaScript, load dynamic content, or match Chromium printing behavior. Both are practical Python routes, but they have different installation and security requirements. This guide shows a minimal WeasyPrint conversion, a Playwright browser workflow, an xhtml2pdf alternative, deployment details, and troubleshooting.
Choose the rendering model first
HTML-to-PDF conversion is not one interchangeable operation. A document renderer parses HTML and CSS directly, while browser automation starts a browser, loads a page, runs its scripts, and asks the browser to print the result.
| Route | Best reason to consider it | Operational trade-off |
|---|---|---|
| WeasyPrint | Direct Python HTML/CSS-to-PDF API | Requires platform-specific native libraries and careful resource handling |
| Playwright with Chromium | Pages that depend on browser behavior or JavaScript | Requires browser binaries, system dependencies, and browser lifecycle management |
| xhtml2pdf | Python library built around ReportLab | Verify its supported CSS and backend requirements for your templates |
| wkhtmltopdf | Existing legacy integrations | The downloads page lists 0.12.6, released June 11, 2020, and warns against untrusted HTML; do not make it the default for new work |
No official source reviewed here establishes a universal fidelity winner. Render representative documents containing your actual CSS, fonts, images, tables, and page breaks before committing to a tool.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteConvert static HTML with WeasyPrint
Install the package and platform dependencies
WeasyPrint is not always a pure-Python install. Its current documentation describes Python and Pango requirements and gives different setup steps for Linux, macOS, and Windows. Follow the installation section for the operating system and Python environment you deploy: WeasyPrint First Steps. Pin the resulting versions in your requirements and container or OS image.
#1 Best Overall
Minimal working example
from weasyprint import HTML
HTML(string="<h1>Report</h1><p>Generated from Python.</p>").write_pdf("report.pdf")
The API is deliberately small: create an HTML object and call write_pdf() to produce one file. You can also construct HTML from a URL or file, then call the same method. Supply a base URL when relative images, stylesheets, or fonts are referenced from an HTML string.
Render a template and CSS
from pathlib import Path
from weasyprint import HTML, CSS
html = Path("invoice.html").read_text(encoding="utf-8")
HTML(string=html, base_url=str(Path("invoice.html").parent)).write_pdf(
"invoice.pdf",
stylesheets=[CSS(filename="print.css")],
)
Keep local assets beside the template or use absolute URLs that your controlled fetcher permits. For custom @font-face rules, the documentation demonstrates sharing a FontConfiguration between the CSS and HTML objects so fonts are embedded consistently; follow that pattern in the official guide.
Convert a web URL
from weasyprint import HTML
HTML(url="https://example.com").write_pdf("example.pdf")
Network access, redirects, authentication, and remote assets can make URL rendering nondeterministic. For repeatable reports, download or generate the assets in your application and render from a controlled base directory.
Use Playwright when a browser is required
Install Python and browser components
pip install playwright installs the Python package, not the browser runtime. The documented setup installs Playwright’s browser binaries as a separate step; system dependencies may also be needed in a Linux container. Start with the Python library installation guide. Playwright’s project is intended for browser automation and end-to-end testing, so plan for browser startup, cleanup, concurrency, and image size.
Rank #2
pip install playwright
playwright install chromium
Minimal synchronous PDF workflow
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="networkidle")
page.pdf(path="example.pdf", format="A4", print_background=True)
browser.close()
For generated HTML, use page.set_content(html) instead of goto(). For asynchronous applications, use Playwright’s async API and await each operation. Consult the current introduction and Page API for print options supported by the version you pin. Playwright distinguishes its bundled browser builds from branded Chrome; installing Chromium does not imply that branded Chrome is installed.
When Playwright is the better fit
- The page builds its content with JavaScript.
- You must execute client-side layout, charts, or framework code before printing.
- You need browser-level cookies, authentication, viewport emulation, or network interception.
- Your acceptance criteria are defined by how Chromium displays the page.
A browser route costs more operationally: keep browser versions aligned, reuse or limit browser processes deliberately, set navigation and rendering timeouts, and close contexts even when a conversion fails.
Consider xhtml2pdf for a library-based alternative
xhtml2pdf uses ReportLab and documents Python 3.10+ as tested and guaranteed to work. Its installation guidance recommends the Cairo extra, so verify the current command and backend requirements for your target platform before deployment. It can be a sensible choice when your templates fit its supported HTML/CSS model, but validate page breaks, fonts, tables, and images with real documents.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Prepare production HTML
Make assets deterministic
- Use UTF-8 and declare it in the document.
- Provide a correct base URL for relative links when rendering HTML strings.
- Install every font used by the template in the runtime image and verify font fallback.
- Check that images are readable by the renderer and that remote URLs are reachable under deployment network rules.
- Define print styles, page margins, table headers, and explicit page-break rules instead of relying on screen-only CSS.
Control output and resources
Pin Python packages, native libraries, browser binaries, and fonts together. Render a fixture set in CI after dependency updates. Set request, navigation, and render timeouts. Limit HTML size, image dimensions, page count, and concurrent jobs so a malformed document cannot consume all CPU or memory.
Security: treat HTML and CSS as untrusted
Do not pass arbitrary user markup directly to a renderer. WeasyPrint documents that URL fetching can access local files through file://; untrusted HTML and CSS can probe local files or embed attachments. Run rendering in a sandbox or isolated process, apply a restrictive custom URL fetcher, deny unexpected schemes and hosts, and remove dangerous or unnecessary content before rendering. Enforce CPU, memory, wall-clock, and output-size limits.
The official wkhtmltopdf downloads page gives an especially strong warning: “Do not use wkhtmltopdf with any untrusted HTML – be sure to sanitize any user-supplied HTML/JS, otherwise it can lead to complete takeover of the server it is running on!” Treat that as a security requirement, not a cosmetic limitation.
Troubleshoot common failures
Import or shared-library errors with WeasyPrint
Cause: Pango or another native dependency is missing, or the wrong architecture is installed. Fix: follow the current OS-specific installation instructions, confirm the active virtual environment, and rebuild the image with the required system packages.
Windows 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 reinstallCrashes, 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 minuteMissing images, CSS, or fonts
Cause: relative URLs have no usable base URL, the process cannot read a local path, or network access is blocked. Fix: pass base_url, use controlled absolute paths, verify permissions, and inspect the renderer’s resource-fetch policy.
Playwright says no browser is installed
Cause: the Python package was installed without its browser binaries. Fix: run the documented playwright install chromium step during image build and install required Linux dependencies where applicable.
JavaScript content is absent
Cause: a document renderer does not execute browser JavaScript, or Playwright printed before the application finished rendering. Fix: use Playwright, wait for a meaningful selector or application-ready signal, and avoid relying only on a fixed sleep.
Fonts or page breaks differ between environments
Cause: different fonts, native libraries, browser builds, or CSS support. Fix: pin the runtime, install and verify fonts, include print CSS, and compare generated PDFs from a representative fixture suite.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Or skip the browser setup
If your source is a public web page and you want an API response instead of managing Chromium, ScreenshotNeo can return a screenshot or PDF from one GET request. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
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 documentation for PDF parameters, authentication, and response handling. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for the free plan.
Best Value
Python, cURL, and Node.js API examples
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()));
Practical decision checklist
- Start with WeasyPrint for generated, mostly static HTML/CSS and accept its native dependency setup.
- Choose Playwright when JavaScript or browser-specific behavior is part of the document, and budget for browser binaries and lifecycle management.
- Evaluate xhtml2pdf when its ReportLab-based model matches your templates and Python 3.10+ baseline.
- Render representative fixtures before deciding; compare fonts, images, tables, page breaks, links, and print backgrounds.
- Isolate untrusted input and enforce resource limits regardless of renderer.
Frequently Asked Questions
Can WeasyPrint execute JavaScript?
No. It parses HTML and CSS directly, so pages that require client-side JavaScript generally need a browser automation route such as Playwright.
Does Playwright install Google Chrome?
The documented install downloads Playwright-managed browser builds. It distinguishes those bundled builds from branded browsers.
Recommended Free Tools
What Python version does xhtml2pdf support?
Its project documentation says Python 3.10+ is tested and guaranteed to work; verify the current project guidance before pinning a newer version.
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.

