fpdf2

Lightweight PDF generation library for Python — pure Python, no external dependencies, creates PDF documents programmatically. fpdf2 features: FPDF class with add_page()/set_font()/cell()/multi_cell()/text() methods, image embedding (JPEG/PNG/GIF/WEBP), table support (Table class for complex tables), header/footer via inherited class methods, automatic page breaks, links (internal and external), TrueType font embedding, SVG support, HTML2FPDF for basic HTML rendering, output() to file or bytes, ArcAnnotation/Highlight for annotations, and templates for recurring layouts. Simpler than reportlab, no dependencies.

Evaluated Mar 06, 2026 (0d ago) v2.7.x
Homepage ↗ Repo ↗ Developer Tools python fpdf2 fpdf pdf generation text images tables
⚙ Agent Friendliness
67
/ 100
Can an agent use this?
🔒 Security
90
/ 100
Is it safe for agents?
⚡ Reliability
82
/ 100
Does it work consistently?

Score Breakdown

⚙ Agent Friendliness

MCP Quality
--
Documentation
85
Error Messages
80
Auth Simplicity
99
Rate Limits
99

🔒 Security

TLS Enforcement
90
Auth Strength
90
Scope Granularity
88
Dep. Hygiene
92
Secret Handling
90

Pure Python PDF library. Image embedding: validate image sources. User-controlled text in PDFs: sanitize to prevent PDF injection (though fpdf2 treats all text as literal). Font files from trusted sources only. output() returns unencrypted PDF — add password protection separately if needed.

⚡ Reliability

Uptime/SLA
85
Version Stability
82
Breaking Changes
78
Error Recovery
82
AF Security Reliability

Best When

Simple PDF generation without system dependencies — fpdf2 is pure Python with no C library requirements, ideal for simple reports, certificates, and invoices in constrained environments.

Avoid When

HTML-to-PDF conversion (use weasyprint), complex multi-column layouts (use reportlab), editing existing PDFs (use pikepdf), or when rich CSS styling needed.

Use Cases

  • Agent simple PDF — from fpdf import FPDF; pdf = FPDF(); pdf.add_page(); pdf.set_font('Helvetica', size=12); pdf.cell(200, 10, text='Hello World', new_x='LMARGIN', new_y='NEXT'); pdf.output('hello.pdf') — basic PDF; agent creates simple text PDF without dependencies; cell() creates text box
  • Agent invoice PDF — pdf = FPDF(); pdf.add_page(); pdf.set_font('Helvetica', 'B', 16); pdf.cell(0, 10, 'Invoice', align='C', new_y='NEXT'); pdf.set_font('Helvetica', size=11); pdf.multi_cell(0, 7, invoice_text) — multi-line; agent generates invoice with headers and multi-line text blocks
  • Agent with images — pdf = FPDF(); pdf.add_page(); pdf.image('logo.png', x=10, y=10, w=50); pdf.set_y(70); pdf.set_font('Helvetica', size=12); pdf.cell(200, 10, text='Report', new_y='NEXT') — image embedding; agent adds images to PDF; x/y in mm from top-left; w= controls width; height auto-scales
  • Agent table — from fpdf import FPDF, XPos, YPos; pdf = FPDF(); pdf.add_page(); with pdf.table() as table: row = table.row(); row.cell('Name'); row.cell('Value'); for name, val in data: row = table.row(); row.cell(name); row.cell(str(val)) — table API; agent creates data tables with auto-column sizing
  • Agent PDF bytes — pdf = FPDF(); pdf.add_page(); pdf.set_font('Helvetica', size=12); pdf.cell(200, 10, text=content); return pdf.output() — bytes; agent generates PDF bytes for HTTP response; output() without filename returns bytes (fpdf2); output('file.pdf') writes to file

Not For

  • HTML/CSS to PDF — fpdf2's HTML support is basic; for full HTML rendering use weasyprint
  • Complex document layouts — fpdf2 requires manual positioning; for complex layouts use reportlab PLATYPUS or weasyprint
  • Editing existing PDFs — fpdf2 creates new PDFs only; for modifying existing PDFs use PyPDF2 or pikepdf

Interface

REST API
No
GraphQL
No
gRPC
No
MCP Server
No
SDK
Yes
Webhooks
No

Authentication

Methods: none
OAuth: No Scopes: No

No auth — PDF generation library.

Pricing

Model: open_source
Free tier: Yes
Requires CC: No

fpdf2 is LGPL 3.0 licensed. Free for all use. Pure Python — no system dependencies.

Agent Metadata

Pagination
none
Idempotent
Full
Retry Guidance
Not documented

Known Gotchas

  • fpdf2 vs fpdf — pip install fpdf2 not fpdf (old version); from fpdf import FPDF works for both but fpdf2 has breaking changes from fpdf 1.x; fpdf2 cell() uses text= keyword not positional; fpdf2 multi_cell() API changed; agent requirements.txt: fpdf2>=2.7 not fpdf
  • cell() vs multi_cell() — cell(w, h, text) creates single-line cell, truncates overflow; multi_cell(w, h, text) wraps text to multiple lines; agent code with long text: use multi_cell(); cell() for table columns with known-short text; new_x/new_y control cursor position after cell
  • Coordinates are in mm from top-left — x=0, y=0 is top-left of page; default A4 is 210mm x 297mm; pdf.get_y() gets current Y position; pdf.set_xy(x, y) moves cursor; agent code: calculate positions in mm; margins: pdf.set_margins(left=20, top=20, right=20); effective width: pdf.epw (effective page width)
  • Fonts must be set before text — pdf.set_font('Helvetica', size=12) before any text call; changing font mid-document: call set_font() again; built-in fonts: Helvetica, Times, Courier; for Unicode/custom: pdf.add_font('Name', '', '/path/font.ttf'); TrueType fonts require ttf file accessible at render time
  • output() returns bytes in fpdf2 — pdf.output() returns bytes object in fpdf2 2.x; pdf.output('file.pdf') writes file AND returns None; agent code: return pdf.output() for bytes; or: pdf.output('path.pdf'); bytes_io = BytesIO(); pdf.output(bytes_io); bytes_io.getvalue() for buffer pattern
  • add_page() must be called before drawing — drawing operations before add_page() raise FPDFException; agent code: always add_page() first; auto_page_break=True (default) adds pages automatically when content reaches bottom; set_auto_page_break(auto=True, margin=15) to control break threshold

Alternatives

Full Evaluation Report

Comprehensive deep-dive: security analysis, reliability audit, agent experience review, cost modeling, competitive positioning, and improvement roadmap for fpdf2.

AI-powered analysis · PDF + markdown · Delivered within 30 minutes

$99

Package Brief

Quick verdict, integration guide, cost projections, gotchas with workarounds, and alternatives comparison.

Delivered within 10 minutes

$3

Score Monitoring

Get alerted when this package's AF, security, or reliability scores change significantly. Stay ahead of regressions.

Continuous monitoring

$3/mo

Scores are editorial opinions as of 2026-03-06.

5229
Packages Evaluated
26151
Need Evaluation
173
Need Re-evaluation
Community Powered