Ferrum: Driving Chrome from Ruby over CDP, Without ChromeDriver
Headless Chrome Ruby API
At a glance
- What is it?
- Ferrum is an MIT-licensed Ruby library that talks to Chrome or Chromium directly over the Chrome DevTools Protocol. It removes the WebDriver layer entirely, which buys protocol-level control and costs you the portability that layer provided.
- Who is it for?
- Adopt Ferrum if you are automating Chrome or Chromium from Ruby and need CDP features that WebDriver does not expose, such as synthetic mouse paths or direct JavaScript evaluation, and you are willing to own Chrome installation and version pinning yourself. Do not adopt it if your test suite must also run against Firefox, Safari or WebKit, because the README frames the design around a single engine's protocol and Cuprite is the Capybara path for that same engine only.
- 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 8 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 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The WebDriver layer Ferrum removes, and who feels its absence
WebDriver was designed to present one interface across several browsers, so its command set is the intersection of what those engines can do. The README states the emphasis was placed on the raw CDP protocol "because Chrome allows you to do so many things that are barely supported by WebDriver because it should have consistent design with other browsers." That sentence is the whole pitch. If you have ever wanted a synthetic mouse path, a direct JavaScript evaluation, or a protocol call that has no WebDriver equivalent, you have hit the ceiling Ferrum is aimed at. The audience is Ruby developers doing browser automation against a single engine: scraping, screenshot pipelines, and test suites that only need to run in Chrome or Chromium. It is not a general browser automation layer and does not pretend to be one.
How the CDP connection and the default page fit together
Ferrum connects to the browser over the Chrome DevTools Protocol and carries no Selenium, WebDriver or ChromeDriver dependency. The object model has two levels. A Ferrum::Browser instance owns the connection and, per the README, "creates and maintains a default page for you, in fact all the methods above are sent to the page instance that is created in the default_context of the browser instance." So browser.go_to and browser.screenshot are conveniences that forward to that implicit page. The README calls creating a page manually the preferred style: browser.create_page returns an explicit page object, and go_to, at_xpath, at_css, evaluate and mouse hang off it. That distinction matters in any code that keeps more than one tab open, because browser-level calls always land on the default page rather than the one you think you are driving.
Mouse paths and JavaScript evaluation from Ruby
Two examples in the README show what the CDP route buys. The first is page.evaluate with a heredoc returning an array, in the documented case document.documentElement.offsetWidth and offsetHeight, which comes back to Ruby as [1024, 1931]. The second is the mouse API: page.mouse.move(x: 0, y: 0).down then a chain of move calls tracing a 100x100 square and finally .up. That chain is a sequence of discrete pointer events with coordinates you choose, not a click on an element the driver located. It is the kind of input a canvas app or a drag interaction needs, and it is the kind of thing that is awkward to express through element-based WebDriver commands. Note that the README gives no timing or interpolation parameters for the path; it documents the calls, not how the browser paces them.
Installing the gem and pointing it at a Chrome binary
The Gemfile line is gem "ferrum", followed by bundle install. The browser is the part with opinions. The README warns against installing Chrome or Chromium from a Linux distribution package, calling such packages "either outdated or unofficial, both are bad", and directs you to download from the official Chrome or Chromium sources instead. The binary must then be discoverable: the README says it "should be in the PATH or BROWSER_PATH and you can pass it as an option to browser instance see :browser_path in Customization." So there are three ways to resolve the executable, and :browser_path is the explicit one. The README does not list the rest of the option set, only pointing at the Customization page on docs.rubycdp.com, which is where headful mode and other settings are documented.
The Chrome version you ship is now your problem
Removing ChromeDriver removes a compatibility guarantee. ChromeDriver is versioned against Chrome and refuses to run on a mismatch, which is annoying but loud. Ferrum speaks CDP directly, so when Chrome changes or drops a protocol domain, the failure surfaces wherever the gem happens to call it, and the README does not describe a version compatibility matrix or a minimum supported Chrome release. The install guidance compounds this: by telling you to avoid distribution packages and fetch Chrome yourself, the project hands you the upgrade cadence. In a container you are now pinning a Chrome build and a gem version together, and the gem's release history shows that pairing is not static. Treat the browser version as a dependency you test, not an ambient detail.
Cuprite for Capybara, Selenium for more than one engine
The README points to Cuprite, a pure Ruby Capybara driver built on Ferrum, and to Vessel, a crawling framework built on Ferrum and Mechanize. Cuprite is the answer if you already have Capybara specs: you keep the Capybara DSL and Ferrum stays the transport, but you are still locked to Chrome and Chromium. Selenium WebDriver is the real alternative when engine coverage is the requirement. It routes commands through the WebDriver protocol and a per-browser driver binary, so the same suite can target Firefox, Safari or WebKit, at the cost of the protocol-level access Ferrum exposes. The choice is not speed or quality, it is scope: one engine with full protocol reach, or several engines with a common subset. Ferrum only wins the first case.
Maintenance, upgrades and the MIT licence
The gem ships under the MIT License, which permits commercial and closed-source use and requires the licence text and copyright notice to be preserved. That is a permissive baseline, not legal advice; check it against your own distribution model. On maintenance, the repository is not archived and the release cadence is irregular rather than dormant: v0.17.1 in May 2025, v0.17.2 in March 2026, v0.18.0 in August 2026. The jump to 0.18.0 is the kind of minor bump that can carry behaviour changes, so read the release notes before upgrading rather than assuming a patch-level risk. The README also documents the maintainer workflow with bundle exec rake test, bin/console and bundle exec rake release, which tells you the test suite is the contract you inherit if you fork or patch.
Editorial conclusion
Adopt Ferrum if you are automating Chrome or Chromium from Ruby and need CDP features that WebDriver does not expose, such as synthetic mouse paths or direct JavaScript evaluation, and you are willing to own Chrome installation and version pinning yourself. Do not adopt it if your test suite must also run against Firefox, Safari or WebKit, because the README frames the design around a single engine's protocol and Cuprite is the Capybara path for that same engine only. Before committing, check that the Chrome binary resolves through PATH or BROWSER_PATH, that the :browser_path option matches your install, and that your Chrome version is one the gem's CDP calls still support after upgrading.
Community notes