Convert HTML to PDF from the command line (2026 guide)

30 July 2026

The fastest way to convert HTML to PDF from the command line is headless Chrome, which is already installed on most machines: google-chrome --headless --print-to-pdf=out.pdf page.html. For print-grade CSS control use WeasyPrint; for scripts and CI where you'd rather not run a browser at all, one curl call to an HTML to PDF API does the job.

Most tutorials ranking for this search still open with wkhtmltopdf. That advice is years out of date: the project was archived in 2023 with unpatched vulnerabilities, and the modern replacement was hiding in plain sight the whole time, because the browser on your machine ships its own print-to-PDF mode.

This guide covers the four command-line routes that matter in 2026, in order of how often they're the right answer, every command copy-paste ready for Linux and macOS.

Key TakeawaysHeadless Chrome is the new default: --headless --print-to-pdf converts any HTML file or URL with the same engine as your browser, no installation needed on most systems.The Chrome CLI has hard limits: no custom headers/footers beyond on/off, no fine margin control. That's where WeasyPrint or an API takes over.WeasyPrint (pip install weasyprint) owns print CSS on the command line: @page rules, margin boxes, page counters.Don't reach for wkhtmltopdf: archived since 2023, unpatched 9.8-severity SSRF, frozen 2016 WebKit.curl + an HTML to PDF API needs zero installed tools, works identically in CI containers and cron jobs, and adds page numbers and custom footers the Chrome CLI can't do.

The command-line one-liner: headless Chrome

Chrome and Chromium ship a print-to-PDF mode. If a browser is installed, you already have an HTML to PDF command line tool:

# Linux
google-chrome --headless --print-to-pdf=out.pdf page.html

# macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
  --headless --print-to-pdf=out.pdf page.html

# URLs work the same way
google-chrome --headless --print-to-pdf=report.pdf https://example.com/report

Rendering is real Chromium: flexbox, grid, webfonts, and JavaScript all behave exactly as they do in a browser tab.

The flags that matter

  • --print-to-pdf=FILE: output path. Omit the =FILE part and Chrome writes output.pdf in the working directory.
  • --no-pdf-header-footer: drops the default date/URL header and footer Chrome prints. You almost always want this. (See the headless Chrome docs for the full flag set; older tutorials show --print-to-pdf-no-header, its deprecated predecessor.)
  • --virtual-time-budget=5000: gives JavaScript up to five simulated seconds to settle before capture. Use it for pages that render client-side.
  • --disable-gpu: only needed on some older Windows setups; harmless elsewhere.

Where the Chrome CLI stops

The command line exposes a fraction of what the engine can do. There's no custom header or footer content (on/off only, so no "Page 1 of 4"), no per-run margin control, and no retry logic when a page hangs. Print-CSS @page rules in your HTML can cover margins and sizing; the rest needs one of the routes below.

WeasyPrint: print CSS from the terminal

WeasyPrint is a Python layout engine with a first-class CLI:

pip install weasyprint
weasyprint invoice.html invoice.pdf
weasyprint https://example.com/statement statement.pdf

Its strength is everything Chrome's CLI hides: @page margins and sizes, margin boxes for running headers, page counters in pure CSS. Its boundary is JavaScript, of which it executes none, so client-rendered pages are out. For designed print documents generated from server-rendered HTML, it's the strongest free CLI there is; our WeasyPrint guide goes deeper on its CSS support.

pandoc and friends: documents, not web pages

If your source is document-shaped (Markdown, HTML that's really an article), pandoc in.html -o out.pdf produces book-quality output, with a caveat: its default PDF path runs through LaTeX, a hefty install. You can point it at WeasyPrint instead (--pdf-engine=weasyprint) and skip LaTeX entirely.

pandoc is a document converter, not a web renderer: page-accurate CSS layout isn't its game. The distinction, and when each wins, is covered in our Pandoc alternatives comparison.

Don't use wkhtmltopdf in 2026

It has to be said, because half the ranking tutorials still recommend it: wkhtmltopdf was archived in January 2023, last released in 2020, renders with a frozen 2016-era WebKit that mangles modern CSS, and carries an unpatched 9.8-severity SSRF vulnerability (CVE-2022-35583) that makes it dangerous with any untrusted HTML. Distribution packages are disappearing too (Homebrew disabled its cask in 2024).

Every flag it offered has a modern equivalent: page setup → Chrome flags or @page CSS; --header-html/--footer-html → an API's header/footer parameters. Our wkhtmltopdf alternatives guide maps the full migration.

curl + an HTML to PDF API: zero installs

For CI pipelines, minimal containers, and cron jobs, the leanest command line HTML to PDF setup is an HTML to PDF API: it installs nothing at all.

curl -s -X POST https://api.transformy.io/v1/pdf/chrome \
  -H "Authorization: Bearer $TRANSFORMY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "'"$(cat invoice.html | sed 's/"/\\"/g')"'",
    "page_size": "A4",
    "margin": "20mm 15mm",
    "footer": { "html": "<span style=\"font-size:9px\">Page {{page}} of {{pages}}</span>" }
  }' \
  --output invoice.pdf

(For anything beyond a quick shell hack, build the JSON with jq -n --rawfile html invoice.html '{html: $html, page_size: "A4"}' instead of sed-escaping.)

Three things this route adds over the Chrome CLI: real headers and footers with {{page}}/{{pages}} tokens, no browser binary in your CI image, and consistent behavior everywhere the script runs. Rendering still happens on headless Chromium, server-side. The full parameter list, including URL mode for live pages, is in the HTML to PDF API docs; test keys render real watermarked PDFs free, so you can wire up the pipeline before deciding anything.

Batch converting HTML files to PDF

Both main routes loop cleanly:

# Headless Chrome, every HTML file in a folder
for f in *.html; do
  google-chrome --headless --no-pdf-header-footer \
    --print-to-pdf="${f%.html}.pdf" "$f"
done

# curl variant with jq, safe for any HTML content
for f in *.html; do
  jq -n --rawfile html "$f" '{html: $html, page_size: "A4"}' \
    | curl -s -X POST https://api.transformy.io/v1/pdf/chrome \
        -H "Authorization: Bearer $TRANSFORMY_API_KEY" \
        -H "Content-Type: application/json" \
        -d @- --output "${f%.html}.pdf"
done

The Chrome loop is serial and local; fine for dozens of files. For hundreds or thousands, or for recurring batch jobs, concurrency, retries, and delivery become the real problem, which is its own topic (async jobs and webhooks) beyond one loop.

FAQ

What is the best command line tool to convert HTML to PDF on Linux?

Headless Chrome or Chromium: google-chrome --headless --print-to-pdf=out.pdf page.html. It's likely already installed, renders with a current browser engine, and handles JavaScript. For print-CSS control without a browser, WeasyPrint is the strongest alternative.

How do I convert HTML to PDF without installing anything?

If a browser is present, the Chrome one-liner needs no installation. On a bare container or minimal CI image, one curl call to an HTML to PDF API converts with nothing installed beyond curl itself.

What replaced wkhtmltopdf?

Headless Chrome for the general case (same one-command usage, modern engine), WeasyPrint for print-CSS documents, and hosted Chrome APIs where wkhtmltopdf's header/footer flags were the draw. wkhtmltopdf itself is archived with unpatched CVEs and shouldn't be used for new work.

How do I get page numbers from the command line?

Chrome's CLI can only toggle its default header/footer. For "Page X of Y" you have two options: WeasyPrint with CSS page counters, or an API's footer parameter with {{page}}/{{pages}} tokens, as in the curl example above.

Conclusion

The 2026 command line HTML to PDF toolkit, in one list:

  • Quick conversion, any page → the headless Chrome one-liner.
  • Designed print documents, pure CSS control → WeasyPrint.
  • Markdown/article sources → pandoc (with WeasyPrint as its engine).
  • CI, cron, containers, page numbers → curl + a rendering API.
  • wkhtmltopdf → migrate away.

And if the curl route fits your pipeline, grab a free API key: 100 documents a month, test keys unlimited, no credit card, your script works in the next five minutes.