Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsUse a browser renderer when the source is HTML and the output must preserve CSS, fonts, images, and layout. In Ruby, Grover provides the most direct route to PDF and PNG/JPEG files through Puppeteer and Chromium; Ferrum gives lower-level Chrome DevTools Protocol control for screenshots and PDFs. HTML-to-Word is a different path: metanorma/html2doc produces a legacy .doc file, which Microsoft Word must then open and save as .docx. The ruby-docx gem works with existing DOCX files; it is not an arbitrary HTML-to-DOCX converter.
Choose the conversion path before writing Ruby code
These formats do not come from one equivalent renderer. PDF and screenshots are browser-rendering jobs: a headless Chromium instance lays out the HTML, executes CSS and JavaScript, loads images, and captures the resulting page. DOCX is an Office Open XML document, so the documented Ruby route in this set of tools first creates old-style Word output and then relies on Microsoft Word for the native DOCX save.
| Output | Ruby route documented by the projects | What you receive |
|---|---|---|
| Grover or Ferrum with Chromium | Browser-rendered PDF with CSS and page-layout controls | |
| PNG/JPEG screenshot | Grover or Ferrum with Chromium | Raster image of a page, viewport, or full document |
| WebP screenshot | Ferrum | Browser screenshot in WebP format |
| DOCX | metanorma/html2doc to .doc, then Microsoft Word Save As |
Native .docx only after the Word conversion step |
Confirm the current gem, browser, and operating-system requirements in each project’s README before deployment. The documentation reviewed here does not establish a current version matrix or guarantee compatibility with a particular Ruby release.
Set up a browser renderer for PDF and images
Grover: the shortest path from HTML to PDF or PNG/JPEG
Grover accepts either a URL or inline HTML and uses Puppeteer with Chromium. Install the Grover gem and the Puppeteer/Chromium runtime described in its README, then save the bytes returned by to_pdf, to_png, or to_jpeg.
#1 Best Overall
require "grover"
# URL input
pdf = Grover.new("https://example.com/invoice/42").to_pdf
File.binwrite("invoice.pdf", pdf)
# Inline HTML input
html = <<~HTML
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body { font-family: sans-serif; margin: 32px; }
h1 { color: #222; }
</style>
</head>
<body><h1>Ruby report</h1><p>Generated from inline HTML.</p></body>
</html>
HTML
png = Grover.new(html).to_png
File.binwrite("report.png", png)
jpeg = Grover.new("https://example.com").to_jpeg
File.binwrite("page.jpg", jpeg)
For production URLs, make sure the Chromium process can resolve the host, reach required assets, and access any authenticated content. For inline HTML, use absolute URLs for external stylesheets, fonts, and images or embed the assets so the browser has something it can load.
Ferrum: use Chrome controls directly
Ferrum drives a browser through the Chrome DevTools Protocol. Choose it when you need browser-level capture controls rather than Grover’s simpler input/output interface. Its documented APIs cover PNG, JPEG, and WebP screenshots, full-page capture, targeted capture options, and PDF paper sizes or custom dimensions.
require "ferrum"
browser = Ferrum::Browser.new
begin
browser.go_to("https://example.com")
# Viewport screenshot. The format may be :png, :jpeg, or :webp.
browser.screenshot(path: "viewport.png", format: :png)
# Capture the complete document rather than only the viewport.
browser.screenshot(path: "full-page.webp", format: :webp, full: true)
# Browser-generated PDF on A4 paper.
browser.pdf(path: "page.pdf", format: "A4")
ensure
browser.quit
end
Ferrum’s screenshot API also documents quality, scale, selector/area capture, and full-page options. Its PDF API accepts a named paper format or custom page dimensions. Keep those settings in the capture call so a desktop viewport does not accidentally become a mobile-looking export.
Grover or Ferrum?
- Choose Grover for a small conversion service where a URL or HTML string should become PDF, PNG, or JPEG with minimal browser code.
- Choose Ferrum when you need explicit browser navigation, selector or area capture, WebP, custom paper dimensions, or other Chrome-level operations.
- Choose neither for a drawing-only PDF if your input is not HTML. Prawn is a programmatic PDF layout library, not an HTML-to-PDF renderer; its documentation directs HTML-rendering use cases toward Ferrum.
Convert HTML to PDF reliably
- Make the page deterministic. Supply a complete HTML document, stable CSS, and absolute asset URLs. If the page depends on JavaScript, ensure the browser has time to execute it before capture.
- Navigate and wait. For a URL, wait for the page’s required content and assets rather than assuming the initial response means rendering is complete.
- Select page geometry. Use the PDF paper format or custom dimensions documented by Ferrum. Keep print CSS, margins, and page-break rules in the HTML so headings and tables do not split unexpectedly.
- Write bytes in binary mode. PDF output is binary; use
File.binwriteor an equivalent binary stream. - Validate the artifact. Open the resulting PDF in a parser or viewer and check fonts, images, links, page count, and clipping before distributing it.
A browser PDF is not the same as printing source text. Web fonts may fail when the runtime cannot reach them, remote images can produce empty boxes, and content rendered after an asynchronous request may be missing unless your wait condition accounts for it.
Convert HTML to screenshots
Viewport versus full-page images
A viewport screenshot represents what fits in the browser window. A full-page screenshot extends the capture over the document’s scrollable height. Use viewport images for responsive checks and social-card-like assets; use full-page capture for long pages, invoices, and visual regression baselines.
Control image format and size
PNG is lossless and useful for text or UI comparisons. JPEG is smaller for photographic pages but introduces compression. Ferrum also documents WebP. Its options include quality and scale, allowing you to trade file size against sharpness. A high scale improves detail while increasing memory and transfer costs.
Rank #2
Capture a specific region
When the deliverable is one component rather than an entire page, use Ferrum’s documented selector or area capture options. Keep the selector stable and fail the job when it is absent; silently capturing the whole page can hide a template regression.
Why the DOCX route is different
The documented html2doc workflow
The metanorma/html2doc project documents HTML-to-Word output as legacy .doc. Its route to a native .docx is:
Recommended Free Tools
- Prepare the HTML according to the project’s supported input.
- Run
html2docas documented by that project to generate a.docfile. - Open the generated file in Microsoft Word.
- Use Word’s Save As command and select the
.docxformat. - Recheck tables, page breaks, images, and styles in the saved document.
This intermediate format and Word step are material limitations. Do not describe html2doc as a direct native-DOCX renderer, and do not promise that browser CSS will map perfectly to Word styles.
Where ruby-docx fits
The ruby-docx gem is for interacting with existing DOCX documents. Its README describes reading document structures and rendering paragraphs as HTML. That is useful for inspecting or transforming a DOCX already in your pipeline, but it does not establish arbitrary HTML-to-DOCX conversion.
When to avoid an HTML-to-DOCX claim
If your requirement is a one-step, server-side conversion from arbitrary modern HTML to native DOCX without Microsoft Word, the documented tools here do not prove that capability. Either accept the legacy-.doc-plus-Word workflow, generate the document structure programmatically, or select a separate converter whose native-DOCX support is explicitly documented and verify it against your templates.
Authentication, assets, and repeatable jobs
Authenticated pages
A browser must be authenticated before it can render a private URL. In a controlled application, load the page through a session-aware browser and keep credentials out of the HTML. Do not put bearer tokens in public URLs or generated filenames.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallRank #3
Fonts and external resources
Pin the fonts and assets needed for the export. A conversion worker with no network access, an expired certificate, or a blocked host can produce a technically valid PDF or image with missing content. For repeatability, prefer assets your worker can resolve consistently.
Resource cleanup
Always close Ferrum’s browser in an ensure block. Browser processes consume considerably more memory than a Ruby-only transformation; leaking one per request will eventually exhaust a worker. Reuse a controlled browser only when you can isolate sessions and reset state between jobs.
Troubleshooting common failures
“Browser executable not found”
Cause: the gem is installed but Puppeteer/Chromium is not installed or is not visible to the process. Fix: install the browser runtime required by Grover or Ferrum’s current documentation and configure the executable path for the deployment user.
The PDF is blank or missing late content
Cause: capture happened before JavaScript, fonts, or images finished loading. Fix: wait for a page-specific readiness condition, verify the URL from the worker, and make asynchronous rendering complete before calling to_pdf or pdf.
Images work locally but not in production
Cause: relative paths, private asset hosts, DNS differences, or blocked outbound traffic. Fix: use absolute URLs or embedded data, allow the worker to reach the asset host, and log the final HTML and browser console/network errors for a failed job.
The screenshot is clipped
Cause: a viewport capture was used for a document that requires full-page capture, or a fixed element extends beyond the intended area. Fix: use Ferrum’s full-page option for a document image, or capture a specific selector/area and adjust the layout CSS.
Rank #4
DOCX formatting changes after Save As
Cause: the HTML-to-Word conversion passed through legacy .doc and Word’s own layout engine. Fix: simplify unsupported CSS, inspect the intermediate document, and compare the final DOCX against a representative template. Treat the Word save as a conversion step, not a byte-for-byte browser rendering.
Performance, reliability, and cost considerations
- Startup: launching Chromium per request adds latency. A worker queue can absorb bursts, but browser reuse must isolate cookies and page state.
- Memory: full-page, high-scale screenshots and large PDFs need more memory than viewport captures. Limit concurrent browser jobs according to the worker’s actual memory budget.
- Reliability: record the input URL or template version, browser errors, wait condition, output format, and output byte size. A zero-byte or unexpectedly tiny artifact should fail the job.
- Cost: self-hosted Grover and Ferrum shift cost to Ruby workers, Chromium processes, storage, and maintenance. The Word-based DOCX route additionally requires a licensed, automatable Word environment where that is permitted.
- Validation: test long pages, missing images, web fonts, right-to-left text, tables crossing page boundaries, and JavaScript-generated content before committing to a format.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF. Before capture it accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for the complete parameter set.
Ruby
require "net/http"
require "uri"
uri = URI("https://api.screenshotneo.com/v1/shot")
uri.query = URI.encode_www_form(access_key: "YOUR_API_KEY", url: "https://stripe.com")
response = Net::HTTP.get_response(uri)
raise "Screenshot failed: #{response.code}" unless response.is_a?(Net::HTTPSuccess)
File.binwrite("shot.webp", response.body)
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' }); const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo also supports full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets and arbitrary viewports, retina scale, PDF paper size/margins/landscape/page ranges, custom CSS and JavaScript, click-before-capture, hidden selectors, waits for selectors/delays/network idle, request and resource blocking, custom headers/cookies/user agents/Authorization, timezone and geolocation, transparent backgrounds, image resizing, chosen cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work.
Every plan includes every feature. The current prices are:
| Plan | Allowance | Price |
|---|---|---|
| Free | 1,000 shots/month | $0, no card |
| Starter | 3,000 shots | $5 |
| Growth | 15,000 shots | $15 |
| Pro | 60,000 shots | $39 |
| Scale | 250,000 shots | $99 |
| Business | 1,000,000 shots | $249 |
Yearly billing provides two months free. If you want screenshots or PDFs without maintaining Chromium workers, create a free ScreenshotNeo account with 1,000 shots a month and no card.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →FAQ
Can Grover create a DOCX directly?
No. The documented Grover outputs are PDF, PNG, and JPEG. The documented HTML-to-Word route creates .doc and uses Microsoft Word to save .docx.
Best Value
Is Prawn interchangeable with Ferrum?
No. Prawn draws a PDF through Ruby APIs. Ferrum renders HTML in a browser; use the latter when HTML and CSS fidelity are the requirement.
Can I treat ruby-docx as an HTML import library?
No. Its documented role is reading and working with existing DOCX structures and rendering paragraphs as HTML.
Which output should be the canonical artifact?
Use PDF for fixed-layout delivery, a screenshot for visual snapshots, and DOCX only when recipients must edit the document in Word and you can accept the intermediate conversion workflow.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Frequently Asked Questions
Can Grover create a DOCX directly?
No. Grover’s documented outputs are PDF, PNG, and JPEG; the documented HTML-to-Word workflow creates a legacy .doc and uses Microsoft Word to save .docx.
Is Prawn interchangeable with Ferrum?
No. Prawn is a programmatic PDF drawing library, while Ferrum renders HTML through a browser.
Can ruby-docx import arbitrary HTML?
Its documented role is working with existing DOCX structures and rendering paragraphs as HTML, not arbitrary HTML-to-DOCX conversion.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

