Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Ruby can turn HTML into PNG or JPEG with a local renderer or a hosted browser service. For modern CSS and JavaScript, use Grover or Ferrum with Chrome; for an existing wkhtmltoimage workflow, use IMGKit; to avoid maintaining a local browser, call a hosted service such as ScreenshotNeo. The right choice depends on whether you are rendering trusted HTML or a URL, how much browser control you need, and what your deployment can support.

Choose a Ruby HTML-to-image approach

Option Renderer and outputs Best fit Operational trade-off
Grover Puppeteer/Chromium; PDF, PNG, JPEG Modern browser rendering with a Ruby interface Requires Chromium/Puppeteer installation and lifecycle management
Ferrum Chrome via DevTools Protocol; PNG, JPEG/JPG, WebP Direct control of Chrome screenshots and capture geometry You manage a Chrome session and its deployment
IMGKit wkhtmltoimage; JPG, JPEG, PNG Existing wkhtmltoimage workflows or relatively simple HTML/CSS Validate required CSS and JavaScript behavior against its renderer
ScreenshotNeo Hosted browser capture; PNG, JPEG, WebP, or PDF Ruby code that should avoid local browser setup Requires a network request and API key

For a new project that depends on current browser behavior, start by evaluating Grover or Ferrum. Choose IMGKit when compatibility with an existing wkhtmltoimage installation matters more than modern browser fidelity. If operating Chromium is the unwanted part, a hosted API moves that work off your application server.

Render HTML with Grover and Chromium

Grover wraps Puppeteer/Chromium to render HTML as PDF, PNG, or JPEG. RubyGems lists Grover 1.2.10, released April 2, 2026, and a required Ruby range of >= 3.0.0 and < 3.5.0; check the current listing for changes before adopting it: RubyGems: Grover.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Install and capture

Add the gem to your project:

bundle add grover

A basic capture can render an HTML string and write the result to a PNG:

#1 Best Overall
require "grover"

html = <<~HTML
  <!doctype html>
  <html>
    <head>
      <meta charset="utf-8">
      <style>
        body { font: 24px sans-serif; padding: 32px; }
      </style>
    </head>
    <body><h1>Ruby screenshot</h1></body>
  </html>
HTML

png = Grover.new(html, format: "png").to_png
File.binwrite("shot.png", png)

Grover’s documented output formats include PDF, PNG, and JPEG. Consult its current documentation for exact option names and setup instructions for your chosen environment; browser packaging and executable paths can differ between development and deployment.

When Grover is a good fit

  • Your page relies on browser-grade CSS or JavaScript.
  • You need PDF as well as raster output from the same rendering approach.
  • You can install and operate the Chromium/Puppeteer dependencies in each runtime environment.

For Rails views, render the view to HTML first, then pass that rendered document or a reachable URL to your capture flow. Ensure stylesheets, fonts, and images resolve in the rendering context; a template that works in a logged-in browser may not be accessible to a separate browser process without session state.

Use Ferrum for direct Chrome screenshot control

Ferrum drives Chrome through the DevTools Protocol. Its screenshot implementation supports PNG, JPEG, JPG, and WebP, with viewport and full-page capture, selector or rectangular-area capture, quality, scale, background color, file output, and base64 output. See the project documentation for the current API: Ferrum on GitHub.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Install and capture a page

bundle add ferrum

A minimal URL screenshot using Ferrum’s browser page API looks like this:

require "ferrum"

browser = Ferrum::Browser.new
begin
  page = browser.create_page
  page.go_to("https://example.com")
  page.screenshot(path: "shot.png", format: :png)
ensure
  browser.quit
end

Check the installed Ferrum version’s documentation for precise method signatures and options. The key operational pattern is to close the browser in an ensure block so exceptions do not leave Chrome processes running.

Choose the capture boundary deliberately

  • Viewport: captures what fits in the configured browser window; set the viewport before navigation or capture if exact dimensions matter.
  • Full page: useful for long documents, but may produce a very tall image and consume more memory.
  • Selector or area: limits the image to a particular element or rectangle; check that the target exists and is visible before capture.
  • Scale and quality: use higher scale for sharper output at larger file sizes; quality matters for lossy formats such as JPEG.
  • Background: set an explicit color when transparency or the browser’s default background would be ambiguous.

Ferrum is a strong choice when you want Ruby to control a persistent Chrome session and need capture geometry or output options. You still need to account for Chrome installation, process cleanup, memory, and concurrency in your deployment.

Use IMGKit when wkhtmltoimage fits your workflow

IMGKit wraps wkhtmltoimage. Its documentation describes the project as making JPGs with plain HTML and CSS, and the API accepts HTML, a URL, or a file; it provides to_img and to_file methods for JPG, JPEG, and PNG output. See IMGKit documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Install and write an image

Install both the Ruby gem and the wkhtmltoimage executable using the package method appropriate to your operating system. Then:

require "imgkit"

html = "<html><body><h1>Ruby screenshot</h1></body></html>"
kit = IMGKit.new(html, format: "png")
File.binwrite("shot.png", kit.to_img)

You can also give IMGKit a URL or file instead of an HTML string. Confirm executable discovery in the target container or server, and test any CSS, web fonts, or JavaScript behavior your page depends on. The supplied project description establishes wkhtmltoimage as the backend; do not assume its rendering behavior is interchangeable with current Chrome.

Set rendering inputs and output intentionally

Input: HTML string, application view, or URL

  • HTML string: convenient for generated cards, receipts, and reports. Escape user-controlled content and avoid concatenating untrusted data into executable markup or scripts.
  • Rails view: render the view with the right locals and assets, then make sure the capture process can access those resources. Authentication and host-relative asset paths often need explicit handling.
  • Public URL: simplest when the page is already reachable. Private pages need an authenticated browser session or supported headers/cookies; do not expose credentials in a public screenshot URL.

Wait for the page to be ready

A screenshot taken immediately after navigation can miss asynchronous content. Wait for a stable selector, a deliberate delay, or network activity to settle when your renderer supports it. Make sure web fonts and images have loaded, and give JavaScript-driven charts time to finish. A fixed delay is simple but can waste time on fast pages and still fail on slow ones; a readiness condition is generally more reliable.

Pick the image format

  • PNG: lossless, usually a good default for text, charts, and interface details.
  • JPEG: lossy and often suitable for photographic content when smaller files matter.
  • WebP: Ferrum and ScreenshotNeo support it; verify support across the tools that will consume the image.
  • PDF: choose a PDF-capable renderer such as Grover when the desired output is a document rather than a raster screenshot.

Or skip the browser setup

ScreenshotNeo accepts a URL and returns an image or PDF from one GET request. Its API can remove cookie/consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. It also has an MCP server for AI agents, and includes 1,000 shots per month free without a card; paid plans start at $5 for 3,000 shots.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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 authentication, formats, and capture parameters. Other available controls include full-page capture with lazy images loaded, CSS selector capture, dark mode, device presets and custom viewports, retina scale, PDF page and margin settings, custom CSS or JavaScript, click-before-capture, wait conditions, request blocking, headers, cookies, user agent, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching, signed image links, async jobs with signed webhooks, bulk capture of 100 URLs per call, usage API, and OpenAPI specification. Parameter names used by other screenshot APIs also work to ease migration.

For Ruby, use the standard HTTP client gem:

require "net/http"
require "uri"

uri = URI("https://api.screenshotneo.com/v1/shot")
uri.query = URI.encode_www_form(access_key: ENV.fetch("SCREENSHOTNEO_API_KEY"), url: "https://stripe.com")
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true, read_timeout: 90) do |http|
  http.get(uri.request_uri)
end
raise "Screenshot request failed: #{response.code}" unless response.is_a?(Net::HTTPSuccess)
File.binwrite("shot.webp", response.body)

Keep the API key in an environment variable or secret manager, not source control. For any HTTP screenshot service, handle non-success responses and set a timeout; a response body may contain an error rather than image bytes if a request fails. Visit ScreenshotNeo to compare the service details, then sign up free for 1,000 screenshots a month with no card.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability, and cost trade-offs

  • Local Chromium: Grover and Ferrum avoid a per-capture network round trip to a rendering provider, but your application must provision browser binaries, memory, process limits, and concurrency. Reuse browser processes where the library’s lifecycle model permits, and close them reliably.
  • wkhtmltoimage: IMGKit may be practical where the executable is already deployed. Test representative pages rather than assuming modern CSS or script behavior matches Chrome.
  • Hosted rendering: reduces local browser maintenance, but depends on network availability and the provider’s limits, policies, and pricing. Review current terms and privacy requirements before sending sensitive HTML or URLs.
  • Output size: full-page images, high viewport dimensions, and high scale increase processing and memory needs. Prefer the smallest dimensions and format that meet the consumer’s requirements.
  • Concurrency: impose queue limits and per-capture timeouts so slow or heavy pages cannot exhaust application resources or tie up workers indefinitely.

No independent performance benchmark establishes a universal fastest Ruby option. Measure with your real pages, target deployment, and concurrency rather than relying on generic speed claims.

Troubleshooting common capture failures

Chrome or wkhtmltoimage cannot be found

The gem may be installed while the external renderer is absent or outside the process PATH. Install the required executable in the runtime image and verify its path under the same user that runs the Ruby application.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The screenshot is blank or missing dynamic content

The page may have been captured before rendering completed, or the capture browser may not be able to reach assets or APIs. Wait for a meaningful selector or loaded state, inspect the page’s network access, and ensure fonts and images are reachable from the capture environment.

CSS or JavaScript looks different than expected

Different rendering engines do not guarantee identical behavior. If modern browser layout or script execution is essential, validate with Chromium via Grover or Ferrum; for IMGKit, confirm the page works with its wkhtmltoimage backend.

Only part of the page appears

A viewport screenshot is bounded by browser dimensions. Set a larger viewport or select full-page capture. For selector captures, ensure the element is present, visible, and not inside an inaccessible frame.

The output file is corrupt or not an image

Check that the request succeeded before writing its body as an image. For hosted calls, inspect the HTTP status and response headers; for local libraries, surface exceptions and confirm the requested format is supported.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Workers accumulate or captures stall

Use ensure/finally-style cleanup for local browser processes, set navigation and read timeouts, and limit concurrent jobs. If a hosted request stalls, set a client timeout and treat timeout responses as failures rather than saving partial data.

Frequently asked questions

Can Ruby convert an HTML string without saving it first?

Yes. Grover, IMGKit, and ScreenshotNeo’s hosted workflow accept HTML or URL-based inputs as supported by their respective interfaces. For a local Ruby library, render the HTML string directly; for the hosted ScreenshotNeo endpoint shown here, the example captures a URL.

Which approach can produce a PDF as well as an image?

Grover supports PDF, PNG, and JPEG output. ScreenshotNeo also returns PDF, with PDF-specific controls available through its API.

Should I capture private pages with a hosted API?

Only after reviewing the provider’s privacy and data-handling terms and deciding that sending the page URL or content is acceptable. For highly sensitive content, a local renderer may be preferable.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.