DEV Community

Custodia-Admin
Custodia-Admin

Posted on Edited on Originally published at pagebolt.dev

How to generate a PDF from HTML in Python

How to Generate a PDF from HTML in Python

The usual Python options for HTML-to-PDF: wkhtmltopdf (requires a system binary), WeasyPrint (CSS support gaps, heavy dependencies), or Puppeteer via subprocess (a browser in your Python app). All of them require you to manage something at the OS level.

An API call requires nothing:

import requests

response = requests.post(
    'https://pagebolt.dev/api/v1/pdf',
    headers={'x-api-key': 'YOUR_API_KEY'},
    json={
        'html': '<h1>Hello</h1><p>This is my PDF.</p>',
        'format': 'A4',
        'printBackground': True
    }
)

with open('output.pdf', 'wb') as f:
    f.write(response.content)
Enter fullscreen mode Exit fullscreen mode

Generate from a URL

If the page is already live, pass a URL instead of HTML:

response = requests.post(
    'https://pagebolt.dev/api/v1/pdf',
    headers={'x-api-key': 'YOUR_API_KEY'},
    json={
        'url': 'https://example.com/report',
        'format': 'A4',
        'printBackground': True,
        'blockBanners': True
    }
)
Enter fullscreen mode Exit fullscreen mode

Invoice generation with Jinja2

A common pattern: render an HTML template, then convert to PDF on the fly:

import requests
from jinja2 import Template

template = Template("""
<html>
<body style="font-family: sans-serif; padding: 40px;">
  <h1>Invoice #{{ invoice_id }}</h1>
  <p>Customer: {{ customer }}</p>
  <p>Amount due: ${{ amount }}</p>
  <p>Due date: {{ due_date }}</p>
</body>
</html>
""")

html = template.render(
    invoice_id=1042,
    customer="Acme Corp",
    amount="299.00",
    due_date="2026-03-01"
)

response = requests.post(
    'https://pagebolt.dev/api/v1/pdf',
    headers={'x-api-key': 'YOUR_API_KEY'},
    json={'html': html, 'format': 'A4', 'printBackground': True}
)

with open(f'invoice-1042.pdf', 'wb') as f:
    f.write(response.content)
Enter fullscreen mode Exit fullscreen mode

In a Django/Flask view

from django.http import HttpResponse
import requests

def invoice_pdf(request, invoice_id):
    html = render_invoice_html(invoice_id)

    resp = requests.post(
        'https://pagebolt.dev/api/v1/pdf',
        headers={'x-api-key': settings.PAGEBOLT_API_KEY},
        json={'html': html, 'format': 'A4', 'printBackground': True}
    )

    return HttpResponse(
        resp.content,
        content_type='application/pdf',
        headers={'Content-Disposition': f'attachment; filename="invoice-{invoice_id}.pdf"'}
    )
Enter fullscreen mode Exit fullscreen mode

Options

{
    'html': '...',          # raw HTML string
    'url': '...',           # OR a live URL
    'format': 'A4',         # A4, Letter, Legal, A3
    'printBackground': True,
    'margin': {
        'top': '20mm', 'bottom': '20mm',
        'left': '15mm', 'right': '15mm'
    },
    'landscape': False,
    'blockBanners': True
}
Enter fullscreen mode Exit fullscreen mode

No system dependencies, no binary installs, no version pinning. Runs anywhere Python runs — Lambda, Cloud Run, a VPS, or your local machine.


Try it free — 100 requests/month, no credit card. → Get started in 2 minutes

Top comments (0)