Back to blog
March 15, 20269 min read

HTML to PDF in Python: ReportLab vs WeasyPrint vs API

Compare Python PDF libraries and learn when an API-based approach saves you time, complexity, and infrastructure costs.

pythonreportlabweasyprintcomparison

Python PDF options

Python developers typically choose between three approaches for PDF generation:

ReportLab

The oldest Python PDF library. You build PDFs programmatically using canvas commands:

from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas

c = canvas.Canvas("output.pdf", pagesize=A4)
c.drawString(72, 800, "Hello World")
c.save()

This works for simple documents, but you're essentially drawing shapes and text pixel by pixel. There's no concept of HTML, CSS, or responsive layout. Building a complex invoice requires hundreds of lines of positioning code.

WeasyPrint

A CSS-based PDF renderer written in Python. Much better — you write HTML and CSS, and WeasyPrint renders it:

from weasyprint import HTML
HTML(string='<h1>Hello</h1>').write_pdf('output.pdf')

WeasyPrint is solid but has limitations: slow performance, incomplete CSS support (no flexbox), heavy system dependencies (Cairo, Pango, GDK), and complex installation on some platforms.

API-based (pdfRelay)

import requests

response = requests.post(
    'https://pdfrelay.com/api/v1/convert',
    headers={'Authorization': 'Bearer sk_live_...'},
    json={'source': 'html', 'content': html}
)

with open('output.pdf', 'wb') as f:
    f.write(response.content)

No system dependencies. No Cairo/Pango installation. Full CSS support including flexbox and grid. Works anywhere Python runs — local, Docker, Lambda, Heroku. Your HTML templates are the same ones you'd write for a web page. No proprietary API, no learning curve.

Ready to try pdfRelay?

Get started free. No credit card required.