Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use WeasyPrint when your HTML is a document template and you want a direct Python API; use Playwright when the output depends on JavaScript and real browser layout. WeasyPrint can render a string, file, or URL with HTML.write_pdf(). Playwright controls a browser, so it requires both the Python package and browser binaries. xhtml2pdf is another Python-library option, while wkhtmltopdf is mainly a legacy integration to keep deliberately isolated.

This guide shows a minimal working conversion, explains installation and deployment trade-offs, and covers security controls for user-supplied HTML.

Choose the rendering model first

HTML-to-PDF conversion is not one operation. A document renderer interprets HTML and CSS directly; browser automation loads a page in an actual browser engine and prints it. Your choice should follow the content you need to reproduce.

Route Consider it when Operational cost and cautions
WeasyPrint You generate reports, invoices, letters, or other mostly static HTML/CSS. Install Python plus platform-native libraries. Restrict URL fetching and isolate untrusted input.
Playwright with Chromium The page needs JavaScript, browser APIs, or the same layout behavior users see in a browser. Install the package, browser binaries, and any required system dependencies; manage browser processes.
xhtml2pdf You want a Python library based on ReportLab and your templates fit its supported HTML/CSS model. The project documents Python 3.10+ as tested and recommends the pycairo extra for its Cairo backend.
wkhtmltopdf An existing legacy system already depends on it. The official downloads page lists 0.12.6 (released June 11, 2020) and warns not to process untrusted HTML. Do not make it an unexamined default for new work.

No official source here establishes a universal fidelity winner. Render a representative template containing your real fonts, images, tables, page breaks, and scripts, then compare the resulting PDFs and deployment burden.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Elebase USB to USB C Adapter for iPhone 18 Pro Max,USBC Car Charger Adapter
  • Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
  • Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
  • Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
  • Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
  • 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.

Convert HTML with WeasyPrint

Install the package and native prerequisites

Install WeasyPrint in your virtual environment:

python -m pip install weasyprint

That command may not be sufficient. The current WeasyPrint installation documentation describes Python and Pango requirements and different setup procedures for Linux, macOS, and Windows. Follow the instructions for the operating system and pin the versions in the image or machine that will run your service.

Minimal string-to-PDF example

Once installed, the smallest useful conversion is:

from weasyprint import HTML

html = """


  
    
    
  
  
    <h1>Report</h1>
    <p>Generated from Python.</p>
  

"""

HTML(string=html).write_pdf("report.pdf")

The documented API is to create an HTML object and call HTML.write_pdf() to produce one PDF file. The output path can be relative or absolute. For a bytes response in a web application, write to an in-memory buffer instead of a filename:

from io import BytesIO
from weasyprint import HTML

buffer = BytesIO()
HTML(string=html).write_pdf(buffer)
pdf_bytes = buffer.getvalue()

Render a file or URL

Use the corresponding HTML input form when your source is not a string:

from weasyprint import HTML

HTML(filename="templates/report.html").write_pdf("report.pdf")
HTML(url="https://example.com/report").write_pdf("remote-report.pdf")

Relative images, stylesheets, and fonts need a sensible base URL. When constructing from a string, provide one so relative links resolve:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from weasyprint import HTML

HTML(string=html, base_url="/srv/app/templates").write_pdf("report.pdf")

Load web fonts deliberately

For CSS @font-face, the documentation demonstrates sharing a FontConfiguration between the HTML and CSS objects:

Rank #2
Anker USB-C Hub, 5-in-1 USB Hub for Laptops, 4K HDMI Multiport Adapter
  • 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
  • 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
  • Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
  • 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
  • What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
from weasyprint import HTML, CSS
from weasyprint.text.fonts import FontConfiguration

font_config = FontConfiguration()
css = CSS(filename="styles/print.css", font_config=font_config)
HTML(filename="templates/report.html").write_pdf(
    "report.pdf",
    stylesheets=[css],
    font_config=font_config,
)

Install the font files in the runtime image or serve them from an allowed location. A PDF that looks different in production often has a missing font or an asset URL that the renderer cannot reach.

Use Playwright when a browser is part of the requirement

Install Python and browser binaries

Playwright is browser automation, not a small HTML parser. Follow the official Python library setup:

python -m pip install playwright
playwright install chromium

The second command downloads the browser binaries. Containers may also need the documented system dependencies. Playwright exposes synchronous and asynchronous APIs; choose one style and manage browser and page lifetimes explicitly.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Minimal synchronous conversion

from pathlib import Path
from playwright.sync_api import sync_playwright

html = """

Browser-rendered report

JavaScript can run before printing.

""" with sync_playwright() as p: browser = p.chromium.launch() page = browser.new_page() page.set_content(html, wait_until="load") page.pdf(path="report.pdf") browser.close()

For a deployed page, use page.goto(url, wait_until="networkidle") or another condition that matches your application, then call page.pdf(). Consult the current Playwright documentation and Page API reference for print settings supported by the version you pin. Do not assume that installing Playwright installs branded Google Chrome; its browser documentation distinguishes bundled browser builds from branded browsers.

Control browser lifecycle

  • Reuse a browser process for a controlled batch, but create a fresh context or page for isolated jobs.
  • Close pages, contexts, and the browser in a finally block when conversion errors are possible.
  • Set application-level timeouts and terminate jobs that never finish loading.
  • In asynchronous code, use async_playwright() and await navigation and PDF operations; do not mix sync and async APIs in one execution path.

xhtml2pdf as a Python-library alternative

xhtml2pdf converts HTML through ReportLab. Its project documentation says Python 3.10+ is tested and guaranteed to work and recommends installing the Cairo extra:

Rank #3
Sale
Anker USB C Hub, 7in1 Multi-Port USB Adapter, 4K@60Hz USBC to HDMI Splitter
  • Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
  • Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
  • Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
  • Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
  • What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
python -m pip install "xhtml2pdf[pycairo]"

Verify the current backend requirements for your operating system. Choose this route when its supported markup and CSS match your templates; otherwise, prototype the exact document before committing to it.

Prepare production templates

Make assets deterministic

  • Use absolute or controlled relative URLs for images, stylesheets, and fonts.
  • Bundle required assets in the deployment image when possible instead of depending on an external website.
  • Specify page size, margins, and print-oriented CSS with @page.
  • Include a character set declaration and test non-ASCII text, long tables, and page breaks.
  • Record the renderer, Python, native-library, browser, and font versions with your build.

Separate document data from markup

Generate HTML from structured values using a template engine and escaping appropriate to HTML. Do not concatenate untrusted values into style blocks, attributes, or scripts. A PDF conversion service should have a bounded input size, render timeout, and output-size limit.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Security: treat HTML and CSS as untrusted

WeasyPrint documents that URL fetching can access local files through file://; untrusted HTML/CSS can probe local files or embed attachments. Its guidance is to isolate the rendering process with sandboxing and provide a restrictive custom URL fetcher that blocks or filters access. It also warns about long renderings and resource exhaustion.

Apply controls at the service boundary:

  • Run conversion in a low-privilege worker or container with a read-only, minimal filesystem.
  • Disable access to local paths and private network ranges unless a specific, reviewed feature requires them.
  • Allow only approved schemes, hosts, MIME types, and response sizes for remote resources.
  • Enforce CPU, memory, wall-clock, page-count, and output-size limits.
  • Keep browser automation jobs isolated; never expose a powerful host session to arbitrary page scripts.

The official wkhtmltopdf downloads page gives an especially direct 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 warning as a reason to sandbox legacy integrations, not as a reason to pass raw user content to the binary.

Reliability, performance, and cost decisions

Rendering speed

Direct renderers generally avoid the startup and memory cost of a full browser, while Playwright adds browser lifecycle overhead. The actual result depends on document size, fonts, images, scripts, and network access. Measure your own representative workload rather than relying on a generic benchmark.

Rank #4
Sale
UGREEN USB to USB C Adapter Combo 4-Pack, 10Gbps USB C Converter Space Gray
  • Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
  • Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
  • Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
  • Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
  • Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft

Repeatable output

Pin Python packages, native libraries, browser binaries, fonts, and templates. Capture a small set of reference PDFs in CI and inspect page count, text, images, and important layout boundaries after upgrades.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Scaling jobs

Use a queue for untrusted or expensive conversions. Limit concurrent browser pages, recycle workers after a defined number of jobs, and monitor timeout and memory failures. Cache identical, immutable inputs only when the cache key includes the template, data, asset versions, and renderer versions.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting common failures

ImportError or missing Pango/Cairo libraries

Your Python package is present but native dependencies are not. Recheck the platform-specific WeasyPrint installation page, or install the xhtml2pdf Cairo extra and its system prerequisites.

Playwright reports that an executable is missing

Run playwright install chromium in the same environment used by the application. In a container, install the browser during image build and verify that the runtime user can read it.

Images or CSS are absent

Check the HTML base URL, URL scheme, filesystem permissions, certificate validation, and your allowlist. Log failed resource requests without exposing sensitive document contents.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
Anker USB C Hub, 5-in-1 USBC to HDMI Splitter with 4K Display
  • 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
  • Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
  • Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
  • HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
  • What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.

JavaScript content is blank

Use Playwright, wait for the application’s actual readiness condition, and ensure the required API requests are allowed. A static renderer will not execute browser JavaScript.

Fonts wrap differently in production

Install the same font files and configure @font-face consistently. Confirm that the renderer can read the font URLs and that the PDF worker is using the intended font configuration.

Jobs hang or consume excessive memory

Set navigation and render timeouts, cap input and output sizes, block unnecessary resources, and terminate the isolated worker when limits are exceeded. Investigate pathological CSS, enormous images, recursive resources, and scripts that never become idle.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request can return a PNG, JPEG, WebP, or PDF, which is useful when the source is already a publicly reachable web page and you do not want to package a browser.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

cURL (see the ScreenshotNeo documentation):

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()));
  • Cookie banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
  • Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed as clean shots; 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.

Create a free ScreenshotNeo account to try the 1,000 monthly shots without a card.

Frequently Asked Questions

Can WeasyPrint execute JavaScript before creating the PDF?

No. Use Playwright or another browser automation route when the document depends on JavaScript execution, browser APIs, or client-side rendering.

Can I return the generated PDF directly from a Python web endpoint?

Yes. Render into a BytesIO buffer, then return its bytes with a PDF content type and a suitable download disposition.

Which option should I select for arbitrary user HTML?

None is safe by default. Isolate the renderer, restrict filesystem and network access, validate input, and enforce resource limits before accepting untrusted markup.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.