PDFPipe

Comparison

A Python alternative to ReportLab

ReportLab is the standard Python library for programmatic PDF generation. Its drawing API and PLATYPUS layout engine work, but they require you to describe your document as a sequence of drawing calls rather than as HTML. Every pixel of margin, every font weight, every table cell needs to be expressed in Python. PDFPipe renders your HTML template, including the Tailwind or Bootstrap your team already uses, with a real browser and returns a PDF with one HTTP call.

ReportLab versus a PDF render API

PDFPipeReportLab
Template formatHTML + CSS (Jinja2, etc.)Python drawing API (PLATYPUS / canvas)
Renders HTMLYes, full browser engineNo (own layout model)
CSS supportCompleteNone
Web fontsLoaded automaticallyMust embed manually as TTF
ImagesAny URL or inlineMust encode or load from disk
JavaScript in templateRuns before captureNot supported
Install sizeNone (HTTP call)~10 MB + GTK on some platforms
Designer workflowDesign in HTML, ship as PDFRewrite design in Python code

The PLATYPUS problem

PLATYPUS (Page Layout and Typography Using Scripts) is ReportLab's high-level layout engine. It introduces its own box model, paragraph styles, table classes, and flowable primitives. To render an invoice you already have in HTML, you need to rewrite it entirely in PLATYPUS classes. Any time your design changes, you update both the HTML template your users see and the PLATYPUS code that renders the PDF. Two sources of truth diverge over time. PDFPipe has one: your template.

Fonts, images, and modern layouts

ReportLab requires TTF or OTF font files to be registered before use. Every Google Font or brand typeface your design team chose needs to be downloaded, stored with your app, and registered at startup. Flexbox, CSS Grid, and modern spacing utilities are unavailable. PDFPipe loads fonts from any URL, renders CSS Grid natively, and supports modern CSS including custom properties and clamp().

From Jinja2 to PDF in one call

python
import os
import requests

html = """
<html>
<body style="font-family: system-ui; padding: 40px">
  <h1 style="color:#d23a1d">Invoice #4012</h1>
  <p>Acme Corp &middot; 12 June 2026</p>
  <table style="width:100%;border-collapse:collapse;margin-top:24px">
    <tr style="border-bottom:1px solid #ccc">
      <td style="padding:8px">Design retainer</td>
      <td style="padding:8px;text-align:right">$2,400</td>
    </tr>
  </table>
  <h2 style="text-align:right;margin-top:24px">Total: $2,400</h2>
</body>
</html>
"""

res = requests.post(
    "https://api.pdfpipe.xyz/v1/pdf",
    headers={"Authorization": f"Bearer {os.environ['PDFPIPE_API_KEY']}"},
    json={"html": html, "options": {"format": "A4"}},
)
res.raise_for_status()

with open("invoice.pdf", "wb") as f:
    f.write(res.content)

When to keep ReportLab

ReportLab is a good choice for pure Python environments with no external HTTP dependencies, where the document layout is simple and entirely code-driven, and where you need fine-grained control over PDF internals like encryption or custom metadata fields. For HTML-first workflows, web fonts, or modern CSS layouts, a render API produces better output with far less code.

Try it on the live playground with no signup. Full Python examples on the Python guide.

See pricing →