Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use Ferrum when you need Ruby to control a local Chrome or Chromium browser. It can open a URL, wait for dynamic content, and save PNG, JPEG, or WebP screenshots, including full-page, selector, and rectangular-area captures. For Capybara suites, Cuprite provides a Ferrum-based driver. If you would rather avoid browser installation and maintenance, a hosted renderer such as ScreenshotNeo accepts one HTTP request and can return an image or PDF.
Choose the rendering approach first
Your choice depends mainly on where Chrome runs and how much control you need.
| Approach | Best fit | What you operate |
|---|---|---|
| Ferrum | Ruby scripts, jobs, and applications needing direct browser control | Chrome or Chromium and its runtime dependencies |
| Cuprite | Capybara feature and system tests | Chrome or Chromium through Ferrum |
| FerrumPdf | Ruby workflows that render HTML or URLs to PDF or images | Its documented Ruby rendering stack |
| Hosted HTML-to-image API | Deployments where you do not want a browser in each worker | API credentials, request handling, and data-transfer policy |
The documentation for Ferrum and its screenshot implementation is version-sensitive. Pin the gem and verify option names against the branch or release you deploy.
Capture a website with Ferrum
Prerequisites
- Ruby and the Ferrum gem.
- A Chrome or Chromium binary available in
PATH, or the browser path configured using Ferrum’s documented option. - Permission for the target site and network access from the machine running the script.
Ferrum communicates with Chrome over the Chrome DevTools Protocol; it does not require Selenium, WebDriver, or ChromeDriver. A minimal script is:
#1 Best Overall
require "ferrum"
browser = Ferrum::Browser.new
browser.go_to("https://example.com")
browser.screenshot(path: "example.png")
browser.quit
The browser opens the page, captures the current viewport, and writes a PNG. Always close the browser in production code, including when navigation or capture raises an exception:
require "ferrum"
browser = Ferrum::Browser.new
begin
browser.go_to("https://example.com")
browser.screenshot(path: "example.webp", format: :webp)
ensure
browser.quit
end
Wait for JavaScript and images
A navigation response does not guarantee that a single-page application has finished rendering. Wait for a meaningful selector, or use a controlled delay when no stable selector exists:
browser.go_to("https://example.com/dashboard")
browser.at_css("[data-page-ready]")
browser.screenshot(path: "dashboard.png", full: true)
For pages that load images lazily, scroll or use the page’s own readiness signal before requesting a full capture. A full-page screenshot is different from a viewport screenshot: it includes the document’s full scrollable height, while the default captures only the visible viewport.
Free tools Windows power users keep installed
One-click scans. No signup required.
Ferrum screenshot options
Ferrum’s implementation documents PNG, JPEG/JPG, and WebP output. It also supports viewport and full-page captures, CSS-selector or rectangular-area captures, scaling, background color, writing directly to a file, and returning Base64 data.
Output formats and scale
browser.screenshot(path: "page.jpg", format: :jpeg, quality: 85)
browser.screenshot(path: "page.webp", format: :webp, scale: 2)
Use a higher scale for retina-style assets, but expect larger files and more memory use. JPEG quality applies to lossy JPEG output; PNG is lossless and WebP can be used when your consumer supports it.
Rank #2
Full page, selector, and area captures
# Entire document
browser.screenshot(path: "full.png", full: true)
# One element identified by CSS selector
browser.screenshot(path: "hero.png", selector: ".hero")
# A rectangular region (coordinates are page pixels)
browser.screenshot(path: "region.png", area: { x: 0, y: 0, width: 800, height: 600 })
Selector capture is useful for cards, invoices, and test fixtures. Make sure the selector resolves to the intended element and that fonts and images have finished loading.
Backgrounds and Base64
data = browser.screenshot(format: :png, encoding: :base64, background_color: "#ffffff")
File.binwrite("page.b64", data)
Check the installed Ferrum version for the exact return encoding and option spelling before relying on Base64 in an API response.
Recommended Free Tools
Convert an HTML string to an image
To render HTML rather than a public URL, create a page in the browser and set its document content. A data URL is simple for small, self-contained markup:
require "ferrum"
require "cgi"
html = <<~HTML
<!doctype html>
<html><head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>body{font-family:system-ui;margin:32px} .card{padding:24px;border:1px solid #ddd}</style>
</head><body>
<div class="card"><h1>Invoice</h1><p>Rendered by Ruby</p></div>
</body></html>
HTML
browser = Ferrum::Browser.new
begin
browser.go_to("data:text/html,#{CGI.escape(html)}")
browser.screenshot(path: "invoice.png", selector: ".card")
ensure
browser.quit
end
For larger documents, serve the HTML from a local route so relative CSS, fonts, and images resolve normally. External resources may be blocked by network policy, authentication, CORS behavior, or the target server.
Generate a PDF instead of an image
Ferrum exposes PDF generation as a separate method. A PDF is a paginated document, not a screenshot image, so choose it when selectable text, print layout, or paper dimensions matter.
Rank #3
browser.go_to("https://example.com/invoice")
browser.pdf(path: "invoice.pdf", format: "A4", landscape: false)
Page size, margins, and other print options vary by Ferrum version; consult the versioned API documentation before shipping a print pipeline.
Windows 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 reinstallCrashes, 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 minuteUse Cuprite with Capybara
Cuprite is a pure-Ruby Capybara driver built on Ferrum. It is a natural choice for system or feature tests that already use Capybara:
require "capybara"
require "capybara/cuprite"
Capybara.register_driver(:cuprite) do |app|
Capybara::Cuprite::Driver.new(app, js_errors: true)
end
Capybara.default_driver = :cuprite
session = Capybara::Session.new(:cuprite)
session.visit("https://example.com")
File.binwrite("capybara.png", session.save_page_screenshot(nil))
Cuprite’s README documents a Base64 screenshot method and warns that some Selenium conventions behave differently. Audit any Selenium-specific waits, driver calls, and browser options during migration rather than assuming drop-in compatibility.
Other Ruby rendering options
FerrumPdf
FerrumPdf is described as a Ruby option for rendering HTML or a URL to PDF and screenshots. The available documentation establishes that use case, but not comparative reliability, maintenance, or performance against Ferrum. Evaluate it against your exact templates and deployment environment.
Hosted Ruby clients
The official Ruby client for the html2img service documents URL screenshots, HTML rendering, full-page captures, selector capture, and PDF output. A hosted client moves browser installation out of your workers, but review its current authentication, retention, pricing, latency, and privacy terms before sending sensitive HTML.
Rank #4
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. It accepts one GET request and returns PNG, JPEG, WebP, or PDF. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result.
Use the documented request from Ruby (see the ScreenshotNeo API documentation):
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 "HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess)
File.binwrite("shot.webp", response.body)
The same endpoint supports full-page and element capture, dark mode, device presets or custom viewports, retina scale, PDF paper settings, custom CSS and JavaScript, clicks, waits, blocked resources, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
Plans include 1,000 free shots per month with no card; Starter is $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to start.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Troubleshooting Ruby captures
Chrome cannot be found
Install Chrome or Chromium and confirm the executable is on PATH. In containers, install the browser and required shared libraries, or pass Ferrum’s documented browser path option.
The screenshot is blank or incomplete
Wait for a page-specific selector, increase the viewport, and confirm that the page’s JavaScript and external assets are reachable from the worker. For lazy images, trigger the page’s loading behavior before a full capture.
Best Value
A selector capture fails
Check that the selector exists after navigation, is unique, and is visible. Use a stable data-* attribute instead of a generated class name.
Fonts differ from development
Install the same fonts in every runtime, wait for web fonts to load, and avoid capturing before the font-loading promise resolves. Container images often lack desktop fonts.
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 errorsCapybara tests fail after switching from Selenium
Review Cuprite’s documented differences and replace Selenium-only driver calls with Capybara APIs or Ferrum-supported operations.
Requests hang
Set navigation and script timeouts, close browsers in an ensure block, and limit concurrency to the CPU and memory available. Reuse a browser only when isolation between jobs is acceptable.
Performance, reliability, and security decisions
- Reuse versus isolation: Reusing one browser reduces startup overhead; separate browser instances reduce cross-request state leakage.
- Concurrency: Each active page consumes memory. Measure your templates before increasing worker count.
- Determinism: Fix viewport, timezone, locale, fonts, and animations for stable visual tests.
- Network safety: Treat user-supplied URLs as SSRF input. Restrict private IP ranges, protocols, redirects, and credentials.
- Data handling: Local Ferrum keeps rendering in your environment. A hosted API sends the requested URL or HTML to a service, so inspect retention and compliance terms.
- Cost: Local rendering costs infrastructure and maintenance. Hosted pricing and cache behavior change over time; use the provider’s current terms and response billing headers.
FAQ
Can Ferrum take a screenshot without Selenium?
Yes. Ferrum controls Chrome or Chromium over CDP and does not require Selenium, WebDriver, or ChromeDriver.
Is a full-page screenshot the same as a PDF?
No. A full-page screenshot is an image of the document; PDF output follows print pagination and paper settings.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Which option fits a Capybara test suite?
Cuprite, because it is documented as a Capybara driver built on Ferrum.
Can I capture only one HTML element?
Yes. Ferrum supports CSS-selector capture, and ScreenshotNeo provides selector capture through its API.
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.

