Open-source project
rubycdp/ferrum avatar
rubycdp/ferrum

Ferrum: a Ruby Chrome API whose first example is the form it tells you not to use

Headless Chrome Ruby API

2,071 stars179 forksRubyMIT

At a glance

What is it?
Ferrum drives Chrome over the DevTools protocol with no Selenium, WebDriver or ChromeDriver in the stack, and it ships RBS type signatures that the page never mentions. The parts worth reading are the quick start ordering, an example whose expected output is a live search result, and a Linux install note that runs two sentences together.
Who is it for?
Ferrum is the layer to reach for when a Ruby project needs browser automation and WebDriver's cross-browser consistency is the wrong trade, and the two projects built on it show that the bet has paid off more than once. Cuprite gives Capybara users a pure Ruby driver, and Vessel adds crawling on top of Ferrum and Mechanize.
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 received new commits within the last day.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

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

From daily snapshots

Star history

  • rubycdp/ferrum2,071 ★ · +29
Star history
Repository2026-09-112026-11-14
rubycdp/ferrum2k2.1k

29 Stars in the last 64 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The first example is the default-page form the next paragraph rejects

The quick start opens with the shortest possible program, creating a browser, navigating, saving a screenshot and quitting:

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

The paragraph immediately after it explains that Ferrum creates and maintains a default page for you, that the methods in that first example are all sent to the page instance created in the browser's default context, and that you can interact with a page created manually and that this is preferred. So the entry point teaches the form the project then tells you to avoid, and the preferred version is the second example, which calls the browser's create_page method and drives that page object directly. The difference matters beyond style. The default page is shared state that Ferrum manages on your behalf, and every subsequent call to the browser level quietly targets it.

An example asserts a live search result and a fixed viewport measurement

Two of the four quick start snippets end with a comment stating what the code returns, and both expectations are fragile. The second searches that engine for a phrase, reads the text of the first heading link, and the comment says the result is the title of this project's own GitHub page:

ruby
page.at_css("a > h3").text # => "rubycdp/ferrum: Ruby Chrome/Chromium driver - GitHub"

That string is this repository's description as one search engine happened to render it on the day the example was written. Change the repository description, or change the ranking, and the assertion is wrong while the code stays correct. The third snippet evaluates JavaScript in the page and the comment gives the answer as a width and a height pair, which is a property of whatever viewport the reader's machine happens to have. Both are the kind of comment a reader copies into a test and then cannot make pass on a different machine. The fourth snippet, tracing a square with chained mouse movements, is the only one with an outcome that depends only on the code.

No WebDriver in the stack, and the reason is stated plainly

The case for a raw protocol client is made in one paragraph and it is a design argument rather than a feature list. Ferrum connects to the browser over the CDP protocol and carries no Selenium, WebDriver or ChromeDriver dependency. The reason given is that Chrome permits a great many things that WebDriver barely supports, because WebDriver has to keep one consistent design across browsers. That is the whole thesis: the library is more capable on Chrome and gives up cross-browser portability, which is the right trade for a project whose stated dependency is Ruby and Chrome or Chromium and nothing else. Two higher-level projects sit on top of it and make the trade visible. Cuprite is a pure Ruby driver for Capybara, so the familiar test DSL runs on Ferrum. Vessel is a web crawling framework built on Ferrum and Mechanize, so the fetching layer and the browser layer are separate.

The Linux install note is two sentences run together, and the advice is negative

The install section opens with an instruction rather than a command, and the instruction is a prohibition. There is no official Chrome or Chromium package for Linux, the page says, and you should not install it that way because such a package is either outdated or unofficial and both are bad. Download it from the official source instead. The rest is a requirement about the binary: it should be on the PATH or in BROWSER_PATH, and it can also be passed as an option to the browser instance, with the browser_path option documented in the customization section. Two things are worth flagging. The first sentence and the second are joined without punctuation, so the whole caution reads as one run-on line, which is a small thing that makes the guidance easier to skim past than it deserves. And the negative instruction is the only thing a Linux user is told, with no version, no distro and no headless dependency noted for a machine that is only ever going to run a test suite.

The gem ships RBS signatures that the page never mentions

The repository layout says more about how the project is maintained than the readme does. There is a sig directory, a collection definition and a lock file for that collection, which together mean the gem carries RBS type signatures for its own API and pins the signatures it depends on from elsewhere. Next to that sit a Rubocop configuration for linting, a documentation options file and a document manifest for the generated API docs, a spec directory with its own options file, and a changelog. None of this appears in the readme. The readme's development section is four sentences: run the dependency install, run the test task, use the console script for an interactive prompt, and to release, edit the version number in version.rb and run the release task, which creates a tag, pushes the commits and the tag, and publishes the built gem. There is a devcontainer configuration as well, so an editor-ready environment is defined even though the readme does not say so.

Release is a manual version edit followed by one rake task

The publishing path is described in prose rather than commands, and it is worth reading for what it implies about versioning. To release a new version you update the version number in version.rb, which is a hand edit in a source file, and then run the release task. That task creates a git tag for the version, pushes the commits and the tag, and pushes the built gem to the gem server. So there is no automated bump, no version derived from the changelog, and no dry run described for the part of the process that pushes to two different remotes. The recent tags give a sense of the cadence: 0.17.1 in May 2025, 0.17.2 in March 2026, and 0.18.0 in August 2026, with the last commit after that in late September. All three release entries carry the same name as their tag, so the changelog file in the repository is the only place the substance of a release is written down.

Headless by default, with a headful mode available and nothing in between

The runtime configuration is described in one sentence: Ferrum runs headless by default and can be configured to run headful. Everything else about launching the browser lives off the repository, in the customization page of the external documentation site. That site is where the quick start, the customization options including the browser path option, and the API reference live, and it is a separate host from the project homepage, so there are two documentation domains in play for one gem. The readme covers install, four code snippets, the development loop, contributing and the licence, and defers everything else. For a library at this level that is a defensible choice, since the example code and the generated API docs cover the surface, but it does mean the readme alone will not tell you what the options are or how they interact.

Editorial conclusion

Ferrum is the layer to reach for when a Ruby project needs browser automation and WebDriver's cross-browser consistency is the wrong trade, and the two projects built on it show that the bet has paid off more than once. Cuprite gives Capybara users a pure Ruby driver, and Vessel adds crawling on top of Ferrum and Mechanize. The library itself is conservative in the right ways: one transport, no driver binaries to keep in step with the browser, type signatures in the gem, and a maintained changelog. What it is not is a finished tutorial. Three things to know before you write code against it. That the quick start opens with the default-page form and immediately tells you that creating a page yourself is preferred, so copy the second example rather than the first. That the examples embed live expected output, a GitHub page title returned by a search and a viewport measurement, so neither is a stable expectation. And that the documentation lives on a separate site rather than in the repository, so the readme gives you an install, four snippets and two sentences about releasing.

Frequently asked questions

Does Ferrum need a WebDriver or ChromeDriver dependency?

No. Ferrum connects to the browser over the CDP protocol directly, and the page states there is no Selenium, WebDriver or ChromeDriver dependency. The stated reason is that Chrome allows a great many things WebDriver barely supports, because WebDriver must keep one consistent design across browsers.

How do I install Chrome for Ferrum on Linux?

The page says not to install it from a Linux package, because such a package is either outdated or unofficial, and to download from the official source instead. The binary then has to be on the PATH or set in BROWSER_PATH, and it can also be passed per browser instance through the browser_path option.

Should I create a page explicitly when using Ferrum?

The documentation says yes. Ferrum creates and maintains a default page for you and sends the browser level methods to it, and interacting with a manually created page is described as preferred. The first quick start example uses the default page form, so the second example is the one to copy.

How is Ferrum related to Capybara?

Indirectly, through Cuprite, which is a pure Ruby driver for Capybara built on Ferrum. A separate project, Vessel, is a high-level web crawling framework built on Ferrum and Mechanize. Ferrum itself is the lower level browser API that both sit on.

Does Ferrum ship type signatures?

The repository carries a signature directory along with a collection definition and its lock file, which means the gem ships RBS signatures and pins the signatures it depends on. The readme does not mention this, so it has to be found in the repository layout rather than the documentation.

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)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/rubycdp-ferrum.svg)](https://hysenlabs.com/projects/rubycdp-ferrum)

Was this useful?