Official Python client for the HTML2DocHub HTML-to-PDF API.
Project description
html2dochub
Official Python client for the HTML2DocHub HTML-to-PDF API.
pip install html2dochub
Pay-per-use HTML → PDF rendering on real Chromium. No subscriptions, no binary dependencies on your server, no Docker Chromium layer to maintain.
Quick start
from html2dochub import Client
client = Client(api_key="sk_live_YOUR_KEY")
pdf_bytes = client.render(
html="<h1>Hello from Python</h1>",
options={"format": "A4", "margin": "18mm"},
)
with open("out.pdf", "wb") as f:
f.write(pdf_bytes)
Get your API key at html2dochub.com/dashboard/api-keys. New accounts get free starter credit — enough to render around 100 pages.
Async (FastAPI, asyncio)
from html2dochub import AsyncClient
async with AsyncClient(api_key="sk_live_YOUR_KEY") as client:
pdf = await client.render(html="<h1>Hello</h1>", options={"format": "A4"})
Render from a URL
pdf = client.render(url="https://example.com/invoice/42")
Async mode with webhook (for long reports)
Large renders (50+ pages) should run in the background so your request
doesn't block. Call render_async with a webhook_url — we POST the
completed job back to it.
job = client.render_async(
html=big_html,
webhook_url="https://yours.com/webhooks/pdf-ready",
tag="q1-report",
idempotency_key="report-42-v3",
)
# job.status == "pending"
In your webhook handler:
@app.post("/webhooks/pdf-ready")
def pdf_ready(payload: dict):
if payload["status"] == "completed":
pdf_bytes = client.download(payload["download_url"])
store(payload["id"], pdf_bytes)
Error handling
Every API error surfaces as a subclass of HTML2DocHubError, so a single
except catches them all. Specific classes let you react differently:
from html2dochub import (
Client,
AuthenticationError,
InsufficientFundsError,
RateLimitError,
ValidationError,
APIError,
)
try:
pdf = client.render(html=html)
except InsufficientFundsError:
# wallet is empty — prompt the user to top up
...
except RateLimitError as e:
# hit the per-API-key throttle
time.sleep(e.retry_after or 2)
except ValidationError as e:
# the request body was malformed (exactly one of html/url required, etc.)
...
except AuthenticationError:
# the API key is wrong or revoked
...
except APIError as e:
# catch-all for anything else (5xx after retries, unknown status, etc.)
...
Automatic retries
The client retries 429 and 5xx responses with exponential backoff
(0.5s, 1s, 2s, up to 30s). Retries are tunable:
client = Client(api_key="...", max_retries=5, timeout=120)
Retry-After headers on 429 responses are honoured.
Idempotency
Pass idempotency_key on any render to make the request safe to retry
without double-billing. Same key within the retention window returns the
original response instead of rendering again.
client.render(
html=invoice_html,
idempotency_key=f"invoice-{invoice.id}-v{invoice.version}",
)
Useful inside Celery tasks, BullMQ workers, or any queue with at-least-once delivery semantics.
Configuration
Client(
api_key="sk_live_...",
base_url="https://api.html2dochub.com", # override for self-hosted
timeout=60, # seconds, applied to each HTTP call
max_retries=3, # for 429 and 5xx responses
user_agent="my-app/1.2", # prepended to the default UA
)
Type safety
html2dochub ships with inline type hints and a py.typed marker. mypy
in strict mode is clean on the public API.
API reference
-
Client/AsyncClientrender(html=..., url=..., type="pdf", options=..., tag=..., idempotency_key=...) → bytesrender_job(...) → Job— same as render but returns the Job object with metadatarender_async(webhook_url=..., ...) → Job— queue a background renderget_job(job_id) → Job— poll the state of a jobdownload(url) → bytes— fetch a signed download URLclose()/aclose()— release the underlying HTTP pool
-
Jobdataclass:id,status,type,mode,output_pages,final_cost,download_url,created_at,started_at,completed_at,raw(preserves unknown fields).
Full API documentation: html2dochub.com/docs.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file html2dochub-0.1.0.tar.gz.
File metadata
- Download URL: html2dochub-0.1.0.tar.gz
- Upload date:
- Size: 13.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4cd6fd3c8fc587fdf67aafe7eca77edb1048cd9144a09470f3acf3ffaed89acd
|
|
| MD5 |
a724a3b996872be8777075faa16d7d95
|
|
| BLAKE2b-256 |
9b689b4918feba768488e44beb7587b12538ecb7ea9668e5a718385fbf821213
|
File details
Details for the file html2dochub-0.1.0-py3-none-any.whl.
File metadata
- Download URL: html2dochub-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7c450204418f8f48adc1bf17ec454bee2a6f2f1791c8ab5f0e4d1a7228a6789
|
|
| MD5 |
2d25757e79aa3701c797a5458dec6135
|
|
| BLAKE2b-256 |
9a1bb7a862d6064d9d86d30dbadc7a93069abc5566d50afdfbf790baa7e4f1b1
|