Introduction
PDF generation is a common task for web developers and data scientists in the Python ecosystem. Whether you need to create invoices, financial reports, user certificates, e-books, data exports, or print-ready documents, Python offers a rich ecosystem of libraries for this purpose.
In this article, we'll walk you through eight of the best Python PDF generation libraries available in 2026. These libraries generally fall into two distinct approaches:
- Canvas-based: With this approach, you draw every element (text, lines, images, tables) programmatically using coordinates or layout objects. This gives absolute control but requires more code. Examples include ReportLab, FPDF2, PyMuPDF, and borb.
- HTML-to-PDF: Here, you write regular HTML and CSS (often using templates like Jinja) and let the library render it to PDF. This is faster to prototype if you already know web technologies. Examples include WeasyPrint, xhtml2pdf, PDFKit, and Playwright.
1. ReportLab
ReportLab is one of the oldest and most powerful pure-Python PDF generation libraries, with over two decades of production use. It follows a canvas-based paradigm at its core, where you specify exact coordinates to position text, lines, and images on a page. For more dynamic, flowable documents, it includes PLATYPUS (Page Layout and Typography Using Scripts), a high-level engine for manageable document structures.
To install ReportLab, run:
pip install reportlabHere's example code to generate a PDF file:
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from reportlab.lib import colors
from datetime import datetime
# Data
company_name = "NovaTech"
company_address = ["45 Innovation Drive", "Manchester"]
website = "www.novatech.com"
requested_by = "J. Smith"
items = [
("Marie", 1, 1.00),
("Gerty", 2, 12.00),
("Rosalyn", 3, 14.00),
("Barbara", 4, 12.00),
("Rita", 5, 19.00),
]
payment_terms = "30 days"
vat_rate = 0.0
# Canvas
c = canvas.Canvas("invoice.pdf", pagesize=A4)
width, height = A4
# Header
c.setFont("Helvetica-Bold", 12)
c.drawCentredString(width / 2, height - 40, "Renewal Invoice")
c.setFont("Helvetica", 9)
c.drawRightString(width - 40, height - 55, website)
# Company info
y = height - 100
c.setFont("Helvetica-Bold", 10)
c.drawString(40, y, company_name)
c.setFont("Helvetica", 9)
for line in company_address:
y -= 12
c.drawString(40, y, line)
y -= 20
c.drawString(40, y, f"Requested by: {requested_by}")
# Invoice meta
c.drawRightString(
width - 40,
height - 100,
f"Invoice time and date: {datetime.now().strftime('%H:%M:%S, %d.%m.%Y')}"
)
c.drawRightString(
width - 40,
height - 115,
f"Payment Terms: {payment_terms}"
)
# Table header
y -= 40
c.setFillColor(colors.HexColor("#1f4fa3"))
c.rect(40, y, width - 80, 20, fill=1, stroke=0)
c.setFillColor(colors.white)
c.setFont("Helvetica-Bold", 9)
c.drawString(45, y + 6, "Name")
c.drawRightString(300, y + 6, "Qty")
c.drawRightString(420, y + 6, "Unit Price")
c.drawRightString(width - 45, y + 6, "Total")
# ---------- Table Rows ----------
c.setFont("Helvetica", 9)
c.setFillColor(colors.black)
row_y = y - 18
for name, qty, price in items:
total = qty * price
c.drawString(45, row_y, name)
c.drawRightString(300, row_y, str(qty))
c.drawRightString(420, row_y, f"{price:.2f}")
c.drawRightString(width - 45, row_y, f"{total:.2f}")
# row line
c.setStrokeColor(colors.lightgrey)
c.line(40, row_y - 4, width - 40, row_y - 4)
row_y -= 18
# Save
c.save()
print("Invoice PDF generated.")Pros
- Complete control: ReportLab offers unparalleled precision over every element's placement
- Mature and well-documented: It has an extensive toolkit and a large community
- Feature-rich: It provides native support for charts, graphs, and vector graphics
- Battle-tested: Used at scale by organizations like Wikipedia
Cons
- Steep learning curve: ReportLab requires understanding its coordinate system and concepts, which may be challenging for beginners
- Verbose code: Building simple layouts can require many lines of code
- No HTML conversion: It cannot directly convert HTML/CSS to PDF
Best for
Complex, data-driven documents requiring precise layout control, such as financial reports, official certificates, or intricate forms.
For more information, see ReportLab documentation.
2. FPDF2
FPDF2 is the modern successor to the classic PyFPDF. It maintains the canvas-based approach but offers a significantly more "Pythonic" and intuitive API. It is designed to be lightweight and approachable for developers who need to generate documents without the overhead of ReportLab.
To install the library, run:
pip install fpdf2Here's example code to generate a PDF file:
from fpdf import FPDF
class PDFReport(FPDF):
def header(self):
# Set font
self.set_font("Arial", "B", 16)
# Title
self.cell(0, 10, "Monthly Sales Report", border=0, ln=1, align="C")
# Line break
self.ln(20)
def footer(self):
# Position at 1.5 cm from bottom
self.set_y(-15)
self.set_font("Arial", "I", 8)
# Page number
self.cell(0, 10, f"Page {self.page_no()}/{{nb}}", align="C")
# Create PDF
pdf = PDFReport()
pdf.alias_nb_pages() # Enable page number placeholder
pdf.add_page()
pdf.set_font("Arial", size=12)
# Add some text
pdf.cell(0, 10, "Here is a summary of Q1 2026 sales:", ln=1)
# Create a simple table
data = [["Region", "Revenue", "Growth"],
["North America", "$120,000", "12%"],
["Europe", "$85,000", "8%"],
["Asia", "$95,000", "15%"]]
for row in data:
for item in row:
pdf.cell(40, 10, item, border=1)
pdf.ln()
pdf.output("fpdf2_report.pdf")Pros
- Lightweight: FPDF2 is written in pure Python and has zero external dependencies, making installation and deployment simple.
- Simple API: The library is easy to learn and quick to get started with, especially compared to more complex tools like ReportLab.
- Good font support: Provides solid support for Unicode text and TrueType fonts.
- Actively maintained: Regular updates ensure compatibility with modern Python versions.
- Basic HTML-to-PDF support: Can render simple HTML content without additional tools.
Cons
- Limited advanced features: Lacks built-in support for charts, complex layouts, or high-level document structures.
- Basic styling capabilities: Layouts such as tables and advanced styling must be manually implemented.
Best for
Generating simple PDFs quickly, such as basic invoices, labels, or short documents, where you value minimal dependencies and a gentle learning curve.
For more information, see FPDF2 documentation.
3. PyMuPDF
PyMuPDF is the Python binding for MuPDF, a lightweight PDF, XPS, and E-book viewer and toolkit. While this article focuses on PDF generation, PyMuPDF's true strength lies in reading, extracting text, and manipulating existing PDFs at exceptional speed. It does support PDF creation, but the generation API is more low-level and less ergonomic than purpose-built libraries like ReportLab or FPDF2.
To install PyMuPDF, run:
pip install --upgrade pymupdfTo create a PDF file and add content to it, you start with an empty document object and insert pages and elements. Here's an example to generate a report table:
import pymupdf
# 1. Create document and page
doc = pymupdf.open()
page = doc.new_page() # A4 by default
# Page size helpers
page_width = page.rect.width
# 2. Report title
page.insert_text(
pymupdf.Point(50, 50),
"Monthly Report",
fontsize=16,
fontname="helv"
)
# 3. Table data
headers = ["Name", "Qty", "Unit Price", "Total"]
rows = [
("Michael", 1, 1.00),
("Dammy", 2, 12.00),
("Rose", 3, 14.00),
("Bimpe", 4, 12.00),
("Rita", 5, 19.00),
]
# 4. Table layout
start_x = 50
start_y = 100
row_height = 25
col_widths = [200, 60, 100, 100]
# 5. Draw table header
x = start_x
for i, header in enumerate(headers):
rect = pymupdf.Rect(
x,
start_y,
x + col_widths[i],
start_y + row_height
)
page.draw_rect(rect, color=(0, 0, 0), fill=(0.12, 0.31, 0.64)) # blue fill
page.insert_text(
pymupdf.Point(x + 5, start_y + 17),
header,
fontsize=10,
color=(1, 1, 1)
)
x += col_widths[i]
# 6. Draw table rows
current_y = start_y + row_height
for name, qty, price in rows:
total = qty * price
row_data = [name, str(qty), f"{price:.2f}", f"{total:.2f}"]
x = start_x
for i, cell in enumerate(row_data):
rect = pymupdf.Rect(
x,
current_y,
x + col_widths[i],
current_y + row_height
)
page.draw_rect(rect, color=(0.7, 0.7, 0.7)) # light border
page.insert_text(
pymupdf.Point(x + 5, current_y + 17),
cell,
fontsize=9
)
x += col_widths[i]
current_y += row_height
# 7. Totals section
net_total = sum(qty * price for _, qty, price in rows)
page.insert_text(
pymupdf.Point(page_width - 200, current_y + 30),
f"Net Total: {net_total:.2f}",
fontsize=10
)
# 8. Save and close
doc.save("pymupdf_report.pdf")
doc.close()For more advanced text layout and structured content (including HTML/CSS), see PyMuPDF documentation.
Pros
- Exceptional performance: The fastest Python PDF library for reading and processing.
- Best-in-class text extraction: Unmatched for extracting text, images, and metadata from existing PDFs.
- Powerful manipulation: Merge, split, rotate, redact, and annotate PDFs with ease.
- PDF creation supported: Can generate new PDFs, though this is not its primary focus.
Cons
- Native C dependency: Relies on the MuPDF C library, which can complicate installation in some environments.
- Generation is secondary: The PDF creation API is more manual and less ergonomic than dedicated generation libraries.
- No high-level abstractions: Lacks conveniences like automatic page breaks, tables, or template systems that ReportLab and FPDF2 provide.
Best for
PyMuPDF is the best choice when your primary need is reading, extracting, or manipulating existing PDFs at high speed. If you also need to generate simple PDFs within the same project, it can handle that too—but for generation-heavy workflows, consider pairing it with a dedicated library like ReportLab or FPDF2.
For more information, see PyMuPDF documentation.
4. WeasyPrint
WeasyPrint is an open-source Python library for converting HTML and CSS documents into high-quality PDF files. It is ideal for generating reports, invoices, and other automated documents from web content. WeasyPrint renders HTML using its own rendering engine (not a browser) and supports CSS paged media (such as headers, footers, page numbers).
To install the library, run:
pip install weasyprintImportant: WeasyPrint requires native system libraries including Pango, Cairo, and GDK-PixBuf. On Linux, you'll need to install these via your package manager (e.g., apt-get install libpango-1.0-0 libpangocairo-1.0-0 libgdk-pixbuf2.0-0). On macOS, use Homebrew (brew install pango). Windows users should consult the installation guide for GTK runtime setup. This can be a significant hurdle in containerized or serverless environments.
Here's example code to generate an invoice:
from weasyprint import HTML, CSS
html_string = """
<!DOCTYPE html>
<html>
<head>
<style>
@page {
size: A4;
margin: 2cm;
@top-center {
content: "Company Confidential";
font-size: 10pt;
color: #666;
}
@bottom-right {
content: "Page " counter(page);
font-size: 10pt;
}
}
body { font-family: sans-serif; }
h1 { color: #2c3e50; }
.invoice-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.invoice-table th, .invoice-table td {
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}
.total { font-weight: bold; background-color: #f8f9fa; }
</style>
</head>
<body>
<h1>Sales Invoice</h1>
<p><strong>Client:</strong> Global Solutions Inc.</p>
<table class="invoice-table">
<thead><tr><th>Description</th><th>Quantity</th><th>Unit Price</th><th>Total</th></tr></thead>
<tbody>
<tr><td>Consulting Hours</td><td>10</td><td>$150.00</td><td>$1,500.00</td></tr>
<tr><td>Software License</td><td>1</td><td>$499.00</td><td>$499.00</td></tr>
<tr class="total"><td colspan="3">TOTAL DUE</td><td>$1,999.00</td></tr>
</tbody>
</table>
</body>
</html>
"""
# Generate PDF from HTML string
HTML(string=html_string).write_pdf("weasyprint_invoice.pdf")
print("PDF generated with WeasyPrint!")Pros
- Superior CSS support: WeasyPrint handles modern CSS, including flexbox and grid, better than most tools.
- Web developer friendly: It allows you to leverage existing HTML/CSS skills to build good-looking PDFs.
- Paged media: It provides excellent support for print-specific CSS (
@pagerules). - No browser needed: It's lighter and more predictable than browser-based tools.
Cons
- System dependencies are mandatory: Unlike pure Python libraries, WeasyPrint cannot work without Pango, Cairo, and GDK-PixBuf installed at the OS level. This makes deployment to Docker, AWS Lambda, or shared hosting significantly more complex.
- No JavaScript support: It lacks JavaScript support and only works with static HTML.
- Performance bottleneck: Can be slower than alternatives for very large documents.
Best for
Web developers converting HTML templates to print-ready PDFs, such as invoices, reports, or documentation where you want to leverage existing HTML/CSS skills.
For more information, see WeasyPrint documentation.
5. xhtml2pdf
xhtml2pdf is a pure-Python HTML-to-PDF converter built on top of the ReportLab Toolkit, html5lib and pypdf. It translates HTML and a subset of CSS into ReportLab drawing commands. Its main advantage is simplicity and ease of deployment, as it has no external system dependencies.
To install the library, run:
pip install xhtml2pdfThe following example generates a statement of account using HTML and CSS with xhtml2pdf:
from xhtml2pdf import pisa
# HTML content as a string
source_html = """
<html>
<head>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f9f9f9;
}
h2 {
color: #2d5016;
border-bottom: 3px solid #2d5016;
padding-bottom: 10px;
font-size: 24px;
}
p {
color: #333;
font-size: 12px;
margin: 10px 0;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 15px;
background-color: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
th {
background-color: #2d5016;
color: white;
padding: 12px;
text-align: left;
font-weight: bold;
}
td {
padding: 10px 12px;
border-bottom: 1px solid #ddd;
}
tr:last-child td {
border-bottom: none;
}
</style>
</head>
<body>
<h2>Statement of Account</h2>
<p>Date: March 15, 2026</p>
<table>
<tr>
<th>Date</th><th>Description</th><th>Amount</th>
</tr>
<tr>
<td>2026-03-01</td><td>Monthly Subscription</td><td>$29.99</td>
</tr>
<tr>
<td>2026-03-10</td><td>Service Fee</td><td>$5.00</td>
</tr>
</table>
</body>
</html>
"""
# Output PDF file
output_filename = "xhtml2pdf_statement.pdf"
# Convert HTML to PDF
with open(output_filename, "w+b") as result_file:
pisa_status = pisa.CreatePDF(
src=source_html,
dest=result_file
)
if pisa_status.err:
print("Error during conversion")
else:
print("PDF created.")Pros
- Pure Python: xhtml2pdf installs anywhere Python runs, meaning no extra dependencies needed.
- Easy setup: It's quick to get started and simpler than WeasyPrint on shared hosting.
- Django-friendly: Integrates seamlessly with Django views and templates.
Cons
- Limited CSS support: Only CSS 2.1 and a small subset of CSS 3 (no flex/grid).
- Slower development: Its development pace has slowed compared to others. Its latest version was released in February 2025.
- Struggles with complex layouts: Modern, intricate designs may render incorrectly.
Best for
Simple HTML-to-PDF conversion tasks within Django projects or environments where installing system dependencies (like WeasyPrint requires) is not possible.
6. PDFKit
PDFKit is a Python wrapper for wkhtmltopdf, a command-line tool to render HTML into PDF and various image formats using the Qt WebKit rendering engine. It offers a very simple API for converting URLs, HTML files, or HTML strings to PDF with just a single function call.
To install the library, run:
pip install pdfkitThen, you also need to install wkhtmltopdf separately:
- Ubuntu/Debian:
sudo apt-get install wkhtmltopdf - macOS:
brew install wkhtmltopdf - Windows: Download from wkhtmltopdf.org
The following code snippet generates PDFs from both URL and HTML string:
import pdfkit
# Convert a live website URL to PDF
pdfkit.from_url('https://en.wikipedia.org/wiki/Python_(programming_language)', 'wikipedia_page.pdf')
# Convert an HTML string to PDF
html_content = """
<h3>Internal Memo</h3>
<p>To: All Staff</p>
<p><strong>Subject:</strong> Team Building Event</p>
<p>Our event will be held on Friday. Please RSVP.</p>
"""
pdfkit.from_string(html_content, 'memo.pdf')
print("PDFs created with PDFKit")Pros
- Easy to use API: The PDFKit library is essentially a one-function API with several methods and options to generate PDFs.
- Convert live URLs: It can directly snapshot a live web page to PDF.
- Decent rendering capability: It relies on a mature rendering engine that handles standard HTML and CSS reasonably well.
Cons
- External binary: PDFKit requires the
wkhtmltopdfbinary, which adds extra setup and deployment complexity. - Unmaintained core dependency:
wkhtmltopdfitself is deprecated and no longer actively maintained. - Limited JavaScript support: JavaScript support is patchy and complex or modern JavaScript-heavy pages may fail to render correctly.
Best for
Quickly converting static HTML pages or URLs to PDF in environments where you can control the installation of the wkhtmltopdf binary.
7. Playwright
Playwright is a modern browser automation library from Microsoft that can generate PDFs using a real Chromium browser. This provides the highest rendering fidelity and full JavaScript support, making it perfect for converting dynamic web content and single-page applications.
Install it with Pip:
pip install playwrightThen install the Chromium browser for PDF generation:
playwright install chromiumHere's an example that generates a PDF from a URL using custom settings (such as setting the print paper size and adding a header and footer):
from playwright.sync_api import sync_playwright
def generate_pdf_from_url(url, output_path):
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
# Navigate to URL
page.goto(url)
# Wait for content to load (important for JavaScript-heavy pages)
page.wait_for_load_state('networkidle')
# Generate PDF with custom options
page.pdf(
path=output_path,
format='A4',
margin={
'top': '20px',
'right': '20px',
'bottom': '20px',
'left': '20px'
},
print_background=True,
display_header_footer=True,
header_template='<div style="font-size:10px; text-align:center; width:100%;">My Company Report</div>',
footer_template='<div style="font-size:10px; text-align:center; width:100%;"><span class="pageNumber"></span> / <span class="totalPages"></span></div>'
)
browser.close()
# Generate PDF from URL
generate_pdf_from_url('https://wikipedia.org', 'webpage.pdf')Pros
- Best rendering fidelity: Playwright uses a real Chromium browser, so what you see in Chrome is exactly what you get in the PDF, including complex CSS and layout edge cases.
- Full JavaScript support: Dynamic content, client-side rendering, and SPAs work out of the box without special configuration.
- Actively maintained: Playwright is developed and updated by Microsoft, ensuring long-term stability and modern web support.
- Built-in auto-waiting: The engine automatically waits for fonts, images, and scripts to load before generating the PDF.
Cons
- Large browser dependency: Playwright requires downloading a Chromium binary (~150-170 MB), which increases setup size.
- Higher resource usage: Running a full browser consumes more CPU and memory than lightweight PDF libraries.
- Overkill for simple HTML: Static pages without JavaScript are better served by simpler, faster tools.
- Slower startup time: Browser initialization adds noticeable latency, especially in short-lived scripts or serverless environments.
Best for
JavaScript-heavy pages, single-page applications (React, Vue, Angular), or when you need pixel-perfect browser rendering of complex web content.
For more information, see the following resources:
Note on Pyppeteer: Pyppeteer is a Python port of the Node.js Puppeteer library, offering similar browser-based PDF generation capabilities. However, Playwright has become the recommended choice due to more active maintenance, better cross-browser support, and improved API design. If you're choosing between the two, go with Playwright.
8. borb
borb is a modern, pure Python PDF library with an object-oriented API that feels more Pythonic than traditional PDF libraries. It supports both creating new PDFs and reading/modifying existing ones, with advanced features like barcodes, forms, and annotations.
To install borb, run:
pip install borbThe following example creates a document with paragraphs, table, and barcode:
from borb.pdf import Document, Page, PageLayout, Paragraph, PDF, SingleColumnLayout
from borb.pdf import FixedColumnWidthTable, Barcode, HexColor
# 1. Create Document and Page
d: Document = Document()
p: Page = Page()
d.append_page(p)
l: PageLayout = SingleColumnLayout(p)
# 2. Add Title
l.append_layout_element(
Paragraph("Product Specification Sheet",
font_size=24,
font_color=HexColor("003366")
)
)
# 3. Add Table (Using Chaining)
# Note: Since it's 3x3, we chain exactly 9 Paragraphs.
l.append_layout_element(
FixedColumnWidthTable(number_of_columns=3, number_of_rows=3)
.append_layout_element(Paragraph("Feature", font="Helvetica-Bold"))
.append_layout_element(Paragraph("Detail", font="Helvetica-Bold"))
.append_layout_element(Paragraph("Status", font="Helvetica-Bold"))
.append_layout_element(Paragraph("ID"))
.append_layout_element(Paragraph("PX-2026"))
.append_layout_element(Paragraph("Active"))
.append_layout_element(Paragraph("Weight"))
.append_layout_element(Paragraph("1.2 kg"))
.append_layout_element(Paragraph("Done"))
)
# 4. Add Barcode
l.append_layout_element(
Barcode(
barcode_data="0123456789",
size=(100, 100),
barcode_type=Barcode.BarcodeType.CODE_128,
)
)
# 5. Write the PDF
PDF.write(what=d, where_to="borb_output.pdf")
print("PDF generated successfully.")Pros
- Pure Python, no external dependencies: Borb installs easily with pip and works without system libraries or native builds.
- Modern, Pythonic API: The API is clean and intuitive, making PDF generation feel natural for Python developers.
- Advanced PDF features: Built-in support for barcodes, QR codes, form fields, and other interactive elements.
- Read and modify existing PDFs: You can open, edit, and extend existing PDF files instead of generating everything from scratch.
Cons
- Smaller community: Borb has fewer users and third-party examples compared to more established libraries like ReportLab.
- Limited documentation: Fewer tutorials and real-world guides mean a steeper learning curve for complex use cases.
- Commercial licensing for advanced features: Some powerful capabilities are only available under a paid license.
- Shorter production history: As a newer library, it has less long-term battle testing in large-scale systems.
Best for
borb is a great choice if you want a modern API with advanced PDF features like barcodes, forms, and annotations, especially when working on projects that require both creating and modifying PDFs.
For more information, see borb documentation.
Comparison Table
The following table compares the core characteristics of each library. Generally, canvas-based libraries provide granular, pixel-perfect control but require more verbose code, whereas HTML-based solutions allow you to leverage familiar web development skills to build visually polished PDFs with significantly less effort.
| Library | Primary Approach | Key Dependencies | Best For | Learning Curve |
|---|---|---|---|---|
| ReportLab | Canvas-based | None (Pure Python) | Complex, precise layouts (reports, forms) | Medium |
| FPDF2 | Canvas-based | None (Pure Python) | Simple PDFs, quick start, minimal deps | Easy |
| PyMuPDF | Read/Manipulate (+ basic generation) | MuPDF C library | Reading, extraction, manipulation; basic generation | Medium |
| WeasyPrint | HTML/CSS to PDF | System libraries (Pango, Cairo) | Web developers, print-ready PDFs from HTML | Easy |
| xhtml2pdf | HTML/CSS to PDF | None (Pure Python) | Simple HTML conversion, Django projects | Easy |
| PDFKit | HTML/URL to PDF | wkhtmltopdf binary | Quick conversion of URLs/static HTML | Easy |
| Playwright | Browser Rendering | Chromium/Firefox/WebKit | JavaScript-heavy pages, SPAs, exact rendering | Medium |
| borb | Canvas-based | None (Pure Python) | Modern API with barcodes/forms features | Medium |
Generating PDFs with DocuPotion
The Python libraries covered above are excellent tools for building PDF generation into your applications. However, as your needs scale, you may encounter challenges: managing server infrastructure, handling memory for large documents, keeping dependencies updated, and maintaining rendering consistency across environments.
DocuPotion offers a different approach that eliminates these operational concerns:
- Drag-and-drop template builder — Design professional PDF templates visually without writing layout code
- Simple REST API — Generate PDFs programmatically by sending data to your templates
- Managed infrastructure — No servers to maintain, no dependencies to update, no memory issues to debug
Here's how to generate a PDF using the DocuPotion API with Python's requests library:
import requests
API_KEY = "your_api_key"
TEMPLATE_ID = "your_template_id"
response = requests.post(
"https://api.docupotion.com/v1/create",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={
"templateId": TEMPLATE_ID,
"output": "url",
"expiration": 60,
"data": {
"customer_name": "Jane Smith",
"invoice_number": "INV-2026-001",
"total": "$1,250.00"
}
}
)
result = response.json()
print(f"PDF URL: {result['url']}")With just a few lines of code, you get a hosted PDF URL ready to share or download. DocuPotion handles the rendering, storage, and delivery.
Key benefits:
- Focus on your application logic instead of PDF infrastructure
- Consistent rendering without browser or system dependencies
- Scale from a few PDFs to thousands without changing your code
Learn more:
Conclusion
In the end, choosing the right PDF generation library in Python depends on your project's specific requirements and your expertise. The canvas-based approach gives ultimate control and is ideal for programmatic, data-driven documents. The HTML-to-PDF approach on the other hand, leverages web technologies for easier styling and is perfect for templated documents.
As a beginner, start with FPDF2 if you prefer programmatic generation, or WeasyPrint if you're comfortable with HTML/CSS. Both offer gentle learning curves and can handle most common use cases. For complex documents, ReportLab is a gold standard for precise layout control, professional reports, and documents requiring custom graphics or charts.
If your project demands speed and performance, PyMuPDF excels at high-performance operations, especially when you need both reading and writing capabilities. Finally, for JavaScript-heavy content, Playwright is a great choice, offering full browser rendering with complete JavaScript support.
As parting advice, the best way to decide is to try a couple of libraries that fit your use case. Generate a sample of your target document with each to evaluate the code clarity, performance, and output quality for your specific needs.
Frequently Asked Questions
What is the best Python library to generate PDFs?
For most use cases, FPDF2 or WeasyPrint are the best starting points. FPDF2 is ideal if you want a lightweight, pure-Python solution with no external dependencies. WeasyPrint is better if you're comfortable with HTML/CSS and want to create visually polished documents quickly. For complex, data-driven reports requiring precise layout control, ReportLab remains the industry standard.
Can Python create PDF from HTML?
Yes. Several Python libraries convert HTML to PDF: WeasyPrint offers the best CSS support (including flexbox and grid), xhtml2pdf is a pure-Python option that works well with Django, PDFKit wraps the wkhtmltopdf binary for quick conversions, and Playwright uses a real browser engine for pixel-perfect rendering of JavaScript-heavy pages.
How do I generate a PDF in Python without external dependencies?
Use FPDF2, xhtml2pdf, ReportLab, or borb. All four are pure Python libraries that install with pip and require no system libraries or external binaries. FPDF2 is the simplest to learn, while ReportLab offers the most features for complex documents.
Is ReportLab free to use?
Yes. ReportLab has an open-source version available under the BSD license that is free for both personal and commercial use. There is also a commercial version called ReportLab PLUS with additional features like advanced charting and encryption, but the open-source library covers most PDF generation needs.
Which Python PDF library is fastest?
PyMuPDF is generally the fastest Python PDF library, particularly for reading, processing, and batch operations. For pure PDF generation, FPDF2 and ReportLab are both performant choices. If you're converting HTML to PDF, WeasyPrint is faster than browser-based solutions like Playwright for static content.