Ask HN: What is nowadays (opensource) way of converting HTML to PDF?

176 points by hhthrowaway1230 ↗ HN
I'm using wkhtmltopdf but it is painful to work with? what are other people using nowadays? i.e canva or other tools?

86 comments

[ 3.1 ms ] story [ 97.2 ms ] thread
pandoc
Does pandoc do JavaScript? For stuff that is rendered (I don't want animated, interactive PDFs...).
To reinforce this: pandoc has been the go-to for a long, long time and they have encountered and addressed tons of issues, which is especially important for two underspecified and over-provisioned formats like HTML and pdf.

Go through the revision and bug history to see a sample of issues you're avoiding by using a highly-trafficked, well-supported solution.

The only reason not to use it is when they say they don't support a given feature that you need; and the nice thing there is that they'll usually say it, and have a good reason why.

The other reason to use pandoc is that while you might currently want PDF as your outbound format, you might end up preferring some other format (structured logically instead of by layout); with pandoc that change would be easy.

Finally, pandoc is extensible. If you do find that you want different output in some respect, you can easily write an plugin (in python or haskel or ...) to make exactly the tweak you need.

I run chromium on my server and render the PDF from there using puppeteer.
Puppeteer and Playwright are the main open-source options nowadays, both solid for HTML → PDF once your print CSS is sorted. Don’t forget proper page breaks (break-before/after/inside) — e.g. break-after: page works in Chromium, while always doesn’t. For trickier pagination you can look at Paged.js, and I’d test layouts in Chrome/Edge before automating.

Shameless plug: I run yakpdf.com, a hosted Puppeteer-based service if you want to avoid self-hosting. https://rapidapi.com/yakpdf-yakpdf/api/yakpdf

Seconded. I went with C# + Playwright. I tried iTextSharp, iText, PDFSharp, and wkhtmltopdf, but they all had limitations. I had good results with Playwright in minutes, outside of tweaking the CSS like you mention.

I documented the process here[0] if anyone needs examples of the CSS and loading web fonts. Apologies for the article being long-winded – it was the first one I published.

[0] https://johnh.co/blog/creating-pdfs-from-html-using-csharp

Thirded, you can build this straight into your backend or into a microservice very easily.

You can also easily generate screenshots if that's more suitable than PDFs.

You can also easily use this to do stuff like jam a set of images into a HTML table and PDF or screenshot them in that format.

You made me realize that tractor feed roll paper would be really great for printed web pages, no page breaks! Kinda like reading scrolls of yore.
https://gotenberg.dev/ ...has been working well for me for the last few years. It's a headless instance of Google Chrome with a golang wrapper. Runs well in Docker or a cloud instance.
gotenberg is really rock solid for us. Easy to deploy as a docker container to any infrastructure.
Seconding.. gotenberg has been solid for us. We also make use of it's convert from Word to PDF feature and it's been really solid.
Just print to PDF in a browser, or automate that using a browser automation tool. For a non-browser-based open source solution, WeasyPrint.

https://weasyprint.org/

For a proprietary solution, try Prince XML:

https://www.princexml.com/

+1 to weasyprint; I have used weasyprint with a django production system for a few years now, and it works well enough that I never have to think about it. I'm not doing anything fancy, though, but for me it has worked well.
WeasyPrint works really well for me. It can support all of the languages and fonts I need. I run it on AWS Lambda and in Docker as a web service.

I previously used WKHTMLTOPDF, but it hasn't been supported for years and doesn't support the latest CSS, etc. It does support JS if you need it, but I'd probably look at headless Chromium or another solution for JS if needed.

Edit: Previous post with some good discussion: https://news.ycombinator.com/item?id=26578826

This is my experience and recommendation too.
Prince XML looks nice but what about creating a PDF directly from a website? This often adds some problems, for example links still pointing to other pages on the web. But in my experience printing to PDF is often not good enough.
Yes, I did that for a recent small program. The @media print media query is powerful enough for most of the stuff I wanted to format nicely. Even page breaks are possible.
I’ve had excellent experience with Prince XML and poor experience with everything else I’ve tried. Prince is fast, robust and reliable.

Yes it costs money. So does developer time.

Agreed. Prince also has a lot of good features for headers, footers, page numbering, etc, that make it very powerful.
Most website do not have a print CSS, so it doesn’t print that nicely in PDF.

But, I upvote weasyprint for that instead.

These two are the only right answers if you want a reliable, reproducible, relatively low resource experience. Running a browser engine has always been hard to maintain in the long run for me.
+1 - Weasyprint is an excellent tool to make pdf from html content, and we're using it at work (with django) to export various documents.
Seconded. In my eccentric workflow, I use Weasyprint to convert HTML emails to more portable PDFs. A surprisingly successful experiment.
> Just print to PDF in a browser

I tried yesterday. With compliments to the moms of SWE who coded the functionality in firefox. Aparently puting the screen on a pdf page is an insurmontable task in 2025. (20 years ago was still doable). I had to make a screenshot and process the picture to print it.

Orion browser produces PDFs which are exactly what you see on screen.
I'll join the choir. We use weasyprint for ebooks and invoices and it's a joy to use. Massively new support for features over the last few years (partially thanks to some monetary sponsorships), it started pretty bare bones, and is now close to commercial solutions.

The maintainers are also very responsive, and helpful.

Amazing project

if you are doing html to pdf, you might also need the ability to merge. a few more features and you're better of with a commercial solution.
Don’t. Show a web page and open the print dialog, and tell people to save as PDF. All major browsers support this, and the browser HTML to PDF code is the most robust and accurate.
If you don't really need the PDF but just want to archive pages, SingleFile is better. It'll capture the entire page to a single HTML file and I find this is better than the PDF if I don't want to print it. It's a browser extension, but there's also a command line version (https://github.com/gildas-lormeau/single-file-cli) that uses Chrome or Chromium's headless mode.
A revers of this question; what is the best way to convert pdf to html? We are required by accessibility law to make our PDFs WCAG compliant however it would be easier to convert these to HTML.
A reverse of this question; what is the best way to convert pdf to html? We are required by accessibility law to make our PDFs WCAG compliant however it would be easier to convert these to HTML.
Rendering to SVG, at least that's what I did on https://fschutt.github.io/printpdf/

I am currently writing a WASM-ready PDF toolkit that can handle both HTML to PDF and then rendering PDF pages to SVG. However, it's not yet production-ready.

The underlying HTML engine is currently a severe "work in progress", but it gives me the low-level access that I need: https://azul.rs/reftest

This reduces to parsing PDFs, which is an unsolved hard problem.

At low volumes, my preferred approach is to select and extract text (copy/paste, perhaps using the poppler library for larger-scale work), dump that to plain-text and convert that (manually / scripted) to Markdown. From there you can get to PDF or pretty much any other format through tools such as pandoc.

Please don't turn nice formats into a format that's similar to screenshots of text. Pandoc has an option to pack all images and styles needed to render the page into one html file:

    pandoc --self-contained input.html -o output.html
HTML+CSS+media files isn’t a nice format, and much less portable through time and space than PDF.
> Please don't turn nice formats into a format that's similar to screenshots of text

Converting HTML to PDF shouldn't result in an image wrapped in a PDF. Text will be preserved as text in the final PDF. (Unless the converter is garbage, of course.)

I was excited to try this today, but this is unusable. It absolutely mangles the page.

  - It duplicated the headline, one in the correct place top-center but then a 2nd copy of the headline left-aligned below that.
  - It shrunk the width of the content of the page (in fact, it seems to have completely discarded the css for the #content selector)
  - It discarded the CSS for my code blocks, so now they are unreadable.
  - My images are no longer center-aligned
  - It added CSS that was not in the original document. For some reason, it addded hyphens: auto, overflow-wrap: break-word, text-rendering: optimizeLegibility, font-kerning: normal . None of those rules existed in the original document anywhere. Now my text is breaking mid-word with hyphens inserted.
  - It pointlessly HTML-escaped some characters (like every quotation mark in every paragraph). This didn't break anything, but just... why?
Implementing the same functionality is like less than 100 lines of python, so I'm just going to go that route. I've implemented it once before, but it was for a previous company so I no longer have access to that code, but its like 1 afternoon of scripting and doesn't randomly destroy your documents. I don't know how pandoc got this so wrong.

For context: the document I am attempting to process has no javascript. It is a simple Emacs Org document (similar to markdown) rendered to HTML and then processed with pandoc. The only external content was a couple of images.

Is this an xy problem? If you have the original document (in Markdown), one possibility would be to use my software, KeenWrite[1], to convert Markdown to XHTML then typeset XHTML to PDF via ConTeXt. See the user manual[2] for an example of a Markdown document typeset in this fashion, along with usage instructions.

If you only have HTML to work with, you can also use Flying Saucer[3], which is what KeenWrite uses to preview Markdown documents when rendered as HTML. Flying Saucer uses an open-source version of iText[4] to produce PDF documents (from HTML source docs).

Another possibility is to use pandoc and LaTeX.

[1]: https://keenwrite.com/

[2]: https://keenwrite.com/docs/user-manual.pdf

[3]: https://github.com/flyingsaucerproject/flyingsaucer

[4]: https://itextpdf.com/

(comment deleted)
the only thing I found to work reliably well is simply Chromium's print feature
5k pdfs a month for archival purposes, must be pdf, customers demand this
If your HTML is simply an intermediary to get you to a PDF, you could consider just skipping straight to building the PDF directly:

https://pdfbox.apache.org

This would be far more efficient than spinning up an entire browser and printing PDFs to disk.

Building PDF directly (unless you're creating documents, especially fillables) is non-intuitive. Most PDFs are people trying to capture live data in a cached manner. If not, using a preliminary format like Markdown/HTML/LaTeX/DocX/etc to generate your PDF is almost always more intuitive.
My website's content is xml, and I use Apache Fop to turn it into a PDF with page numbers and other nice things. It works nicely, but takes some setup.
I have Chromium shoved into an AWS Lambda Layer, when we need HTML to PDF conversion we shove it off onto that. It loads the HTML into Chromium then "prints" it to PDF.
I'd love to go the other way: convert a PDF into a self contained HTML page that renders properly in a browser. It's been way harder than I thought it would. Any advice?
If generating PDF dynamically is what you really care about, consider Typst. https://typst.app/ We use it in production to generate reports, and it is amazing.