Skip to main content

pdf_io

Create PDF files in Python: convert SVG, draw pages, plot data, render PNG or JPEG. No dependencies: a bundled C library does the heavy lifting.

showcase

  • Convert SVG to PDF: shapes, paths, text with embedded font subsets, gradients, patterns, clipping, masks, markers, images (PNG, JPEG, and JPEG XL when libjxl is installed) and CSS. With libjxl, images can also be written as JPEG XL (/JXLDecode, as PDFium reads it).
  • Draw a scene with pdf_io.draw (drawsvg-style) and save it as PDF, SVG, PNG, JPEG, JPEG XL or AVIF.
  • Draw on pages with Document and Canvas (HTML-canvas-style): multiple pages, links, bookmarks, metadata, placed SVG files.
  • Lay out text: paragraphs in boxes, justified or not, greedy or Knuth–Plass line breaking, kerning, ligatures, rich text with links, overflow into further boxes.
  • Print and archive: CMYK output, spot colors (Separation), ink limit, ICC output intent; PDF/A-2b, 2u and 3b with file attachments.
  • Plot: markers at many points, each with its own shape, size, colors and opacity; lines of millions of points; many bars and polygons; heatmaps through color maps (plot_io, built on pdf_io, names them); histograms, kernel densities, contours and swarm layouts computed in C. Coordinates are sequences or any buffer (array, numpy arrays, ...). simplify leaves out what later points hide and decimates long lines, within half a level per pixel.
  • Rasterize groups, SVG filters and whole pages (PNG, JPEG, JPEG XL, AVIF) with the same rendering as the PDF.

Install

pip install .

Python 3.11+. No dependencies. Copying the pdf_io/ directory into a project also works.

The C library is bundled, prebuilt for Linux (x86_64, aarch64), Windows (x86_64, arm64) and macOS (arm64); pip compiles nothing. On other platforms, build it with tools/build_native.py and point PDF_IO_NATIVE_LIB at it; without it, plain vector drawing still works and the bulk features (markers, lines, heatmaps, rasterization, PNG, image decoding) raise NativeLibraryError.

Quick start

import pdf_io

pdf_io.convert_file("drawing.svg")                 # writes drawing.pdf
pdf_bytes = pdf_io.svg_to_pdf(svg_text)
pdf_io drawing.svg out.pdf
import pdf_io.draw as draw

d = draw.Drawing(400, 300)                         # CSS pixels, origin top-left
d.append(draw.Circle(200, 150, 80, fill="teal"))
d.append(draw.Text("Hello", 32, 200, 160, text_anchor="middle", fill="white"))
d.save_pdf("hello.pdf")
d.save_svg("hello.svg")
from pdf_io import Document

doc = Document(title="Report")
page = doc.add_page(size="A4")                     # points, origin top-left
page.font_size = 24
page.fill_text("Report", 50, 80)
page.draw_markers(xs, ys, size=4, fill="steelblue", stroke=None)
page.draw_heatmap(values, 50, 300, 400, 250, cmap=["#440154", "#21918c", "#fde725"])
doc.save("report.pdf")

Documentation

  • API.md: the complete API, supported SVG features, fonts, rasterization and limits.
  • EXAMPLES.md: worked examples (scatter plot, bubble chart, heatmap, multi-page document, rasterization, filters, PNG).

Limits

  • Text: no complex-script shaping or bidirectional reordering. Kerning and ligatures apply to laid-out paragraphs only.
  • Fonts: WOFF2 and CFF2 (variable OpenType) fonts are not supported.
  • Filters can only be reproduced as pixels, so they are opt-in.
  • Animation and scripting are ignored: the initial state is drawn.

Development

python -m unittest discover -s tests -t tests

Tests generate their own fonts and images and ignore installed fonts.

mypy                                       # type check (configured in pyproject.toml)

The package ships type annotations (py.typed); mypy is a development tool only.

python tools/regress.py --render --check   # output vs. HEAD on tests/corpus
python tools/regress.py --base main --system
python tools/bench.py                      # timings quoted in API.md

regress.py converts every SVG of the corpus with the working tree and with a git revision and compares the page content streams and rasterized images byte for byte; --render reports pixel differences of changed files and --check reports files poppler warns about.

pip install ziglang==0.15.1                # or: pip install -e .[dev]
python tools/build_native.py               # rebuild pdf_io/_native/bin/*
python tools/build_native.py --check       # binaries match the sources, byte for byte
python tools/crosscheck.py --qemu qemu-aarch64-static   # same pixels on x86_64 and aarch64

The C library and its rules (no libc, no imports, deterministic floating point) are described in pdf_io/_native/README.md, with the sanitizer build and the fuzzers (tests/fuzz_native.py).

python tools/verapdf.py                    # PDF/A validation of the corpus

verapdf.py converts the corpus at each PDF/A level and validates the files with veraPDF (on PATH or --verapdf); the PDF/A unit tests also run veraPDF when it is on PATH.

License

BSD 3-Clause, see LICENSE.

Metadata

Release files for pdf-io 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pdf-io 0.5.0
File Size Uploaded Provenance
pdf_io-0.5.0.tar.gz 1.9 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pdf-io 0.5.0
File Interpreter ABI Platform
pdf_io-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 3.1 MB

Release files / pdf_io-0.5.0.tar.gz

Download URL pdf_io-0.5.0.tar.gz
Size 1.9 MB
Tags Source
SHA-256 checksum
How to use checksums
5b161c59880b3641ecb7f4ede100184ef9b4d780b1c4811d9bf65d94bb844b25
BLAKE2b-256 checksum
How to use checksums
67fff35eb3cf78ca21f7edfcbd582f3f0c9edb20e6dc8063cd8fe31c11a38b5b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Release files / pdf_io-0.5.0-py3-none-any.whl

Download URL pdf_io-0.5.0-py3-none-any.whl
Size 1.2 MB
Tags Python 3
SHA-256 checksum
How to use checksums
29a1a0cde5768bd43fcafbb74ecc31ab5fe99f37742ee261a52e37db43b5af5a
BLAKE2b-256 checksum
How to use checksums
b219c03f32780856990a590c01f046614a6b9c4ecbf7891e8dc967e19e79c504
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Security for pdf-io 0.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page