Introduction
WeasyPrint is a Python library that renders HTML and CSS into PDF documents. Unlike headless-browser approaches, WeasyPrint implements its own CSS layout engine, producing clean, predictable output without depending on Chrome or Firefox. It is commonly used for generating invoices, reports, and printable documents from templates.
What WeasyPrint Does
- Converts HTML documents with full CSS support into PDF files
- Renders CSS Flexbox, Grid, multi-column layouts, and paged media features
- Embeds custom web fonts (WOFF, WOFF2, TTF, OTF) directly into PDFs
- Supports CSS bookmarks, page counters, headers/footers via @page rules
- Generates PDF/A-compliant output for archival and accessibility
Architecture Overview
WeasyPrint parses HTML with html5lib and CSS with tinycss2, building a formatting tree that maps to the CSS box model. The layout engine resolves Flexbox, Grid, floats, and positioned elements into page-sized fragments. Final rendering is performed by Cairo and Pango, producing vector-based PDF output. Images are fetched and embedded during the rendering phase.
Self-Hosting & Configuration
- Install via pip; system dependencies include Pango, Cairo, and GDK-PixBuf
- On Debian/Ubuntu: apt install libpango1.0-dev libcairo2-dev libgdk-pixbuf2.0-dev
- On macOS: brew install pango cairo gdk-pixbuf libffi
- Use Docker images (e.g., weasyprint/weasyprint) to avoid system dependency management
- Configure custom fonts by placing font files in system font directories or using @font-face in CSS
Key Features
- Modern CSS rendering including Flexbox, Grid, and CSS Variables
- @page support for page size, margins, headers, footers, and page breaks
- PDF bookmarks generated from HTML heading hierarchy
- PDF/A output for long-term archival compliance
- Runs as a Python library, CLI tool, or behind a web server for on-demand generation
Comparison with Similar Tools
- wkhtmltopdf — uses a WebKit engine; WeasyPrint has its own CSS engine with better paged media support
- Puppeteer/Playwright — headless Chrome rendering; heavier but supports JavaScript
- Prince — commercial CSS-to-PDF engine with broad CSS support; WeasyPrint is free and open source
- pdfkit (Python) — low-level PDF generation; WeasyPrint works from HTML/CSS templates
- Gotenberg — Docker microservice that wraps multiple converters; can use WeasyPrint internally
FAQ
Q: Does WeasyPrint run JavaScript? A: No. WeasyPrint is a CSS rendering engine only. Pre-render dynamic content server-side or use a headless browser for JS-dependent pages.
Q: Can I generate PDFs from Jinja2 templates? A: Yes. Render your Jinja2 template to an HTML string, then pass it to HTML(string=rendered_html).write_pdf().
Q: How do I handle large documents? A: WeasyPrint streams pages during rendering. For very large documents, increase available memory and consider splitting into multiple PDFs.
Q: Is WeasyPrint suitable for production invoicing? A: Yes. Many companies use it for invoice and report generation. Its deterministic rendering produces identical output across runs.