Documentation page: PD4ML for Python Compared with WeasyPrint, xhtml2pdf and Playwright. This page is also available as Markdown at python-html-to-pdf-library-comparison.md.

PD4ML for Python Compared with WeasyPrint, xhtml2pdf and Playwright

Python developers who need HTML to PDF usually pick one of a few libraries: WeasyPrint, xhtml2pdf, a headless browser driven by Playwright, or pdfkit with wkhtmltopdf. Most are free and install with pip, and each works well for some kinds of documents. This page compares them with PD4ML for Python, the pip package that brings the PD4ML layout engine to Python, so you can see where each one fits: CSS layout, PDF/A and PDF/UA, e-invoices, Word output, signatures, deployment and license.

The comparison covers PD4ML v4.1.1 and, marked 4.2, features of the upcoming PD4ML 4.2 with its new v42 layout engine. Information about the other libraries comes from their documentation and PyPI pages as of November 2026; a cell marked "not verified" means we could not confirm it from public sources. ReportLab is not included: it builds PDFs from Python code rather than from HTML.

At a glance

  • PD4ML for Python (pd4ml on PyPI) runs the PD4ML engine in a Java virtual machine inside the Python process, with no server, and exposes its full API to Python. It needs Python 3.9 and Java 8 or later. Commercial license, perpetual, from €100; free evaluation with a watermark.
  • WeasyPrint (70.0) is a print-oriented HTML and CSS renderer written in Python on top of Pango. It is the most complete of the open-source options: paged media, PDF/A, PDF/UA and PDF/X. BSD-3-Clause.
  • xhtml2pdf (0.2.28) converts HTML and CSS 2.1, with parts of CSS3, to PDF through ReportLab, in pure Python. It is actively developed again and has added Flexbox, signatures and PDF/X-4. Apache-2.0.
  • Playwright (1.64) drives a headless Chromium whose print to PDF renders HTML as Chrome does, JavaScript included, but with few PDF options. Apache-2.0.
  • pdfkit wraps the wkhtmltopdf command-line tool, whose Qt WebKit engine dates from 2012. wkhtmltopdf has been archived since January 2023 and pdfkit's last release was in 2021. MIT (pdfkit) and LGPL-3.0 (wkhtmltopdf).

Requirements, installation and license

Item PD4ML WeasyPrint xhtml2pdf Playwright (Chromium) pdfkit (wkhtmltopdf)
Install pip install pd4ml pip install weasyprint pip install xhtml2pdf pip install playwright, then playwright install chromium pip install pdfkit plus the wkhtmltopdf binary
Python version 3.9 or later 3.10 or later 3.10 or later 3.10 or later Any Python 3
Runtime Python plus Java 8 or later Python plus the Pango library (1.44 or later) Pure Python (ReportLab) Python plus a downloaded Chromium Python plus wkhtmltopdf
Engine Own print-focused engines: v40 and v42 (Chrome-verified layout) 4.2 Own CSS layout engine ReportLab Platypus Chromium Qt WebKit (2012)
Maintained Supported Supported Supported Supported Not supported wkhtmltopdf archived in 2023
License Commercial, perpetual BSD-3-Clause Apache-2.0 Apache-2.0 MIT; wkhtmltopdf LGPL-3.0
Price €100 single, €1,600–3,200 site, €8,000–16,000 enterprise (one-time) Free Free Free Free
Commercial support Supported Partial or add-on From its authors' company Not supported Community Not supported Community Not supported

PD4ML's Java runs inside the Python process: there is no separate server to deploy, and a long-running process (a web server, a worker) starts Java once. The first conversion of a fresh installation downloads the PD4ML library unless it was installed ahead of time with pd4ml install. Details: PD4ML for Python.

HTML and CSS layout support

Feature PD4ML WeasyPrint xhtml2pdf Playwright (Chromium) pdfkit (wkhtmltopdf)
CSS level Modern CSS; v42 engine checked against Chrome 4.2 CSS 2.1 and much of CSS3, paged media CSS 2.1 and some CSS3 Current Chrome CSS 2.1 and early CSS3 of 2012 WebKit
Flexbox Supported Partial or add-on Supported, "not deeply tested" Partial or add-on Level 1; inline-flex laid out as flex Supported Not supported Old -webkit-box syntax only
CSS Grid Supported Template areas, line names, dense placement 4.2 Partial or add-on No subgrid, inline-grid, auto-fill/auto-fit, or rows split across pages Not supported Supported Not supported
Absolute and fixed positioning Supported Supported Supported Supported Supported
CSS @page Supported Size, :first/:left/:right, named pages, margin boxes 4.2 Supported Named pages, margin boxes, :nth() Partial or add-on Size, margins, named page templates and frames Partial or add-on Size; margins through options Not supported
Headers, footers, page numbers Supported HTML headers and footers with page and total counts Supported Margin boxes and counters Supported Static frames, <pdf:pagenumber> Partial or add-on Header and footer templates Supported HTML header and footer
Multi-column layout Supported Partial or add-on No column breaks or spanning Not verified Supported Partial or add-on
Media queries Supported Level 4 range syntax 4.2 Supported Partial or add-on Media types only Supported Supported
Vector SVG Supported Supported Supported Through svglib Supported Supported
MathML Supported Not verified Not supported Supported Not supported
Barcodes and QR codes Supported QR codes (<qrcode>) Not supported Supported <pdf:barcode> Not supported Through JavaScript libraries Not supported Through JavaScript libraries
JavaScript Not supported Not supported Not supported Supported Supported Old engine

PD4ML's @page support is described in CSS @page rules, and its DOM API (Java, DMS and UA editions) in modifying the HTML document before conversion.

A headless browser renders whatever Chrome renders, including pages built by JavaScript, but its print to PDF knows little about paged documents: no margin boxes, no named pages, no PDF standards. WeasyPrint is the strongest of the open-source libraries for paged media.

Output formats

Format PD4ML WeasyPrint xhtml2pdf Playwright (Chromium) pdfkit (wkhtmltopdf)
PDF Supported Supported Supported Supported Supported
DOCX (Word) Supported Not supported Not supported Not supported Not supported
RTF Supported Not supported Not supported Not supported Not supported
PNG and TIFF images Supported Paged Not supported Not supported Partial or add-on Screenshots, not paged Partial or add-on wkhtmltoimage, not through pdfkit
Several formats from one parse Supported Not supported Not supported Not supported Not supported

PDF/A, PDF/UA and e-invoices

Standard PD4ML WeasyPrint xhtml2pdf Playwright (Chromium) pdfkit (wkhtmltopdf)
PDF/A Supported PDF/A-1a/1b, 2a/2b/2u, 3a/3b/3u, 4, 4e Supported PDF/A-1 to 4 (a, b, u, e, f) Not supported Not supported Not supported
PDF/UA accessible PDF Supported PDF/UA-1 and PDF/UA-2 Supported PDF/UA-1 and PDF/UA-2 Not supported Partial or add-on Tagged PDF option, no PDF/UA conformance Not supported
ZUGFeRD and Factur-X Supported Presets, including accessible PDF/A-3a invoices Supported PDF/A-3b with the invoice attached Not supported Not supported Not supported
PDF/X for print Not supported Supported PDF/X-1a, 3, 4, 5g Supported PDF/X-4 Not supported Not supported
PDF 2.0 Supported Not verified Not supported Not supported Not supported

WeasyPrint states that it generates these variants but does not guarantee their validity; check its output with a validator. See PDF/A, PDF/UA and e-invoicing formats and ZUGFeRD and Factur-X PDF invoices.

Fonts and international text

Feature PD4ML WeasyPrint xhtml2pdf Playwright (Chromium) pdfkit (wkhtmltopdf)
TrueType and OpenType embedding with subsetting Supported Supported Supported Supported Supported
Arabic and Hebrew, right to left Supported Supported Supported Shaped with arabic-reshaper Supported Supported
Indic and other complex scripts Supported Supported HarfBuzz through Pango Not verified Supported Partial or add-on
Kerning and ligatures Supported Supported Not verified Supported Supported
Color emoji Supported COLR and CBDT fonts 4.2 Not verified Not verified Supported Partial or add-on
WOFF2 web fonts Supported Supported Supported With the fonts extra Supported Not supported

Security, signatures and forms

Feature PD4ML WeasyPrint xhtml2pdf Playwright (Chromium) pdfkit (wkhtmltopdf)
Passwords and permissions Supported RC4, AES-128/256 Not supported Supported Not supported Not supported
Digital signatures Supported PKCS#12, PKCS#11, HSM, cloud KMS, RFC 3161, PAdES-LT/LTV Not supported Supported PKCS#12 and PKCS#11 through pyHanko Not supported Not supported
Fillable forms from HTML Supported Inputs, selects, text areas, buttons Supported Text inputs, check boxes, text areas, selects Supported No radio button fields Not supported Partial or add-on --enable-forms
Merge, optimize, XFDF Supported Not supported Not supported Not supported Not supported
Fetching untrusted resources Supported Allow and deny lists Supported URL fetcher Supported Restrictive defaults Partial or add-on Browser sandbox Not supported Known SSRF issue, unpatched

Any of these PDFs can also be signed afterwards with a separate Python library such as pyHanko.

When to choose which

  • WeasyPrint suits print-designed documents written for paged media (margin boxes, named pages), PDF/A, PDF/UA and PDF/X, when a permissive license matters and Pango can be installed.
  • xhtml2pdf suits simple reports and invoices in pure Python, with no system libraries, including encrypted and signed output.
  • Playwright suits pages that need JavaScript or must look exactly like the browser, when no PDF standard is required and a browser can run on the server.
  • pdfkit with wkhtmltopdf suits existing projects only: the engine is unmaintained and has unpatched security issues, so new projects should use one of the others.
  • PD4ML for Python suits templates written with modern CSS (Flexbox, Grid, @page), documents that also need DOCX or RTF, PDF/UA and e-invoices from HTML, digital signatures with long-term validation, and teams that want commercial support. It needs Java on the server.

Frequently asked questions

What is the best Python library for converting HTML to PDF?

For print-designed HTML without JavaScript, WeasyPrint is the strongest free option. For pages that depend on JavaScript, a headless Chromium through Playwright. If you need CSS Grid without limits, Word output, PDF/A together with digital signatures, or commercial support, PD4ML for Python covers that through pip, with Java on the server.

Is PD4ML a good alternative to WeasyPrint?

Yes, when you need DOCX or RTF output, digital signatures, encryption, CSS Grid features WeasyPrint does not support, or one library for PDF, Word and images. WeasyPrint needs no Java and is free; it is the better fit for teams that only need PDF.

Is PD4ML a good alternative to wkhtmltopdf and pdfkit?

Yes. wkhtmltopdf was archived in January 2023 and its WebKit engine dates from 2012, so it supports neither Flexbox nor Grid. PD4ML supports both, has no browser engine to keep patched, and adds PDF/A, PDF/UA and signatures.

Should I use a headless browser instead?

A headless Chromium (Playwright, pyppeteer) renders exactly what Chrome shows, JavaScript included. It cannot produce PDF/A, PDF/UA, encrypted or signed PDFs, and each server needs a browser to install and keep updated. PD4ML does not run JavaScript; it lays out the HTML it is given.

Do I need Java to use PD4ML in Python?

Yes. PD4ML for Python starts a Java 8 or later virtual machine inside the Python process. There is no separate server; a long-running process starts Java once, and each conversion then takes milliseconds for an ordinary document.

Can Python create PDF/A and ZUGFeRD invoices from HTML?

Yes, with PD4ML or WeasyPrint. PD4ML has presets for ZUGFeRD and Factur-X on PDF/A-3, including accessible PDF/A-3a invoices; WeasyPrint documents Factur-X on PDF/A-3b with the invoice attached.

Can Python convert HTML to Word (DOCX)?

Among these libraries, only PD4ML converts HTML and CSS to DOCX and RTF, from the same layout as the PDF.

Try PD4ML for Python

Install the module with pip install pd4ml and convert one of your own templates. Unlicensed output carries a watermark, with all features enabled. See PD4ML for Python, the comparison with PHP libraries, the comparison with Java HTML-to-PDF libraries, and PD4ML editions and prices.

Product names are trademarks of their respective owners. Information about other libraries is taken from their public documentation as of November 2026 and may have changed; corrections are welcome through PD4ML support. This page is not legal advice on open-source licenses.