Back to Blog
Guide February 26, 2026

How to generate a PDF from HTML in Python

Convert HTML to PDF in Python with one requests call. No wkhtmltopdf, no WeasyPrint, no headless browser to configure.

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://api.pagebolt.dev/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://api.pagebolt.dev/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://api.pagebolt.dev/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://api.pagebolt.dev/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

Get Started Free

100 requests/month, no credit card

Screenshots, PDFs, video recording, and browser automation — no headless browser to manage.

Get Your Free API Key →