Guide

BrowserX keeps the API of the browser gem, predicate for predicate. Installing it is swapping a gem; this page covers the rest.

Installation

gem "browserx"

BrowserX requires Ruby 3.3 or later. It is tested on Rails 8.0 and 8.1, and works without Rails.

Migrating from browser

Change one line of the Gemfile, nothing else:

- gem "browser"
+ gem "browserx"

The gem still loads with require "browser", still defines Browser, and require "browser/aliases" or require: "browser/browser" keep the meaning they had. BrowserX 1.0.0 is forked from browser 6.2.0 (dd88933), and a change that is not meant to change an answer is diffed against that version on the 20,328 user agents of the corpus.

To roll back, put gem "browser" back: 1.0.0 adds no option of its own, so no call site depends on BrowserX.

What comes next — a per-user-agent cache, bot categories, verified crawler IPs, Cloudflare headers and Client Hints — is tracked in the GitHub issues. Each will be an addition; no existing predicate changes meaning.

Usage

require "browser"

browser = Browser.new("Some User Agent", accept_language: "en-us")

Browser

browser.name                 # readable browser name
browser.version              # major version number
browser.full_version
browser.to_s                 # the meta info joined by space
browser.meta                 # an array with several attributes
browser.known?               # has the browser been successfully detected?
browser.unknown?             # the browser wasn't detected
browser.webkit?
browser.webkit_full_version
browser.chromium_based?
browser.chrome?
browser.edge?                # newest MS browser
browser.electron?            # Electron Framework
browser.firefox?
browser.ie?
browser.ie?(6)               # detect specific IE version
browser.ie?([">8", "<10"])   # detect specific IE (IE9)
browser.opera?
browser.opera_mini?
browser.safari?
browser.safari_webapp_mode?
browser.samsung_browser?
browser.core_media?
browser.duck_duck_go?
browser.epiphany?
browser.nokia?
browser.phantom_js?
browser.qq?
browser.quicktime?
browser.sougou_browser?
browser.sputnik?
browser.uc_browser?
browser.wechat?
browser.weibo?
browser.yandex?

Version predicates take a version or a list of constraints, so a “modern browser” check is a method of yours:

def modern_browser?(browser)
  [
    browser.chrome?(">= 65"),
    browser.safari?(">= 10"),
    browser.firefox?(">= 52"),
    browser.ie?(">= 11") && !browser.compatibility_view?,
    browser.edge?(">= 15"),
    browser.opera?(">= 50"),
    browser.facebook? &&
      browser.safari_webapp_mode? &&
      browser.webkit_full_version.to_i >= 602
  ].any?
end

Bots

browser.bot?
browser.bot.name
browser.bot.search_engine?
browser.bot.why?             # which matcher detected this user agent as a bot
Browser::Bot.why?(user_agent)

How a bot is detected, and how to change the lists, is on the Bots page.

Device

browser.device
browser.device.id
browser.device.name
browser.device.unknown?
browser.device.mobile?
browser.device.tablet?
browser.device.tv?
browser.device.console?
browser.device.ipad?
browser.device.iphone?
browser.device.ipod_touch?
browser.device.kindle?
browser.device.kindle_fire?
browser.device.silk?
browser.device.surface?
browser.device.samsung?
browser.device.blackberry_playbook?
browser.device.nintendo?
browser.device.switch?
browser.device.wii?
browser.device.wiiu?
browser.device.playstation?
browser.device.ps3?
browser.device.ps4?
browser.device.psp?
browser.device.vita?
browser.device.xbox?
browser.device.xbox_360?
browser.device.xbox_one?

Platform

browser.platform
browser.platform.id
browser.platform.name
browser.platform.version          # e.g. 9 (for iOS 9)
browser.platform.unknown?
browser.platform.adobe_air?
browser.platform.android?
browser.platform.android?(4.2)    # detect Android Jelly Bean 4.2
browser.platform.android_app?     # detect webview in an Android app
browser.platform.android_webview? # alias for android_app?
browser.platform.blackberry?
browser.platform.blackberry?(10)  # detect specific BlackBerry version
browser.platform.chrome_os?
browser.platform.firefox_os?
browser.platform.ios?
browser.platform.ios?(9)          # detect specific iOS version
browser.platform.ios_app?         # detect webview in an iOS app
browser.platform.ios_webview?     # alias for ios_app?
browser.platform.kai_os?
browser.platform.linux?
browser.platform.mac?
browser.platform.windows?
browser.platform.windows_xp?
browser.platform.windows_vista?
browser.platform.windows7?
browser.platform.windows8?
browser.platform.windows8_1?
browser.platform.windows10?
browser.platform.windows_rt?
browser.platform.windows_mobile?
browser.platform.windows_phone?
browser.platform.windows_touchscreen_desktop?
browser.platform.windows_wow64?
browser.platform.windows_x64?
browser.platform.windows_x64_inclusive?

The full lists live in lib/browser/platform.rb and lib/browser/device.rb.

Aliases

To call browser.mobile? and browser.tablet? on the base object, include the aliases:

require "browser/aliases"
Browser::Base.include(Browser::Aliases)

Browser.new("Some user agent").mobile? #=> false

Options

SettingDefaultWhat it does
accept_language:nilThe Accept-Language header, passed to Browser.new; parsed into browser.accept_language.
Browser.user_agent_size_limit2048Largest user agent accepted, in bytes. A larger one raises Browser::Error.
Browser.accept_language_size_limit2048Largest Accept-Language header accepted, in bytes. A larger one raises Browser::Error.
Browser::Bot.matchersthree built-in matchersCallables deciding whether a user agent is a bot. See Bots.
Browser::Bot.botsbots.ymlKnown bots, keyed by a lowercase substring of their user agent.
Browser::Bot.search_enginessearch_engines.ymlBots answering bot.search_engine?.
Browser::Bot.bot_exceptionsbot_exceptions.ymlSubstrings that are never a bot, even when a matcher says so.
Browser.user_agent_size_limit = 4096
Browser.accept_language_size_limit = 4096

Rails

The Gemfile line is enough: a railtie adds a browser helper to controllers and views, built from the request’s User-Agent and Accept-Language headers.

<% if browser.ie?(6) %>
  <p class="disclaimer">You're running an older IE version. Please update it!</p>
<% end %>

To use BrowserX in a Rails app without adding the helper to controllers, load only the library:

gem "browserx", require: "browser/browser"

Middleware

Browser::Middleware redirects user agents from a Rack stack:

use Browser::Middleware do
  redirect_to "/upgrade" if browser.ie?
end

In Rails, route helpers work from an initializer (config/initializers/browser.rb), and request gives the Rack::Request:

Rails.configuration.middleware.use Browser::Middleware do
  redirect_to upgrade_path if browser.ie? && request.env["PATH_INFO"] != "/exclude_me"
end

Accept-Language

browser.accept_language is an array of languages, sorted by quality from highest to lowest. A missing quality means 1.0; a quality of zero means the language is not accepted.

language = Browser.new(user_agent, accept_language: "en-us").accept_language.first

language.code    #=> "en"
language.region  #=> "US"
language.full    #=> "en-US"
language.quality #=> 1.0
language.name    #=> "English/United States"

Internet Explorer and Safari

Internet Explorer. In compatibility view, IE8 and later run as an older version. version and full_version return the navigator’s version; msie_version and msie_full_version return the engine’s.

browser.version             #=> 11
browser.full_version        #=> 11.0
browser.msie_version        #=> 7
browser.msie_full_version   #=> 7.0
browser.compatibility_view? #=> true

Safari. iOS webviews and web apps are not Safari. Combine platform and WebKit detection instead:

browser = Browser.new("Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405")

browser.safari?        #=> false
browser.webkit?        #=> true
browser.platform.ios?  #=> true