Skip to main content

Command Palette

Search for a command to run...

How to generate a PDF from HTML in Python

Updated
2 min readView as Markdown

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)

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
    }
)

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)

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"'}
    )

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
}

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. → pagebolt.dev

More from this blog

P

Pagebolt.dev

401 posts