Skip to main content

Ferri PDF for Python

An HTML and CSS to PDF renderer for print, written in pure Rust. No browser and no JavaScript.

pip install ferri-pdf

Wheels are prebuilt for CPython 3.10 and later on Linux, macOS and Windows.

Rendering

import ferri_pdf

output = ferri_pdf.render("<h1>Hello</h1>")
with open("hello.pdf", "wb") as file:
    file.write(output.pdf)

render takes a str, or bytes decoded by the HTML encoding rules. It returns the PDF bytes, page_count, the located headings and the diagnostics for recovered input. Invalid markup, unsupported CSS and missing resources never raise; they are recovered as the specifications say and listed in diagnostics.

The interpreter lock is released while rendering, so threads render in parallel.

Options

options = ferri_pdf.RenderOptions(
    base="templates/invoice",
    stylesheets=["@page { size: A4; margin: 2cm }"],
    serif=["Georgia"],
    jpeg_quality=85,
    image_dpi=150,
    allow_http=False,
)
output = ferri_pdf.render(html, options)
Option Effect
base Directory that relative URLs resolve against (default: the working directory)
base_url Document URL that relative URLs resolve against, instead of base
stylesheets Author stylesheets applied after the document's own
user_stylesheets User-origin stylesheets
paper Paper size (width, height) in points when CSS sets none (default: A4)
color_scheme "light" or "dark" for prefers-color-scheme
contrast "no-preference", "less", "more" or "custom" for prefers-contrast
reduced_motion "no-preference" or "reduce" for prefers-reduced-motion
serif, sans_serif, monospace Installed families for each generic font
fallback Installed families tried for missing glyphs
image_dpi Downsample raster images to this resolution
jpeg_quality Re-encode opaque photos as JPEG at this quality, 1 to 100
include_layout Return the measured layout as output.layout
allow_content_loss Return the PDF even when a resource limit left content out
allow_http Fetch HTTP(S) resources with the built-in client (default: True)
file_root Refuse local files outside this directory
fetch Callable that loads every URL other than local files and data URLs

Rendering untrusted HTML? Set allow_http=False and file_root so a document cannot reach your network or read files outside its own assets, or route requests through fetch and decide there.

Fetching resources yourself

fetch receives each absolute URL that is not a file: or data: URL: HTTP(S), and any scheme your base_url uses, such as app://. It replaces the built-in HTTP client. Return the body as bytes, a ferri_pdf.Resource to add a content type or the final URL after redirects, or None when the resource is unavailable.

import httpx
import ferri_pdf

client = httpx.Client(headers={"Authorization": f"Bearer {token}"}, timeout=10)

def fetch(url: str) -> ferri_pdf.Resource | None:
    if not url.startswith("https://assets.example.com/"):
        return None
    response = client.get(url, follow_redirects=True)
    response.raise_for_status()
    return ferri_pdf.Resource(
        response.content,
        content_type=response.headers.get("content-type"),
        url=str(response.url),
    )

output = ferri_pdf.render(html, ferri_pdf.RenderOptions(fetch=fetch))

Relative URLs inside a fetched resource resolve against its url. An Exception raised by fetch, like None, leaves that resource unavailable and is reported in diagnostics; rendering carries on. KeyboardInterrupt, SystemExit and a return value of the wrong type stop further fetches and are raised from render. Local files still load from disk, within file_root when set.

Several documents in one PDF

output = ferri_pdf.render_parts([
    ferri_pdf.Part(cover_html, base="cover"),
    ferri_pdf.Part(body_html, base="body"),
])
for part in output.parts:
    print(part.first_page, part.page_count)

Each part starts on a new page. Parts can also be plain str or bytes, which use the options' base.

Errors

ferri_pdf.RenderError is raised when rendering fails. Its subclass ferri_pdf.ContentLostError is raised when a resource limit left content out of the PDF; its diagnostics list the losses and part names the one-based part of a multipart render. Pass allow_content_loss=True to get the PDF anyway. Invalid option values raise ValueError.

Licence

MIT. The bundled fonts, hyphenation patterns and specification data keep their own licences; see the repository.

Metadata

Release files for ferri-pdf 0.1.8

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

Source distribution (sdist)

Source distribution for ferri-pdf 0.1.8
File Size Uploaded Provenance Actions
ferri_pdf-0.1.8.tar.gz 9.7 MB With provenance Details for ferri_pdf-0.1.8.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for ferri-pdf 0.1.8
File Actions
ferri_pdf-0.1.8-cp310-abi3-win_arm64.whl CPython 3.10 abi3 Windows ARM64 Details for ferri_pdf-0.1.8-cp310-abi3-win_arm64.whl
ferri_pdf-0.1.8-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details for ferri_pdf-0.1.8-cp310-abi3-win_amd64.whl
ferri_pdf-0.1.8-cp310-abi3-musllinux_1_2_x86_64.whl CPython 3.10 abi3 Linux musl 1.2+ x86-64 Details for ferri_pdf-0.1.8-cp310-abi3-musllinux_1_2_x86_64.whl
ferri_pdf-0.1.8-cp310-abi3-musllinux_1_2_aarch64.whl CPython 3.10 abi3 Linux musl 1.2+ ARM64 Details for ferri_pdf-0.1.8-cp310-abi3-musllinux_1_2_aarch64.whl
ferri_pdf-0.1.8-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details for ferri_pdf-0.1.8-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
ferri_pdf-0.1.8-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details for ferri_pdf-0.1.8-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
ferri_pdf-0.1.8-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details for ferri_pdf-0.1.8-cp310-abi3-macosx_11_0_arm64.whl
ferri_pdf-0.1.8-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details for ferri_pdf-0.1.8-cp310-abi3-macosx_10_12_x86_64.whl

Total release size: 174.7 MB

Release files / ferri_pdf-0.1.8.tar.gz

Download URL ferri_pdf-0.1.8.tar.gz
Size 9.7 MB
Tags Source
SHA-256 checksum
How to use checksums
e49e200d56351d99fdceac90060ea6a13c6569f140f2b87e0a93219fc7d93626
BLAKE2b-256 checksum
How to use checksums
82fc4b1d181e76b6a3d322d57dd8fc139a7c19831d13b99cb06d66e2f4f6787a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.

Transparency log

Release files / ferri_pdf-0.1.8-cp310-abi3-win_arm64.whl

Download URL ferri_pdf-0.1.8-cp310-abi3-win_arm64.whl
Size 18.8 MB
Tags CPython 3.10 Windows ARM64 abi3
SHA-256 checksum
How to use checksums
9b0d99c5a3ebef5e52b4bfad4d6a4aa11a54be863ebbf615b9e40dae8e98e3ac
BLAKE2b-256 checksum
How to use checksums
3694f429a80b587cc6e049f9d374913b8055de37f667b0a2947c4c48c9d7415f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.

Transparency log

Release files / ferri_pdf-0.1.8-cp310-abi3-win_amd64.whl

Download URL ferri_pdf-0.1.8-cp310-abi3-win_amd64.whl
Size 20.0 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
76f2c202bfad1b17e771e9483da0dfc062df994a6e46edb4148c5ff5741763de
BLAKE2b-256 checksum
How to use checksums
46148107a3ebcd3d9cd905698fe346b44cadacde13b4547dc042a28b57ca129b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.

Transparency log

Release files / ferri_pdf-0.1.8-cp310-abi3-musllinux_1_2_x86_64.whl

Download URL ferri_pdf-0.1.8-cp310-abi3-musllinux_1_2_x86_64.whl
Size 22.2 MB
Tags CPython 3.10 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
15cc86ca520a57c11d3d0a3b7103cf85f86df91df9a1cf2dd7c65590605e315a
BLAKE2b-256 checksum
How to use checksums
36a913ae844923287e171795533709cc60f47df339e81717991af70a846ec68e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.

Transparency log

Release files / ferri_pdf-0.1.8-cp310-abi3-musllinux_1_2_aarch64.whl

Download URL ferri_pdf-0.1.8-cp310-abi3-musllinux_1_2_aarch64.whl
Size 21.5 MB
Tags CPython 3.10 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
35cb128fcc147cecbfa11ee5ffb337dc5f9000a75a91606515286cb24499e2ac
BLAKE2b-256 checksum
How to use checksums
446230548c18dbf5ea200c770a2a134d80bbea71acd86ac51c5c9cf8fc63d546
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.

Transparency log

Release files / ferri_pdf-0.1.8-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL ferri_pdf-0.1.8-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 21.3 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
aaf0d601a1aac7c28e848af40645febd18b944b74ed9d1de6d67ae79b3afdf0d
BLAKE2b-256 checksum
How to use checksums
8ecd2fbc3f97c5fa12eba2dcf07ab1c0463699d6635b7277f3996b13006d5a74
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.

Transparency log

Release files / ferri_pdf-0.1.8-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

Download URL ferri_pdf-0.1.8-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Size 21.2 MB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
c30e036bb9228bbc30a753dc61ffc08b0de264f62ab94e8976bb279814b23337
BLAKE2b-256 checksum
How to use checksums
d9d94329b4b793b3e9edb24448128c69e958721effc68a78ed8a2ae54a212784
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.

Transparency log

Release files / ferri_pdf-0.1.8-cp310-abi3-macosx_11_0_arm64.whl

Download URL ferri_pdf-0.1.8-cp310-abi3-macosx_11_0_arm64.whl
Size 19.7 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
90c7e4165be69a199de2eaa107db9e41021950ae0bdfbb78238d87b19f482ba2
BLAKE2b-256 checksum
How to use checksums
4cdf2fc4b8c49b286ea16dd4fa472ab35a7c7fe681409de97f2c3d1bea5c687e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.

Transparency log

Release files / ferri_pdf-0.1.8-cp310-abi3-macosx_10_12_x86_64.whl

Download URL ferri_pdf-0.1.8-cp310-abi3-macosx_10_12_x86_64.whl
Size 20.4 MB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
93d51bcee6a568383d61756d9652314b4165d82bc78500d2bd9f66a416a08d9d
BLAKE2b-256 checksum
How to use checksums
8bbc418be56e321901cee8901b36d5b2b727c0f01074b86a7a3cc71873821535
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.

Transparency log

Security for ferri-pdf 0.1.8

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.

Full provenance

All 9 files in this release have been uploaded with provenance metadata.

Select from 9 files

Attestation for ferri_pdf-0.1.8.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.

Transparency log

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