Practical guide

Generate PDF from HTML code: Puppeteer, WeasyPrint, Gotenberg or a hosted API

Last materially reviewed 2026-10-03

Quick answerLoad the HTML in headless Chrome with Puppeteer and call page.pdf(), or run HTML(string=html).write_pdf() in WeasyPrint. Both are free. Use a hosted API only if you cannot run a renderer.

Four ways to turn HTML code into a PDF

To generate a PDF from HTML code, pass the HTML to a rendering engine and ask it for a PDF. The engine is either a headless browser (Puppeteer, or Gotenberg which wraps Chromium), a dedicated HTML-to-PDF library (WeasyPrint) or a hosted API that runs one of these for you.

Ways to generate a PDF from HTML code
RouteLanguageRuns JavaScript in the pageWhat you install
PuppeteerNode.jsYes, it is ChromeAn npm package plus a Chrome download
WeasyPrintPython or command lineNot a browser; choose it for static HTML and CSSA pip package plus the Pango system library
GotenbergAny, over HTTPYes, it uses headless ChromiumA Docker container
Hosted APIAny, over HTTPDepends on the serviceNothing

If the HTML does not exist yet and you really want to fill a layout with data, a template route is the better starting point.

Puppeteer: the documented steps

Prerequisites. Node.js, and room for the Chrome for Testing build that Puppeteer downloads on install, which is roughly 170 to 282 MB depending on the operating system.

  1. Install: npm i puppeteer
  2. Launch the browser: const browser = await puppeteer.launch();
  3. Open a page: const page = await browser.newPage();
  4. Load your HTML string: await page.setContent(html);
  5. Create the PDF: await page.pdf({ path: 'out.pdf', printBackground: true });
  6. Close: await browser.close();

To convert a live URL instead of a string, the Puppeteer guide uses await page.goto(url, { waitUntil: 'networkidle2' }) in place of step 4. By default page.pdf() waits for fonts to load and times out after 30 seconds.

WeasyPrint and Gotenberg: the same job without Node.js

WeasyPrint is the shortest route in Python. Version 70.0 needs Python 3.10 or later and Pango 1.44 or later.

  1. Install: pip install weasyprint
  2. Import: from weasyprint import HTML
  3. Convert a string: HTML(string=html).write_pdf("out.pdf")
  4. Or convert a file: HTML(filename="page.html").write_pdf("out.pdf")

There is also a command line form. The documentation's example is weasyprint https://weasyprint.org /tmp/weasyprint-website.pdf: input first, output second.

Gotenberg gives every language the browser route over HTTP.

  1. Start it: docker run --rm -p "3000:3000" gotenberg/gotenberg:8
  2. Save your HTML as a file named index.html. The name is required.
  3. Convert: curl --request POST http://localhost:3000/forms/chromium/convert/html --form files=@/path/to/index.html -o my.pdf

Hosted APIs: one request, nothing to install

If you cannot run Chrome or Docker, a hosted API accepts the same HTML in a POST request. Three with public documentation:

  • DocRaptor: POST JSON to https://api.docraptor.com/docs with "type": "pdf" and "document_content": "<html>...</html>". Adding "test": true makes a free, watermarked document.
  • PDFShift: POST JSON to https://api.pdfshift.io/v3/convert/pdf with source set to your HTML or a URL, and the key in the X-API-Key header.
  • Api2Pdf: POST {"html": "<h1>Hello World</h1>"} to https://v2.api2pdf.com/chrome/pdf/html with the key in the Authorization header.

Free allowances and entry prices for these are in the HTML to PDF API comparison. For a few hundred documents a month on a server you already run, the free routes above are enough.

Worked example: a two-page report with a header band

The HTML has a dark header band, a summary paragraph and a 60-row table. With Puppeteer, call page.pdf({ path: 'report.pdf', printBackground: true }). The format option defaults to letter, so a US audience needs no size setting, and the margin option sets page margins. Add displayHeaderFooter: true and a footerTemplate containing an element with the class pageNumber to print page numbers.

With WeasyPrint the same result comes from CSS alone: an @page rule sets size and margins, as in the documentation's @page { size: A3; margin: 1cm } example with your own values.

A mistake to avoid: expecting the PDF to match the screen

PDF renderers print; they do not screenshot. Puppeteer's documentation states that page.pdf() uses the print CSS media type, that printBackground is false by default, and that colors may be modified for printing. So the header band above disappears until you set printBackground: true, and any @media print rules in your stylesheet apply. Call page.emulateMediaType('screen') before page.pdf() if you want screen styles.

The second mistake is security. Both the WeasyPrint documentation and the wkhtmltopdf status page warn against rendering untrusted HTML. If users can supply markup, sanitize it and isolate the renderer.

The third is long tables splitting badly across pages; the page breaks guide covers the CSS. For template-driven versions of these steps, see the Node.js and Python guides.

Sources used for this page

The facts above come from the pages below, read on 3 October 2026. We have not used these products hands-on. Prices and terms change, so confirm them on the vendor's site before you buy.

  1. Installation | Puppeteer — Vendor documentation · pptr.dev · checked 2026-10-03
  2. PDF generation | Puppeteer — Vendor documentation · pptr.dev · checked 2026-10-03
  3. Page.setContent() method | Puppeteer — Vendor documentation · pptr.dev · checked 2026-10-03
  4. Page.pdf() method | Puppeteer — Vendor documentation · pptr.dev · checked 2026-10-03
  5. PDFOptions interface | Puppeteer — Vendor documentation · pptr.dev · checked 2026-10-03
  6. First Steps - WeasyPrint documentation — Vendor documentation · doc.courtbouillon.org · checked 2026-10-03
  7. Installation | Gotenberg — Vendor documentation · gotenberg.dev · checked 2026-10-03
  8. Convert HTML to PDF | Gotenberg — Vendor documentation · gotenberg.dev · checked 2026-10-03
  9. DocRaptor API documentation: overview and parameters — Vendor documentation · docraptor.com · checked 2026-10-03
  10. Convert to PDF - PDFShift API Documentation — Vendor documentation · docs.pdfshift.io · checked 2026-10-03
  11. Authentication - PDFShift API Documentation — Vendor documentation · docs.pdfshift.io · checked 2026-10-03
  12. API2PDF home page with starter requests — Vendor product page · api2pdf.com · checked 2026-10-03
  13. wkhtmltopdf project status — Vendor documentation · wkhtmltopdf.org · checked 2026-10-03