§ Rails HTML to PDF
HTML to PDF Rails: Convert a Ruby on Rails View to a Real PDF
Turn a Rails view into a searchable, pixel accurate PDF with one call. Managed Chromium renders your real ERB or ViewComponent output with full CSS, web fonts and JavaScript, so you can leave the archived wkhtmltopdf binary behind without putting Chromium in your container. Try it on any URL or HTML below.
- Early access, launching soon
- No card required
- Your HTML stays yours
§ Live demo
Runs in your browser. Nothing is uploaded.
Your HTML
Live preview
Your PDF is downloading. Want this as one API call, with the page archived too?
§ Short answer
To convert HTML to PDF in Rails, render your view to a string with render_to_string, then hand that HTML to a renderer. The old default, WickedPDF, wraps wkhtmltopdf, which was archived in 2023 and receives no security patches, so it is not a safe choice for new apps. The current in-app options are Grover, which drives Chromium through Puppeteer and needs Node on the host, and Ferrum, which drives Chromium directly with no Node. Both mean shipping and scaling a browser yourself. The alternative is to POST the HTML to a rendering API. Sitepdf renders it in managed Chromium and returns a true, selectable vector PDF, plus an optional timestamped archive of exactly what it rendered.
Last updated July 2026. Written and fact checked by the Sitepdf team.
§ 00
Four ways to make a PDF in Rails, compared
Rails has no built-in PDF export, and the long-standing default is now on borrowed time. These four routes differ on rendering engine, what you must install and run, and whether your CSS and JavaScript survive.
| Approach | Engine | CSS and JavaScript | What you run | Best for |
|---|---|---|---|---|
| WickedPDF legacy |
wkhtmltopdf, an old WebKit fork | Dated CSS support, no modern layout; JavaScript is unreliable | A vendored wkhtmltopdf binary per platform | Existing apps only, as a temporary state with a migration planned |
| Grover Chromium via Node |
Chromium, driven through Puppeteer | Full modern CSS and JavaScript, it is a real browser | Node plus Puppeteer plus Chromium in your image | New apps where Node on the host is already acceptable |
| Ferrum PDF Chromium, no Node |
Chromium, driven directly over CDP from Ruby | Full modern CSS and JavaScript | Chromium in your image, but no Node runtime | Teams who want browser fidelity without adding Node |
| Managed Chromium API Sitepdf |
Chromium, run and scaled by us | Full modern CSS and JavaScript | One HTTP call, no browser in your container | Production documents, exact fidelity, zero browser ops, a dated record |
The honest read: Grover and Ferrum are good gems and give you the same Chromium output we do, for free, if you are happy to install and scale a browser. Ferrum is the lighter of the two since it drops the Node layer. An API earns its place when a browser does not belong in your container at all, when your PDF traffic is spiky and you do not want to size a browser pool for peaks, or when you need a retrievable, timestamped record of what you rendered.
§ 01
First, the WickedPDF situation
For a decade, "HTML to PDF in Rails" meant WickedPDF, and the pattern it popularized was genuinely good: you render a normal Rails view, in a normal layout, and get a PDF of it. The problem is not the gem, it is the engine underneath. WickedPDF shells out to wkhtmltopdf, and the wkhtmltopdf project was archived in 2023. It still runs, and plenty of production apps still use it, but nothing is being fixed, including security issues, and its rendering engine is an old WebKit fork that never learned modern CSS.
What that means in practice: a template written today with flexbox or CSS grid will not lay out correctly, web fonts are fragile, and JavaScript-driven content is a coin flip. If you have a WickedPDF app that works, there is no emergency, but treat it as a temporary state and pin your binary version. For anything new, start on a current engine. The wkhtmltopdf alternative page maps the replacements across every language, not just Ruby.
§ 02
Grover and Ferrum: real Chromium, in your infrastructure
The two in-app successors both give you Chromium, and the difference between them is the stack you have to carry. Grover drives Chromium through Puppeteer, which means Node and a Chromium download live in your image alongside Ruby. It keeps the familiar shape, so a WickedPDF migration is mostly mechanical: you still build HTML with render_to_string and pass it in. Ferrum talks to Chromium directly over the Chrome DevTools Protocol from Ruby, so the Node layer disappears and there is one less wrapper between your call and the browser.
Both are solid, and if you are comfortable running a browser they are the cheapest way to get browser-quality output. Be clear-eyed about what running a browser means, though. Chromium is memory hungry, a crashed or leaked browser process will take a Puma worker with it, and sizing a pool for a Monday-morning batch of statements is a real capacity exercise rather than a one-line config. Teams usually discover this the first time a month-end job renders two thousand documents at once.
§ 03
The API path: same Chromium, none of the ops
If you want browser fidelity but not a browser, the pattern stays the same and only the last step changes. Render your view to a string exactly as you would for Grover, then post it, or point the API at a live route in your app and let it load the page and run the JavaScript.
class InvoicesController < ApplicationController
def show
html = render_to_string(template: "invoices/show", layout: "pdf", formats: [:html])
response = Faraday.post("https://api.sitepdf.com/v1/render") do |req|
req.headers["Authorization"] = "Bearer #{ENV['SITEPDF_KEY']}"
req.body = { html: html, format: "Letter", archive: "true" }
end
redirect_to JSON.parse(response.body)["pdf_url"], allow_other_host: true
end
endYour asset pipeline output, Tailwind classes, web fonts and any JavaScript charts render the way they do in Chrome, and the PDF text stays selectable and searchable rather than becoming a flat image. Nothing runs a browser inside your dyno or pod, so a spike in PDF volume does not become a memory incident in your web tier. The same call works from a Sidekiq job for background generation, which is where most Rails PDF work belongs anyway. Our HTML to PDF in Ruby guide covers the gem-by-gem detail including Prawn, and the PDF generator API page lists every parameter.
§ 04
When the document is not really HTML: Prawn
One honest caveat before you reach for any HTML renderer. If the document has no HTML version and never will, a shipping label, a boarding pass, a generated certificate, then Prawn is probably the right tool. It is pure Ruby, draws the page in code, has no browser or binary behind it, and is the fastest option because it skips a layout engine entirely. The trade is that you describe the document in Ruby rather than reusing a view, so it drifts from your web pages over time. Use Prawn when there is no page to mirror, and an HTML renderer when there is one.
§ 05
Keep a dated copy of every document you generated
A generated invoice, quote or statement leaves your Rails app and nothing verifiable stays behind. Add archive=true to the render call and Sitepdf also stores a timestamped, immutable snapshot of exactly what it rendered, retrievable by id later, so you can prove what a document said on a given date. The website archiving page explains how the record works, and if you are weighing running headless Chrome yourself, the Puppeteer alternative page runs that trade off honestly. Renders are transient by default; leave archiving off and we return the PDF and store nothing.
curl https://api.sitepdf.com/v1/render \
-H "Authorization: Bearer $SITEPDF_KEY" \
-F url=https://app.example.com/invoices/8842 \
-F format=Letter \
-F print_background=true \
-F archive=true
{
"pdf_url": "https://api.sitepdf.com/v1/documents/doc_rb27f.pdf",
"pages": 2,
"rendered_in_ms": 1523,
"archive": {
"id": "arc_rb64d",
"captured_at": "2026-07-19T21:44:52Z",
"retrieve_url": "https://api.sitepdf.com/v1/archives/arc_rb64d"
}
}
The API is in early access; this is the documented call shape it opens with. Full request and response walkthrough.
§ 06
Questions about this job
How do I convert HTML to PDF in Ruby on Rails?
Is WickedPDF still safe to use in 2026?
Grover or Ferrum, which should I use in Rails?
How do I generate a PDF in Rails without installing Chromium?
Should I use Prawn or an HTML to PDF renderer in Rails?
§ Index
More PDF and archiving tools
- Convert HTML to PDF
- Webpage to PDF
- Save webpage as PDF
- URL to PDF API
- Website archiving
- Screenshot API
- React to PDF
- Laravel HTML to PDF
- Vue to PDF
- Next.js PDF generator
- Angular to PDF
- Markdown to PDF API
- Django HTML to PDF
- Blazor HTML to PDF
- Spring Boot HTML to PDF
- Airtable to PDF
- PDF generator API
- Document generation API
- Bulk HTML to PDF
- Wayback Machine alternative
- Best HTML to PDF API
- DocRaptor alternative
- Puppeteer alternative
- Wkhtmltopdf alternative
- PDFShift alternative
- Urlbox alternative
- PDFCrowd alternative
- Api2Pdf alternative
- Browserless alternative
- APITemplate alternative
- CraftMyPDF alternative
- PDFMonkey alternative
- dompdf alternative
- Gotenberg alternative
- GrabzIt alternative
- How it works
- Features
- Pricing
§ Early access
Get on the early-access list
The API opens to the list first, in order. Early access locks the planned launch rates for 12 months. No card required, launching soon.