Skip to main content

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 / AsyncClient

    • render(html=..., url=..., type="pdf", options=..., tag=..., idempotency_key=...) → bytes
    • render_job(...) → Job — same as render but returns the Job object with metadata
    • render_async(webhook_url=..., ...) → Job — queue a background render
    • get_job(job_id) → Job — poll the state of a job
    • download(url) → bytes — fetch a signed download URL
    • close() / aclose() — release the underlying HTTP pool
  • Job dataclass: 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

html2dochub-0.1.0.tar.gz (13.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

html2dochub-0.1.0-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

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

Hashes for html2dochub-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4cd6fd3c8fc587fdf67aafe7eca77edb1048cd9144a09470f3acf3ffaed89acd
MD5 a724a3b996872be8777075faa16d7d95
BLAKE2b-256 9b689b4918feba768488e44beb7587b12538ecb7ea9668e5a718385fbf821213

See more details on using hashes here.

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

Hashes for html2dochub-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b7c450204418f8f48adc1bf17ec454bee2a6f2f1791c8ab5f0e4d1a7228a6789
MD5 2d25757e79aa3701c797a5458dec6135
BLAKE2b-256 9a1bb7a862d6064d9d86d30dbadc7a93069abc5566d50afdfbf790baa7e4f1b1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page