HTML to PDF API

HTML to PDF API, die genau das rendert, was Ihr Browser zeigt

Schicken Sie HTML und CSS und bekommen Sie ein druckfertiges PDF zurück: Median-Renderzeit 216 ms1. Kein Headless Chrome, das Sie betreiben, patchen oder skalieren müssen.

  • 50 kostenlose Renderings/Monat
  • Ohne Kreditkarte
  • Chromium 153

Was ist eine HTML-zu-PDF-API?

Eine HTML-zu-PDF-API ist ein Webdienst, der HTML und CSS in eine PDF-Datei umwandelt. Sie schicken Ihr Markup in einer HTTP-Anfrage; der Dienst lädt es in einem Headless-Browser, wendet Druckstile, Seitengröße, Ränder, Kopf- und Fußzeilen an und liefert das fertige PDF zurück — Sie müssen also nie selbst einen Browser betreiben oder skalieren.

Dynamic Document API macht genau das mit einem Endpunkt, POST /v1/pdf/from-html. Die Fakten auf einen Blick:

HTML to PDF API: die wichtigsten Fakten
EndpunktPOST https://api.dynamicdocumentapi.com/v1/pdf/from-html
EingabeHTML plus optionaler <head>-Inhalt (CSS, Schriften, Skripte); optional JSON-data für {{ variables }}
AusgabePDF als signierte URL (Standard), als Binärdaten oder base64
Rendering-EngineEngine 2026.4 auf Chromium (Chrome 153.0.8010.47), JavaScript standardmäßig aktiv
RenderzeitMedian 216 ms, p95 516 ms, p99 667 ms (Warteschlange + Verarbeitung, ohne Netzwerk)1
Seitengrößen13 benannte Größen (A0–A6, B4, B5, Letter, Legal, Tabloid, Ledger) oder jede eigene Größe von 0,1 bis 200 Zoll
AuslieferungStandardmäßig synchron; asynchron mit Webhooks für lange Aufträge
DatenresidenzNutzdaten und Dateien bleiben in der EU
Client-BibliothekenReines REST und JSON: jeder HTTP-Client funktioniert. Beispiele unten für cURL, Node.js, Python und PHP
PreisFree: 50 Renderings/Monat. Bezahlt ab 15 €/Monat (jährlich abgerechnet) für 3.000 Renderings, automatisches Nachladen ab 6 € je 1.000
Stand

1. Gemessen über 1.664 erfolgreiche Renderings mit Engine 2026.4. Die Renderzeit ist total_ms: Zeit in der Warteschlange plus Verarbeitung im Worker, ohne API-Overhead und Netzwerkübertragung. p75 378 ms, p90 478 ms, Maximum 2.261 ms.

HTML mit einer API-Anfrage in PDF umwandeln

Jede Anfrage enthält Ihr HTML, optionalen <head>-Inhalt und ein pdf-Objekt mit den Druckeinstellungen. Das Beispiel unten rendert eine US-Letter-Seite mit 20 mm Rand oben und unten und einer Fußzeile mit Seitenzahl. Die Varianten für cURL und Python verlangen die Datei selbst ("delivery": "binary"); die für Node.js und PHP nutzen den Standard und bekommen JSON mit einer signierten Download-URL zurück.

curl https://api.dynamicdocumentapi.com/v1/pdf/from-html \
  -H "Authorization: Bearer $DYNAMIC_DOCUMENT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<h1>Hello from HTML</h1><p>Rendered by Chromium.</p>",
    "head": "<style>body{font-family:system-ui} h1{color:#4751e9}</style>",
    "pdf": {
      "paper":  { "size": "Letter" },
      "margin": { "top": "20mm", "bottom": "20mm" },
      "footer": { "enabled": true, "center": "Page {{page}} of {{pages}}" }
    },
    "delivery": "binary"
  }' \
  --output hello.pdf

# hello.pdf is written to the current directory
// Node.js 18+ (built-in fetch)
const res = await fetch("https://api.dynamicdocumentapi.com/v1/pdf/from-html", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.DYNAMIC_DOCUMENT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    html: "<h1>Hello from HTML</h1><p>Rendered by Chromium.</p>",
    head: "<style>body{font-family:system-ui} h1{color:#4751e9}</style>",
    pdf: {
      paper:  { size: "Letter" },
      margin: { top: "20mm", bottom: "20mm" },
      footer: { enabled: true, center: "Page {{page}} of {{pages}}" },
    },
  }),
});

const render = await res.json();
console.log(render.files[0].url);
// signed URL, valid for 1 hour by default
import os
import requests

res = requests.post(
    "https://api.dynamicdocumentapi.com/v1/pdf/from-html",
    headers={"Authorization": f"Bearer {os.environ['DYNAMIC_DOCUMENT_API_KEY']}"},
    json={
        "html": "<h1>Hello from HTML</h1><p>Rendered by Chromium.</p>",
        "head": "<style>body{font-family:system-ui} h1{color:#4751e9}</style>",
        "pdf": {
            "paper":  {"size": "Letter"},
            "margin": {"top": "20mm", "bottom": "20mm"},
            "footer": {"enabled": True, "center": "Page {{page}} of {{pages}}"},
        },
        "delivery": "binary",
    },
    timeout=60,
)
res.raise_for_status()

with open("hello.pdf", "wb") as f:
    f.write(res.content)
<?php
$payload = [
    'html' => '<h1>Hello from HTML</h1><p>Rendered by Chromium.</p>',
    'head' => '<style>body{font-family:system-ui} h1{color:#4751e9}</style>',
    'pdf'  => [
        'paper'  => ['size' => 'Letter'],
        'margin' => ['top' => '20mm', 'bottom' => '20mm'],
        'footer' => ['enabled' => true, 'center' => 'Page {{page}} of {{pages}}'],
    ],
];

$ch = curl_init('https://api.dynamicdocumentapi.com/v1/pdf/from-html');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . getenv('DYNAMIC_DOCUMENT_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode($payload),
]);

$render = json_decode(curl_exec($ch), true);
echo $render['files'][0]['url'];

Ohne "delivery": "binary" liefert eine erfolgreiche Anfrage 200 OK und ein Render-Objekt. Gekürzt:

{
  "id": "rnd_01J9ZM1X3F7R8K2C4V6B8N0P2Q",
  "status": "succeeded",
  "engine": "2026.4",
  "files": [{
    "format": "pdf",
    "pages": 1,
    "bytes": 18342,
    "url": "https://files.dynamicdocumentapi.com/f/…",
    "url_expires_at": "2026-09-22T15:06:34Z"
  }],
  "timings": { "total_ms": 214 }
}

Anfrageparameter

Die meistgenutzten Felder. Die vollständige Referenz mit jedem Enum-Wert und jedem Limit steht in der API-Dokumentation.

Parameter von POST /v1/pdf/from-html
FeldWas es tut
htmlPflichtfeld. Das zu rendernde Markup. Ist data gesetzt, werden zuerst die {{ variables }} befüllt.
headInhalt von <head>: <style>, <link>, <script>, <meta>.
dataJSON-Werte für die Variablen in html und head.
pdf.paperEine benannte size (A4, Letter, …) oder width und height mit Einheit, z. B. "80mm".
pdf.orientationportrait oder landscape.
pdf.margintop, right, bottom, left als CSS-Längen ("20mm", "0.5in").
pdf.scaleZoomfaktor von 0,1 bis 2,0.
pdf.print_backgroundHintergrundfarben und -bilder drucken. Standard true.
pdf.emulate_mediaCSS-Medium print (Standard) oder screen.
pdf.header, pdf.footerMitlaufende Kopf- und Fußzeile, als HTML oder als left/center/right-Text mit {{page}} und {{pages}}.
pdf.waitWann erfasst wird: until = load, networkidle, selector, ready_flag oder delay; timeout_ms bis 300.000.
pdf.locale, pdf.timezoneSprache und Zeitzone, in der die Seite läuft, z. B. de-DE und Europe/Berlin.
deliveryurl (Standard, signierter Link), binary oder base64.
mode, webhooksync (Standard) oder async, mit einem Webhook, der auslöst, sobald die Datei fertig ist.

Was die Rendering-Engine kann

Die Engine ist Chromium, dieselbe Codebasis wie Chrome auf dem Desktop, festgelegt auf eine getestete Version (Engine 2026.4 läuft auf Chrome 153). Wenn Ihre Seite in Chrome richtig druckt, rendert sie hier genauso. HTML to PDF ist ein Eingang unserer vollständigen PDF-Generierungs-API; die Druckfunktionen unten teilen sich alle Eingänge.

Modernes CSS: Flexbox, Grid, @page und Print-Media-Queries

Flexbox, Grid, Custom Properties und @media print funktionieren wie im aktuellen Chrome. Das Druckmedium wird standardmäßig emuliert. Mit prefer_css_page_size entscheiden @page-Regeln über die Seitengröße.

@page { size: Letter; margin: 18mm 16mm; }
@media print { .no-print { display: none; } }

Kopf- und Fußzeilen und automatische Seitenzahlen

Nutzen Sie die einfachen Felder left/center/right mit den Platzhaltern {{page}}, {{pages}} und {{date}} oder eine vollständige HTML-Kopfzeile mit eigenen Stilen. Elemente mit den Klassen page, pages und title werden auf jeder Seite befüllt.

"footer": { "enabled": true,
  "right": "Page {{page}} of {{pages}}" }

Eigene Schriften und Webfonts

Laden Sie Schriften wie auf einer Website: ein <link> auf ein Font-Stylesheet oder eine @font-face-Regel mit entfernter URL, abgerufen über unseren Proxy. Schriften aus dem eingebauten Katalog der Engine funktionieren ohne Einrichtung.

Vor der Erfassung wartet die Engine auf das load-Ereignis der Seite, auf fertig geladene Schriften, dekodierte Bilder und zwei gerenderte Frames. Damit ist der klassische Fehler „PDF in der Ersatzschrift gedruckt" erledigt.

JavaScript, Diagramme und dynamische Inhalte

JavaScript läuft standardmäßig, also können Chart.js, D3 oder eine clientseitig gerenderte App zeichnen, bevor das PDF entsteht. Sagen Sie der Engine, was „fertig" heißt: networkidle (500 ms ohne Anfragen), ein CSS-selector, ein ready_flag, das Ihr Code setzt, oder eine feste delay.

"wait": { "until": "selector",
  "selector": "#chart[data-ready]",
  "timeout_ms": 15000, "strict": true }

Mit strict: true lässt eine Zeitüberschreitung das Rendering scheitern; mit false bekommen Sie das PDF plus eine Warnung wait_timeout.

Seitenumbrüche und lange Tabellen

Steuern Sie Umbrüche mit Standard-CSS: break-before: page beginnt eine neue Seite, break-inside: avoid hält eine Zeile oder Karte zusammen. Das <thead> einer Tabelle wiederholt sich oben auf jeder Seite, über die sie läuft — so bleibt eine Rechnung mit 40 Posten auch auf Seite drei lesbar.

.section   { break-before: page; }
tr, .card  { break-inside: avoid; }

Jede Seitengröße

Wählen Sie eine von 13 benannten Größen (A0–A6, B4, B5, Letter, Legal, Tabloid, Ledger) oder setzen Sie width und height frei von 0,1 bis 200 Zoll. single_page erzeugt eine durchgehende Seite, so hoch wie der Inhalt — so werden Thermobelege mit 58 mm und 80 mm gedruckt. page_ranges liefert nur die Seiten, die Sie brauchen, zum Beispiel "1-3,5".

Passwortschutz, Lesezeichen und Metadaten

protect setzt ein Benutzer- und ein Eigentümerpasswort plus sieben einzelne Berechtigungen, etwa Drucken oder Kopieren. outline erzeugt Lesezeichen aus Ihren h1–h6, tagged fügt die Struktur hinzu, die Screenreader nutzen, und metadata setzt Titel, Autor, Betreff, Schlüsselwörter und Sprache.

Sprache, Zeitzone und Farben

Daten und Zahlen, die das JavaScript Ihrer Seite formatiert, stimmen, wenn Sie locale und timezone setzen: Eine US-Kundin sieht 9/22/2026, ein deutscher Kunde 22.9.2026. Hintergründe und Markenfarben werden standardmäßig gedruckt, ohne Häkchen bei „Hintergrundgrafiken".

HTML to PDF API vs. selbst betriebenes Puppeteer vs. wkhtmltopdf

Die meisten Teams, die einen HTML-zu-PDF-Dienst suchen, haben schon eine von zwei Alternativen im Kopf: Headless Chrome selbst mit Puppeteer oder Playwright betreiben oder das Programm wkhtmltopdf. So schneiden sie im Vergleich ab. Zahlen nennen wir nur, wo wir messen können; beim Selbstbetrieb lautet die ehrliche Antwort „kommt auf Ihr Setup an".

HTML to PDF API im Vergleich mit selbst betriebenem Puppeteer und wkhtmltopdf
Kriterium Dynamic Document API Selbst betriebenes Puppeteer / Playwright wkhtmltopdf
EinrichtungAPI-Schlüssel und eine HTTPS-AnfrageChromium und Schriften installieren, einen Render-Dienst mit Warteschlange bauenProgramm und Systemschriften installieren
EngineChromium (Chrome 153), von uns mit jeder Engine-Version aktualisiertChromium, in der Version, die Sie festlegen und patchenVeraltetes Qt WebKit; Repository seit 2023 archiviert
CSS Grid und FlexboxJaJaKein Grid; Flexbox nur in der alten Syntax -webkit-box
JavaScriptJa, mit eingebauten WartebedingungenJa, die Wartelogik schreiben Sie selbstAlte JS-Engine; wartet über eine feste Verzögerung oder window.status
WartungKeine auf Ihrer SeiteBrowser-Updates, Sicherheitspatches, Speicherlecks, hängende ProzesseKeine Sicherheitskorrekturen mehr vom Projekt
SkalierungParallelität je Tarif; asynchrone Aufträge und WebhooksIhr Browser-Pool, Ihre Warteschlange und Ihr AutoscalingIhre Prozesse und Server
Renderzeitp50 216 ms, p95 516 ms (Warteschlange + Verarbeitung)Hängt von Kaltstarts und Poolgröße abHängt von Ihrer Hardware ab
Kosten bei 10.000 PDFs/Monat47 €/Monat (Growth, 15.000 Renderings, jährlich abgerechnet) oder 59 € monatlichServer plus EntwicklungszeitServer plus Entwicklungszeit
Wählen Sie es, wennSie korrekte PDFs wollen, ohne Browser zu betreibenDaten Ihr Netzwerk nie verlassen dürfen oder Sie schon eine Browser-Flotte betreibenSie ein Altsystem pflegen, das Sie noch nicht ändern können

Wann eine gehostete API nicht die richtige Wahl ist

Wenn Ihre Dokumente in einem abgeschotteten Netz entstehen müssen oder eine Richtlinie verbietet, ihren Inhalt an Dritte zu senden, betreiben Sie Chromium selbst. Dasselbe gilt, wenn Sie schon eine gut eingestellte Browser-Flotte mit sehr hohem Volumen betreiben: Dann spart Ihnen die API vor allem Betriebsarbeit, kein Geld. Für alle anderen nimmt der gehostete Weg genau den Teil der PDF-Erzeugung ab, der um zwei Uhr nachts kaputtgeht: den Browser.

Umstieg von wkhtmltopdf

Weil wkhtmltopdf auf einem alten WebKit beruht, enthalten dafür geschriebene Layouts oft Umwege wie -webkit-box oder Float-Raster. Sie funktionieren in Chromium weiter — Sie können also zuerst den Renderer wechseln und das CSS später modernisieren. Die Optionen für Seitengröße und Ränder entsprechen pdf.paper und pdf.margin, die HTML-Optionen für Kopf- und Fußzeile pdf.header und pdf.footer.

Rohes HTML oder wiederverwendbare Vorlagen?

Rohes HTML zu senden ist richtig, wenn Ihre Anwendung das Markup schon erzeugt, zum Beispiel mit React-Server-Rendering, Django-, Rails- oder Laravel-Views. Das Layout bleibt in Ihrem Repository, und die API druckt es nur.

Wird dasselbe Layout tausendfach mit anderen Daten gefüllt, speichern Sie es einmal und senden nur noch JSON. Wiederverwendbare PDF-Vorlagen nutzen Jinja-Syntax, formatieren Datum und Währung je Sprache über ICU, rendern QR-Codes und Barcodes und behalten jede veröffentlichte Version — so können Sie eine Version festlegen und eine Layoutänderung zurücknehmen. Ein typischer Fall: für jede Bestellung eine HTML-Rechnung in ein PDF umwandeln.

Sie schreiben lange Texte wie Berichte, Handbücher oder LLM-Ausgaben? Dann können Sie auch mit Markdown statt HTML beginnen und eines von vier Druck-Themes wählen.

Große Dokumente: synchron, asynchron und Webhooks

Standardmäßig ist eine Anfrage synchron: Die Verbindung bleibt offen, bis das PDF fertig ist, und die meisten Renderings sind weit unter einer Sekunde fertig. Dauert ein Rendering länger als das Sync-Limit Ihres Tarifs, scheitert die API nicht; sie antwortet mit 202 Accepted und der Render-ID und arbeitet weiter. Das Ergebnis holen Sie später über GET /v1/renders/{id}.

Für große Berichte oder Stapelaufträge senden Sie "mode": "async" mit einem Webhook. Die API antwortet sofort, und Ihr Endpunkt bekommt render.succeeded oder render.failed, sobald der Auftrag erledigt ist. Mit einem Idempotency-Key-Header können Sie eine Anfrage gefahrlos wiederholen: Derselbe Schlüssel liefert 24 Stunden lang dasselbe Rendering, statt ein zweites zu erzeugen.

Synchronous and asynchronous HTML to PDF requests Synchronous: your app sends POST /v1/pdf/from-html and receives 200 OK with the PDF. Asynchronous: your app sends the request with mode async, receives 202 Accepted with a render ID, and later Dynamic Document API calls your webhook with render.succeeded and the file URL. SYNCHRONOUS (DEFAULT) Your app waits for the reply Dynamic Document API renders in Chromium POST /v1/pdf/from-html 200 OK · PDF or signed URL ASYNCHRONOUS (LARGE JOBS) Your app continues working Dynamic Document API queues and renders POST … "mode": "async" 202 Accepted · render ID webhook: render.succeeded + URL
Synchrone Anfragen liefern das PDF direkt. Asynchrone Anfragen antworten sofort und benachrichtigen Ihren Webhook, sobald die Datei fertig ist.

Sicherheit und Umgang mit Daten

  • Regionale Verarbeitung. Render-Nutzdaten und erzeugte Dateien bleiben in der Region des API-Hosts, den Sie aufrufen.
  • Signierte, ablaufende Links. Download-URLs sind signiert und laufen standardmäßig nach einer Stunde ab. Setzen Sie expires_in auf 60 Sekunden bis 7 Tage, oder verzichten Sie auf das Hosting und nehmen Sie die Datei als binary.
  • Aufbewahrung, die Sie bestimmen. Legen Sie pro Anfrage mit retention_days fest, wie lange Dateien bleiben — bis zum Maximum Ihres Tarifs —, und löschen Sie sie jederzeit mit DELETE /v1/renders/{id}/files.
  • Ihr eigener Speicher. In Enterprise-Tarifen können Dateien direkt in Ihren eigenen S3-kompatiblen Bucket gehen.
  • Sicheres Laden von Ressourcen. Bilder, Schriften und Stylesheets, auf die Ihr HTML verweist, werden über einen Proxy geladen, der private und interne Netzwerkadressen sperrt.
  • Test- und Live-Schlüssel. Getrennte API-Schlüssel für Entwicklung und Produktion und ein AV-Vertrag in jedem Bezahltarif.

Preise der HTML to PDF API

Starten Sie mit 50 kostenlosen Renderings im Monat, ohne Kreditkarte. Bezahltarife sind feste Monatspreise mit festem Volumen und automatischem Nachladen — die Kosten pro Dokument sind leicht zu berechnen, und eine Pipeline hält am Monatsende nie an.

Free

€0

50 Renderings pro Monat, volle REST-API. Zum Testen und für Prototypen.

Starter

€15 / Monat

3.000 Renderings pro Monat, jährlich abgerechnet (19 € bei monatlicher Abrechnung). Etwa 0,005 € pro Rendering.

Höhere Volumen, Teamfunktionen und Ihr eigener Speicher gibt es in den größeren Tarifen. Alle Stufen finden Sie in den vollständigen Preisen der HTML to PDF API.

FAQ

HTML to PDF API: häufige Fragen

Unterstützt die API CSS Grid und Flexbox?

Ja. Die Engine ist Chromium (Chrome 153), also verhalten sich Flexbox, Grid, Custom Properties, @page-Regeln und Print-Media-Queries wie im aktuellen Chrome. Eine schnelle Vorschau eines Layouts liefert die Druckvorschau von Chrome selbst: Sie nutzt dieselbe Layout-Engine.

Wie füge ich Seitenzahlen und eine mitlaufende Fußzeile hinzu?

Setzen Sie pdf.footer auf {"enabled": true, "center": "Page {{page}} of {{pages}}"} oder übergeben Sie eigenes Fußzeilen-HTML mit Elementen, die die Klassen page und pages tragen. Reservieren Sie den Platz dafür mit margin.bottom. Kopfzeilen funktionieren genauso über pdf.header.

Führt die API JavaScript aus, bevor das PDF entsteht?

Ja, JavaScript ist standardmäßig aktiv. Mit pdf.wait.until legen Sie fest, wann die Seite fertig ist: networkidle, ein CSS-selector, ein ready_flag, das Ihr Skript setzt, oder eine feste delay. Setzen Sie pdf.javascript auf false, um Skripte abzuschalten.

Wie lange darf ein Rendering dauern?

Die meisten Renderings sind schnell: Der Median liegt bei 216 ms, p99 bei 667 ms, gemessen als Warteschlange plus Verarbeitung ohne Netzwerk. Wartet eine Seite auf Inhalte, beträgt die Wartezeit standardmäßig 30 Sekunden und lässt sich auf 300 Sekunden erhöhen. Dauert eine synchrone Anfrage länger als das Sync-Limit Ihres Tarifs, antwortet die API mit 202 und stellt das Rendering asynchron fertig.

Kann ich eine URL statt rohem HTML umwandeln?

Ja. Mit POST /v1/pdf/from-url können Sie eine Live-URL in ein PDF umwandeln, auch Seiten hinter einem Login über Cookies, Header oder Basic Auth. Zugangsdaten werden nur an dieselbe Domain gesendet. In eine URL-Erfassung lässt sich kein eigenes CSS einfügen; wenn Sie die Seite umgestalten müssen, senden Sie stattdessen ihr HTML.

Worin unterscheidet sich das von wkhtmltopdf?

wkhtmltopdf rendert mit einer veralteten Qt-WebKit-Engine, und sein Repository wurde 2023 archiviert — es bekommt also keine Korrekturen mehr. Es unterstützt kein CSS Grid und kommt mit modernem JavaScript schlecht zurecht. Dynamic Document API rendert mit aktuellem Chromium, und Sie installieren oder patchen nichts.

Gibt es einen kostenlosen Tarif der HTML to PDF API?

Ja. Der Free-Tarif umfasst 50 Renderings pro Monat mit der vollen REST-API und ohne Kreditkarte. Bezahltarife beginnen bei 15 € im Monat für 3.000 Renderings bei jährlicher Abrechnung oder 19 € bei monatlicher.

Wandeln Sie Ihr erstes HTML kostenlos in ein PDF um

50 Renderings im Monat im Free-Tarif, ohne Kreditkarte, automatisches Nachladen in Bezahltarifen, kein Browser zu warten.

Kostenlos starten