🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)
🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)

🔧 Programmierung 🕛 kürzlich 7 Min Lesezeit
0

WeasyPrint Alternative: HTML to PDF in Python (When You Need JavaScript)

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

You build a report template in HTML. It looks right in the browser: the layout holds, the webfont loads, the Chart.js graph draws. Then you run it through WeasyPrint and the PDF comes back with a blank space where the chart should be. No exception, no warning, just a hole in the page.



That is not a bug you can fix. WeasyPrint does not execute JavaScript, so anything drawn or injected client-side simply does not exist as far as its renderer is concerned. This post walks through where the Python PDF stack falls short and the API route around it; it originally appeared on the HTML to Image blog as gives you the first option without the operations. You POST your HTML with format: "pdf" and get back a URL to a finished document, rendered by a real browser engine:




CODE
import os

import requests

API_KEY = os.getenv('HTML2IMG_API_KEY')


def html_to_pdf(html: str, css: str = '') -> str:
"""Render HTML to a PDF and return the hosted URL."""
response = requests.post(
'https://app.html2img.com/api/html',
json={'html': html, 'css': css, 'format': 'pdf'},
headers={'X-API-Key': API_KEY},
timeout=60,
)
response.raise_for_status()
result = response.json()
if not result.get('success'):
raise RuntimeError(result.get('message', 'Render failed'))
return result['url']






The response is small enough to read in full:




CODE
{
"success": true,
"id": "9d5f9b52-6b32-4a1c-a9c5-1f0b2a9e4c11",
"credits_remaining": 499,
"url": "https://i.html2img.com/image-1784019129398-416501.pdf"
}






The url points at a real vector PDF served as application/pdf. Text stays selectable and searchable, fonts are embedded (webfonts included) and background colours and gradients come through. Content lays out on A4 portrait pages and paginates automatically, so a three page report is no more work than a one page invoice.



One detail that saves you a refactor: the PDF renders with your normal screen CSS. You do not need @media print rules or a parallel print stylesheet. The markup that looks right in the browser is the markup that ships.






A worked example: an invoice from a Jinja2 template



Invoices are the classic job. Here is the whole flow, template to hosted PDF:




CODE
from jinja2 import Template

INVOICE = Template("""
<div class=
"invoice">
<h1>Invoice #{{ number }}</h1>
<p class=
"meta">Northgate Coffee Ltd &middot; Due {{ due }}</p>
<table>
<tr><th>Item</th><th>Qty</th><th>Price</th></tr>
{% for line in lines %}
<tr><td>{{ line.item }}</td><td>{{ line.qty }}</td><td>&pound;{{ line.price }}</td></tr>
{% endfor %}
</table>
<p class=
"total">Total due: &pound;{{ total }}</p>
</div>
""")

CSS = """
body { font-family: Helvetica, Arial, sans-serif; color: #0e1521; }
.invoice { padding: 24px; }
table { width: 100%; border-collapse: collapse; margin-top: 16px; }
th, td { text-align: left; padding: 8px 4px; border-bottom: 1px solid #e2e6ec; }
.total { font-weight: 700; margin-top: 16px; }
"""

html = INVOICE.render(
number=1042,
due='20 August 2026',
lines=[
{'item': 'Espresso machine service', 'qty': 1, 'price': '180.00'},
{'item': 'Filter papers (case)', 'qty': 4, 'price': '12.50'},
],
total='230.00',
)

print(html_to_pdf(html, CSS))






In Flask you would build html with render_template, in Django with render_to_string. The API does not care which framework produced the markup.






Your charts render, because JavaScript runs



Back to that blank hole from the opening. JavaScript executes in the renderer, so Chart.js draws exactly as it does in the browser. Disable the entry animation so the canvas paints immediately, and give the page a short ms_delay so the script settles before capture:




CODE
chart_html = """
<canvas id=
"sales" width="640" height="280"></canvas>
<script src=
"https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
new Chart(document.getElementById(
'sales'), {
type:
'bar',
data: {
labels: [
'Mar', 'Apr', 'May', 'Jun'],
datasets: [{ label:
'Orders', data: [412, 468, 530, 597] }]
},
options: { animation: false }
});
</script>
"""

response = requests.post(
'https://app.html2img.com/api/html',
json={'html': chart_html, 'format': 'pdf', 'ms_delay': 500},
headers={'X-API-Key': API_KEY},
)






Turning a chart you already render in the browser into a document is one parameter.






What changes in your deployment



Your PDF dependency list becomes requests. No Pango, no HarfBuzz, no Chromium layer, no font packages. The same code runs identically on Alpine, in a distroless container and on Lambda, because the rendering happens on the API's browsers rather than your box. For async stacks there is an httpx version in .



What are you using for PDF generation in Python at the moment? Share your setup in the comments below.

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
3 Quellen
GPT-6 Astra Release Today? OpenAI’s Next Major AI Model Is Almost Here
1 Quelle
Apple accuses OpenAI of destroying evidence as trade-secrets fight intensifies
1 Quelle
Major AI platforms go down in unprecedented simultaneous outage
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten WeasyPrint Alternative: HTML to PDF in Python (When You Need JavaScript)

Thematisch verwandte Begriffe: WeasyPrint, Alternative, HTML, Python · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...