Python4 min read · June 7, 2026

HTML to PDF in Python: Generate PDFs with requests in 2 Minutes

Generate PDFs from HTML in Python using the requests library and a REST API. No WeasyPrint, no wkhtmltopdf, no browser — just a simple HTTP call.

Python PDF generation usually means WeasyPrint (heavy GTK dependencies), ReportLab (programmatic layout, not HTML), or shelling out to wkhtmltopdf. All three require significant setup and don't behave the same across environments.

The HTML to PDF API is a REST endpoint you hit with requests. That's it — no pip packages beyond what you already have, no system dependencies.

Install requests (if not already)

Terminalbash
pip install requests

Generate a PDF from HTML

generate_pdf.pypython
import os
import requests

API_KEY = os.environ["HTMLTOPDF_API_KEY"]
API_URL = "https://platform.htmltopdfapi.co/api/v1/pdf/generate"

html = """
<!DOCTYPE html>
<html lang="en">
<body style="font-family:sans-serif;padding:32px">
  <h1>Hello from Python</h1>
  <p>Generated via HTML to PDF API.</p>
</body>
</html>
"""

response = requests.post(
    API_URL,
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
        "Accept": "application/pdf",
    },
    json={
        "html": html,
        "paper_size": "a4",
        "orientation": "portrait",
    },
)

response.raise_for_status()

with open("output.pdf", "wb") as f:
    f.write(response.content)

print("PDF saved to output.pdf")

Convert a URL to PDF

To convert a live URL instead of raw HTML, swap the html key for url:

url_to_pdf.pypython
response = requests.post(
    API_URL,
    headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", "Accept": "application/pdf"},
    json={"url": "https://example.com", "paper_size": "a4"},
)

Use in Django or Flask

In a Django or Flask view, render your template to a string, call the API, and return the bytes as a PDF response:

Django view snippetpython
from django.http import HttpResponse
from django.template.loader import render_to_string

def invoice_pdf(request, pk):
    invoice = get_object_or_404(Invoice, pk=pk)
    html    = render_to_string('invoices/pdf.html', {'invoice': invoice})

    res = requests.post(API_URL, headers=headers, json={'html': html, 'paper_size': 'a4'})
    res.raise_for_status()

    return HttpResponse(res.content, content_type='application/pdf',
                        headers={'Content-Disposition': f'inline; filename="invoice-{pk}.pdf"'})