A modern, fully-typed Python client for the Gotenberg PDF generation API, with sync and async support.
pip install "gotenberg-client[httpx]"from gotenberg_client import GotenbergClient
from pathlib import Path
with GotenbergClient("http://localhost:3000") as client:
with client.chromium.html_to_pdf() as route:
response = route.index(Path("my-index.html")).run()
response.to_file(Path("my-index.pdf"))Four lines (excluding imports) to convert HTML to PDF.
Gotenberg is a powerful, Docker-based API for PDF generation and manipulation using Chromium and LibreOffice under the hood. This client gives you a clean, Pythonic interface to all of its capabilities, so you can skip the multipart form-data boilerplate and focus on your documents.
- Fully typed with concrete return types and full
py.typedsupport - Sync and async APIs with identical interfaces
- Pluggable HTTP backends -- httpx (with HTTP/2), niquests, or requests — install whichever you prefer
- Pathlib-native -- pass
Pathobjects directly, no manual file handling - Thoroughly tested against a real Gotenberg server across multiple Python versions
- Broad route coverage including Chromium, LibreOffice, PDF merge/convert/split, health checks, and more
- If there's a route you need, just ask!
An HTTP backend is required. Pick the one that suits your project:
pip install "gotenberg-client[httpx]" # recommended — HTTP/2 and async support
pip install "gotenberg-client[niquests]" # alternative — HTTP/2 and async support
pip install "gotenberg-client[requests]" # sync-onlyIf you need MIME-type detection for automatic content-type headers, add the magic extra:
pip install "gotenberg-client[httpx,magic]"from gotenberg_client import GotenbergClient
from pathlib import Path
with GotenbergClient("http://localhost:3000") as client:
with client.chromium.html_to_pdf() as route:
response = route.index(Path("my-index.html")).run()
response.to_file(Path("my-index.pdf"))from gotenberg_client import AsyncGotenbergClient
from pathlib import Path
async with AsyncGotenbergClient("http://localhost:3000") as client:
async with client.chromium.html_to_pdf() as route:
response = await route.index(Path("my-index.html")).run()
response.to_file(Path("my-index.pdf"))from gotenberg_client import GotenbergClient
from pathlib import Path
with GotenbergClient("http://localhost:3000") as client:
with client.chromium.html_to_pdf() as route:
response = (
route.index(Path("my-index.html"))
.resource("image.png")
.resource("style.css")
.run()
)
response.to_file(Path("my-index.pdf"))from gotenberg_client import GotenbergClient
from gotenberg_client.options import PageOrientation
with GotenbergClient("http://localhost:3000") as client:
with client.chromium.url_to_pdf() as route:
response = route.url("https://hello.world").orient(PageOrientation.Landscape).run()
response.to_file(Path("my-world.pdf"))from gotenberg_client import GotenbergClient
from gotenberg_client.options import PdfAFormat
from pathlib import Path
with GotenbergClient("http://localhost:3000") as client:
with client.chromium.html_to_pdf() as route:
response = (
route.index(Path("my-index.html"))
.resources(["image.png", "style.css"])
.pdf_format(PdfAFormat.A2b)
.run()
)
response.to_file(Path("my-index.pdf"))from gotenberg_client import GotenbergClient
from datetime import datetime
with GotenbergClient("http://localhost:3000") as client:
with client.chromium.html_to_pdf() as route:
response = (
route.index("my-index.html")
.metadata(
title="My Document",
author="John Doe",
subject="Example PDF",
keywords=["sample", "document", "test"],
creation_date=datetime.now(),
)
.run()
)
response.to_file(Path("my-index.pdf"))Install the backend you want, then select it explicitly (or rely on auto-detection):
from gotenberg_client import GotenbergClient
# httpx — pip install "gotenberg-client[httpx]"
with GotenbergClient("http://localhost:3000", backend="httpx") as client:
...
# niquests — pip install "gotenberg-client[niquests]"
with GotenbergClient("http://localhost:3000", backend="niquests") as client:
...
# requests (sync-only) — pip install "gotenberg-client[requests]"
with GotenbergClient("http://localhost:3000", backend="requests") as client:
...
# auto — tries httpx first, then niquests (default)
with GotenbergClient("http://localhost:3000") as client:
...from gotenberg_client import GotenbergClient
with GotenbergClient("http://localhost:3000", auth=("user", "secret")) as client:
with client.chromium.html_to_pdf() as route:
response = route.index(Path("my-index.html")).run()
response.to_file(Path("my-index.pdf"))All routes follow the same pattern:
- Add the file(s) you want to process
- Configure options the route supports
- Call
.run()and receive your result
Responses are either a SingleFileResponse or ZipFileResponse, each providing:
to_file(path)-- write the result to diskextract_to(directory)-- extract a ZIP result into a directory (ZipFileResponse only)- Access to
headers,status_code, andcontentfrom the underlying response
Both the client and routes should be used as context managers for proper cleanup.
If that isn't possible, call .close() explicitly:
from gotenberg_client import GotenbergClient
from pathlib import Path
client = GotenbergClient("http://localhost:3000")
try:
route = client.merge.merge()
try:
response = route.merge([Path("myfile.pdf"), Path("otherfile.pdf")]).run()
response.to_file(Path("merged.pdf"))
finally:
route.close()
finally:
client.close()For the full API reference and more examples, see the documentation.
gotenberg-client is distributed under the terms of the MPL 2.0 license.