All formats

ReportLab

LanguagePython 3.9+
LicenseBSD (the open-source ReportLab Toolkit; ReportLab PLUS is commercial)
RepositoryReportLab open source (Mercurial), PyPI
Documentationdocs.reportlab.com
Depends onPillow, charset-normalizer; optional pyaes for AES-256 encryption
Read / writeno / yes

ReportLab generates PDFs from Python, at two levels:

It also draws charts, barcodes and AcroForm fields, embeds TrueType fonts and encrypts output. It’s used for invoices, reports and statements in many Python applications. ReportLab can’t read or modify existing PDFs; combine it with pypdf to stamp generated content onto existing pages.

Installation#

Shell
pip install reportlab
# for AES-256 encryption
pip install pyaes

Basic usage: create a PDF with text#

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

c = canvas.Canvas("hello.pdf", pagesize=A4)
c.setTitle("Hello")
c.setAuthor("Me")
width, height = A4
c.setFont("Helvetica-Bold", 24)
c.drawString(72, height - 72, "Hello, PDF!")  # origin is bottom-left, units are points
c.setFont("Helvetica", 12)
c.drawString(72, height - 100, "Created with ReportLab.")
c.showPage()  # end page 1
c.drawString(72, height - 72, "Page 2")
c.save()

How to create a document with paragraphs and a table#

Python
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Paragraph, SimpleDocTemplate, Spacer, Table, TableStyle

styles = getSampleStyleSheet()
doc = SimpleDocTemplate("invoice.pdf", pagesize=A4, title="Invoice")

data = [["Item", "Qty", "Price"], ["Widget", "2", "9.99"], ["Gadget", "1", "24.50"]]
table = Table(data, colWidths=[200, 60, 80], repeatRows=1)
table.setStyle(TableStyle([
    ("BACKGROUND", (0, 0), (-1, 0), colors.lightgrey),
    ("GRID", (0, 0), (-1, -1), 0.5, colors.grey),
    ("ALIGN", (1, 1), (-1, -1), "RIGHT"),
]))

story = [
    Paragraph("Invoice #1001", styles["Title"]),
    Paragraph("Thank you for your <b>order</b>.", styles["Normal"]),
    Spacer(1, 12),
    table,
]
doc.build(story)

Platypus breaks the story across pages automatically; repeatRows=1 repeats the table header on every page.

How to use a TrueType font for Unicode text#

The built-in fonts cover only Latin-1. Register a TrueType font to write other scripts:

Python
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

pdfmetrics.registerFont(TTFont("DejaVuSans", "DejaVuSans.ttf"))
c.setFont("DejaVuSans", 14)
c.drawString(72, 700, "Zażółć gęślą jaźń · Привет")

How to create a fillable PDF form#

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

c = canvas.Canvas("form.pdf", pagesize=A4)
c.drawString(72, 750, "Name:")
c.acroForm.textfield(name="name", x=120, y=740, width=200, height=20, tooltip="Your name")
c.acroForm.checkbox(name="agree", x=120, y=700, size=16)
c.save()

How to encrypt a PDF#

Python
from reportlab.lib import pdfencrypt
from reportlab.pdfgen import canvas

enc = pdfencrypt.StandardEncryption("user", ownerPassword="owner",
                                    canPrint=1, canModify=0, strength=256)  # 256 needs pyaes
c = canvas.Canvas("secret.pdf", encrypt=enc)
c.drawString(72, 750, "Secret")
c.save()

strength=128 (RC4) works without extra packages but isn’t secure.

Tips#