Open-source project
rubycdp/ferrum avatar
rubycdp/ferrum

Ferrum: a Ruby CDP driver for Chrome without ChromeDriver

Headless Chrome Ruby API

2,059 stars170 forksRubyMIT

At a glance

What is it?
Ferrum talks to Chrome over the DevTools Protocol directly, so Ruby scripts skip Selenium and ChromeDriver entirely. It fits screenshot, scraping and browser-automation work where you want raw CDP access.
Who is it for?
Adopt Ferrum if you write Ruby and want CDP-level control over Chrome without a WebDriver layer, for screenshots, scraping, or scripted interaction. Do not adopt it if you need a cross-browser driver, since it targets Chrome and Chromium only, or if you expect the gem to manage the browser binary for you.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Ferrum removes: no Selenium, no ChromeDriver

Most Ruby browser automation goes through Capybara, which goes through Selenium, which goes through ChromeDriver. Each layer exists to keep one API working across browsers. Ferrum's README is explicit that it connects to the browser by the CDP protocol and that there is no Selenium, WebDriver or ChromeDriver dependency. The stated reason is that Chrome exposes capabilities WebDriver barely supports because WebDriver must stay consistent across browsers.

So the audience is narrow and specific: Ruby developers automating Chrome or Chromium who are willing to give up cross-browser portability in exchange for direct access to the DevTools Protocol. If your test suite must also run against Firefox or Safari, this is the wrong layer. If everything you automate is Chrome, the extra layers only add version-matching pain.

Ferrum is also a building block. The README names Cuprite, a pure Ruby Capybara driver built on Ferrum, and Vessel, a crawling framework built on Ferrum and Mechanize. That tells you where the project sits: below Capybara, not competing with it.

How Ferrum drives Chrome over CDP

The architecture is a Ruby client holding a CDP session against a browser process. A Ferrum::Browser instance launches or attaches to Chrome, and the README notes that Ferrum creates and maintains a default page inside the default_context of that browser instance. Every convenience method on the browser is really forwarded to that page.

The README calls creating pages manually the preferred style, and the reason is visible in the API: a page object carries the navigation, query and input methods, while the browser object owns the process and the contexts. Page queries return element objects with their own methods, so focus and typing chain off the element rather than the page. Evaluation is a separate channel: page.evaluate takes a JavaScript string and returns the value, which the README demonstrates by reading document.documentElement.offsetWidth and offsetHeight. Input is modelled as devices: the README shows a mouse object with move, down and up, chained to trace a 100x100 square. That chaining is the API's whole personality.

What is not documented in the README is the lifecycle of a CDP connection under failure. There is no rollback or reconnect story in the README text, and the docs site is where deeper customization is pointed to. Treat connection handling as something to verify against the docs for your version rather than something the README promises.

Installing Ferrum and taking a first screenshot

The README is direct about the browser binary: there is no official Chrome or Chromium package for Linux, and it warns against installing it that way because such packages are outdated or unofficial. Download Chrome or Chromium from the official sources. The binary should be in PATH or pointed at with BROWSER_PATH, and the README says you can also pass it to the browser instance as the :browser_path option described under Customization.

Add the gem to your Gemfile and run bundle install. The README gives exactly this line:

ruby
gem "ferrum"

With the gem installed and a Chrome binary reachable, the Quick Start is four lines. This navigates to a site, writes a PNG, and quits the browser:

ruby
browser = Ferrum::Browser.new
browser.go_to("https://google.com")
browser.screenshot(path: "google.png")
browser.quit

After running it you should find google.png in the working directory. If the binary is not on PATH and BROWSER_PATH is unset, the browser will not start; that is the first thing to check.

The README's preferred style creates a page explicitly, then queries and interacts with it. This example focuses the search input, types a query, presses Enter, and reads the first heading:

ruby
browser = Ferrum::Browser.new
page = browser.create_page
page.go_to("https://google.com")
input = page.at_xpath("//input[@name='q']")
input.focus.type("Ruby headless driver for Chrome", :Enter)
page.at_css("a > h3").text
browser.quit

Calling quit matters. Nothing in the README suggests the browser process is reaped for you when the script ends.

Evaluating JavaScript and scripting input devices

Two capabilities separate Ferrum from a thin navigation wrapper. The first is evaluate, which runs JavaScript in the page and returns the result to Ruby. The README returns an array of two numbers from a heredoc:

ruby
width, height = page.evaluate <<~JS
  [document.documentElement.offsetWidth,
   document.documentElement.offsetHeight]
JS

The README comments the result as [1024, 1931]. That value depends on the viewport, so treat it as an illustration of the return shape, not a fixed number.

The second is the mouse device. Input is expressed as coordinates and button state rather than as high-level gestures, which is what you want when a site reacts to pointer movement itself:

ruby
page.mouse
  .move(x: 0, y: 0)
  .down
  .move(x: 0, y: 100)
  .move(x: 100, y: 100)
  .move(x: 100, y: 0)
  .move(x: 0, y: 0)
  .up

That traces a square through four corners and releases the button. The cost of this style is that you own the geometry. There is no element-relative helper in the README, so if a layout shifts, your coordinates are wrong and the script fails silently rather than raising.

Where Ferrum is the wrong tool

Cross-browser testing is the clearest mismatch. Ferrum speaks CDP, which is Chrome's protocol. The README frames the missing WebDriver layer as an advantage precisely because CDP goes further than a cross-browser API can, and that same property means a Firefox or Safari target is out of scope.

The second limitation is operational: Ferrum does not install Chrome for you, and the README actively argues against distro packages. That makes the gem a poor fit for environments where you cannot control the browser binary, such as locked-down CI images that ship a vendor Chromium you are not allowed to replace. You need a binary in PATH, or BROWSER_PATH, or the :browser_path option.

The third is lifecycle discipline. The README examples all end with browser.quit, and there is no documented automatic cleanup. Long-running Ruby processes that create browsers per job will accumulate Chrome processes if quit is skipped on the error path. Wrap browser creation in a begin/ensure that calls quit, and treat that as your responsibility rather than the library's.

Finally, if you want a Capybara-style DSL with matchers and waiting semantics, Ferrum is one level too low. Cuprite exists for exactly that, and the README points to it.

Ferrum compared with Selenium and ChromeDriver in Ruby

The alternative most Ruby teams already have is Selenium WebDriver with ChromeDriver. The difference is architectural, not cosmetic. WebDriver is a W3C-standard protocol implemented by every browser vendor, so the same Ruby code runs against Chrome, Firefox and Safari by swapping the driver. ChromeDriver is a separate binary that must match your Chrome version, and version skew between the two is a recurring failure mode.

Ferrum removes both the driver binary and the standardization layer. It speaks CDP, which the README describes as allowing things WebDriver barely supports because WebDriver must stay consistent across browsers. In practice that means Ferrum can reach browser-level behaviour that has no WebDriver equivalent, and in exchange it has no cross-browser story and no standard to fall back on when Chrome changes.

A second alternative is Cuprite, which is not really a competitor. Cuprite is a Capybara driver built on Ferrum, so choosing Cuprite still means running Ferrum underneath. If your team already writes Capybara specs, Cuprite is the lower-friction path to the same CDP foundation. If you are writing plain Ruby scripts with no test framework, Ferrum directly is the shorter route.

Maintenance, licensing and upgrade cost

Ferrum is MIT licensed, which permits commercial and closed-source use with the usual requirement to keep the copyright notice. That is a permissive baseline and imposes no copyleft obligation on your application. This is a description of the licence text, not legal advice.

The last push to the repository was on 2026-09-08, and the most recent release listed is v0.18.0 from 2026-08-20. The release cadence before that was uneven: v0.17.2 landed on 2026-03-24 and v0.17.1 on 2025-05-11. The 0.x version number is the honest signal here. Minor versions can carry breaking changes, so pin the gem version in your Gemfile and read CHANGELOG.md before bumping.

Upgrade cost is dominated by Chrome, not by the gem. Because Ferrum drives the browser over CDP, a Chrome release that changes protocol behaviour can affect you even when the gem version is unchanged. The repository carries sig/ and rbs_collection files, so RBS type signatures ship with the project, and .rubocop.yml and .rspec indicate the project's own tooling. There is a docs/ directory and a separate documentation site at docs.rubycdp.com, which is where the README sends you for customization options such as :browser_path.

Editorial conclusion

Adopt Ferrum if you write Ruby and want CDP-level control over Chrome without a WebDriver layer, for screenshots, scraping, or scripted interaction. Do not adopt it if you need a cross-browser driver, since it targets Chrome and Chromium only, or if you expect the gem to manage the browser binary for you. Before committing, confirm that a Chrome or Chromium binary is on your PATH or reachable through BROWSER_PATH, and check the docs site for the version of the customization options your release supports. The project is MIT licensed and its last push was on 2026-09-08.

Frequently asked questions

How do I install Ferrum?

Add gem "ferrum" to your Gemfile and run bundle install. You also need a Chrome or Chromium binary available in PATH or pointed to with BROWSER_PATH, since the README warns against installing Chrome from Linux distribution packages.

How do I use Ferrum to take a screenshot?

The README's Quick Start creates a Ferrum::Browser, calls go_to on a URL, then calls screenshot with a path such as "google.png", and finishes with browser.quit.

Is there a free edition of Ferrum?

The gem is published as open source under the MIT License, and the README describes no paid tier or separate edition. It is installed from RubyGems through your Gemfile.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. rubycdp/ferrum on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rubycdp-ferrum.svg)](https://hysenlabs.com/projects/rubycdp-ferrum)