Choosing a Rails HTML-to-PDF Gem

HtmlToPdf vs. Grover vs. WickedPdf/PDFKit vs. Prawn — what each one actually renders, what it depends on, and which question to ask before picking one.

The first question is not "which gem" — it's "do I want to render my existing view, or build the PDF's layout from scratch." Prawn is the only contender here that doesn't render HTML/CSS at all; everything else in this comparison converts an HTML page, the difference is how.

CapabilityHtmlToPdfGroverWickedPdf / PDFKitPrawn
Renders existing HTML/CSS view✓✓✓— (own DSL)
Rendering engineChrome (CDP, direct)Chrome (via Node/Puppeteer)wkhtmltopdfn/a
Modern CSS (flexbox/Grid)✓✓—n/a
Runtime outside RubyChrome/ChromiumChrome + Node.js + Puppeteerwkhtmltopdf binarynone
Pooled/reused browser process✓ (built in)depends on setupn/a (CLI per call)n/a
Rails controller integrationbuilt in (around_action)manualbuilt inmanual
Precise pixel-level layout controlvia CSSvia CSSvia CSS (limited)✓ (direct PDF primitives)

HtmlToPdf

Headless Chrome driven directly over the DevTools protocol via ferrum — no Node.js in the dependency chain. One pooled browser process per Ruby process (see BrowserPool), each render in its own isolated context. Ships as an around_action, so other callbacks and rescue_from work exactly as they would for a normal request — see why that specific detail is harder to get right than it looks. The narrowest print-options surface of the HTML-rendering contenders here: every option is a validated number/enum/boolean except header/footer templates, which are opt-in only (see Security). Best fit if you want Chrome-quality rendering without adding Node.js to a pure-Ruby/Rails stack.

Grover

Also headless Chrome, via Puppeteer — which means Node.js and the puppeteer npm package become real dependencies alongside the Ruby gem, not just an implementation detail. If your deploy already runs a Node toolchain for other reasons, that cost is close to zero; if it doesn't, it's a second language runtime to install, patch, and reason about solely for PDF export. Puppeteer's own PDF generation API (native header/footer templates, `waitUntil` semantics) is mature and well-documented independent of Grover itself.

WickedPdf / PDFKit

Both wrap the wkhtmltopdf binary — see Headless Chrome vs. wkhtmltopdf for what that costs you in rendering fidelity (no flexbox/Grid, years-stale WebKit, an unmaintained upstream project). The appeal is real, though: a single static binary is operationally simpler to deploy than a full Chrome install, and for simple layouts — plain text, basic tables, no modern CSS — the rendering gap may never actually surface. If your PDF output is that simple and you'd rather not add a browser to your stack, this is a legitimate reason to stay.

Prawn

A fundamentally different tool, not a wkhtmltopdf/Chrome alternative: Prawn has no HTML/CSS engine at all. It's a Ruby DSL for drawing PDF content directly — text blocks, tables, shapes, positioned by hand. Choosing Prawn means writing your PDF's layout as Prawn code instead of reusing an existing view, full stop; there's no middle ground where you point it at an ERB template. The payoff is precision: exact pixel-level control over a PDF a browser-rendering approach can only approximate through CSS. Right tool when the PDF's layout needs don't actually match your HTML view's layout at all — a label sheet, a check, a precisely-gridded form — not when the goal is "render this page as a PDF."

The actual decision

  1. Need the PDF to look exactly like an existing, CSS-styled view? Rule out Prawn immediately — it can't do that by design.
  2. Want Chrome-quality rendering without adding Node.js to the stack? HtmlToPdf.
  3. Already running Node.js/Puppeteer for other reasons, or specifically want Puppeteer's own PDF API? Grover.
  4. PDF output is simple enough that wkhtmltopdf's rendering gap won't matter, and a single static binary beats a Chrome install for your deploy? WickedPdf/PDFKit.
  5. Need pixel-exact control a CSS layout can't give you — labels, checks, precisely-gridded forms? Prawn, writing the layout directly.

Further reading