Browserino
Browserino is a tool that parses a user agent string into a convenient object to work with. This allows developers to gather information about the system of a user on a website without having to ask countless questions about their browser / OS versions.
Status
Table of Contents
- Browserino
- Status
- Table of Contents
- Sources
- Changelog
- 10-07-2019 VERSION 4.5.0
- 21-10-2018 VERSION 4.4.1
- 23-06-2018 VERSION 4.4.0
- Installation
- Rails (>= 3.2.0)
- Initializer
- Usage
show 5 items - Client
- Formatting
- Non version-like properties
- Version-like properties
- Config
- Matchers
- Aliasses
- Labels
- HTTP headers
- Methods
show 31 items - name
- name?(sym, opts = {})
- version
- version?(version)
- engine
- engine?(sym, opts = {})
- engine_version
- engine_version?(version)
- platform
- platform?(sym, opts = {})
- platform_label
- platform_version
- platform_version?(version)
- device
- device?(sym)
- architecture
- architecture?(sym)
- locale
- locale?
- locales
- locales?
- x64?
- x32?
- mobile and #mobile?
- type
- type?(sym)
- like
- like?(sym, opts = {})
- is?(sym, opts = {})
- not
- not?(sym, opts = {})
- Magic methods
- Names
- Aliasses
- Supported
show 8 items - Browsers
- Bots
- Validators
- Libraries
- Email Clients
- RSS
- Platforms
- Android
- Windows
- Macintosh
- Devices
Sources
Many thanks to the creators and maintainers of the following sources of user agents and timelines:
- udger.com
- ua.theafh.net
- user-agents.org
- zytrax.com
- useragentstring.com
- whatismybrowser.com
- mobile247.eu
- commons.wikimedia.org browser timeline
- browscap database (github repo)
Changelog
dates are in dd-mm-yyyy format older changes can be found in the changelog
10-07-2019 VERSION 4.5.0
- Add: browser user-agents
:basilisk:facebook_app
- Add:
:goannarendering engine detection - Add:
:catalinalabel for MacOS 10.15.x
21-10-2018 VERSION 4.4.1
- Fix:
Browserino.parsehandlesnilandfalseby converting them to an empty string
23-06-2018 VERSION 4.4.0
- Update: Gem dependencies
- Add: ability to supply HTTP headers to Browserino for extra information
- Improve: location will be detected from HTTP headers when available (on by default in Rails)
- Add:
prop_missingDSL for last-minute info gathering - Add: Android
:pielabel - Add:
:falkonalias for:qupzillaorange_browser - Add:
:alohabrowser - Add:
:iris - Add:
:otter - Add:
:chedot - Add:
:cm_browser - Add:
:diglo - Add:
:diigo_browser - Add:
:flyflow - Add:
:freebox - Add:
:kuaiso - Add:
:lovense - Add:
:slimjet - Add:
:zetakey - Add:
:wkbrowser - Add:
:yolobrowser - Add:
:whale - Add:
:vivo - Add:
:jasmine - Add:
:seraphic_sraf - Add:
:phantomjs - Add:
:slimerjs - Add:
:liebao - Add:
:w3m - Add:
:charon - Add:
:cent - Add:
:jig_browser_web - Add:
:blazer
Installation
Add this line to your application's Gemfile:
gem 'browserino'And then execute:
$ bundle
Or install it yourself with:
$ gem install browserino
After installing the gem globally or in your application you'll have to require the gem before being able to use it.
require 'browserino'Afterwards, the gem is loaded and you can proceed by calling:
Browserino.parse '<user agent>'[, {'request-header' => 'header-value', ...}]The first argument to Browserino.parse is a user agent string. This is the string that browsers send to webservers for identification.
The second (optional) argument to Browserino.parse is a hash that contains HTTP headers. When a property could not be found, these headers
will be used by Browserino to attempt to extract it from there if a prop_missing handler is defined for it.
Browserino is tested with the following ruby versions
- 2.0.0
- 2.1.0
- 2.2.0
- 2.3.0
- 2.4.0
- 2.5.0
Rails (>= 3.2.0)
If you're using Rails (>= 3.2.0) you'll have access to a client object. Browserino will initialize itself using request.headers['User-Agent'] and will also use Rails request.headers to find
extra information that could not be found in the user agent (e.g. user locales).
A quick example on how to get going:
class ExampleController < ApplicationController
def example_method
render json: client.to_json
end
endInitializer
If you would like to extend Browserino within your rails app, this is certainly possible. Create a file config/initializers/browserino.rb and add the following:
Browserino.config.define do
# your magic here
endPlease skip ahead to the Config part of the documentation, that section contains information on how to make use of Browserino's builtin DSL
Usage
Client
the parse method will always return a Browserino::Client object. This object is special in that it simply resonds to everything. If a property does not exist or isn't defined on the current instance of client then it will simply return nil. Parsing an empty user agent will result in the following output:
client = Browserino.parse ''
client.is_a? Browserino::Client # => truePrior to version 4.4.1, Browserino.parse nil or Browserino.parse false were invalid. As of 4.4.1 an empty user agent ('') is assumed when these values are used.
Formatting
This section explains the output / return values given by calling a method on an instantiated Browserino::client object.
Non version-like properties
Non-version-like properties are properties that are not solely digits seperated by a delimiter like '.' or '_'.
All the non-version-like property values (which aren't Array or Hash instances) will be formatted in the following order:
- skip following steps if
ArrayorHash - stringify value
- lowercase all characters
- strip spaces on either side
- replace one or more spaces or dashes with a single underscore (
_) - convert to symbol
client = Browserino.parse 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:24.0) Gecko/20100101 Firefox/24.0 Waterfox/24.0'
client.name # => :waterfox
client.type # => :browser
client.platform # => :windows
client.engine # => :gecko
client.platform_label # => :windows7Version-like properties
All the version-like property values will be converted to Browserino::Version objects.
These objects are comparable to numbers and version-like strings (e.g. '1.2.4')
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36'
client.version # => [37, 0, 2062, 124]
client.version.is_a? Browserino::Version # => true
client.version.is_a? Array # => true
# get full version
client.version.full # => '37.0.2062.124'
client.version.to_s # => '37.0.2062.124'
# get version components [major, minor, patch]
client.version.major # => 37
client.version.minor # => 0
client.version.patch # => 2062
# comparing with integers
client.version >= 32 # => true
client.version < 40 # => true
# comparing with strings
client.version >= '37.0.2000' # => true
client.version > '37.1.2000' # => falseConfig
Matchers
Browserino is based on a concept of matchers, a matcher is a single client entity.
They are defined in a Browserino.config.define { ... } block. A small example:
Browserino.config.define do
# define a matcher that looks for the pattern %r{mybrowser}i in the UA
# when found, give it a name of :mybrowser and a type of :browser
match %r{mybrowser}i, name: :mybrowser, type: :browser
end
ua = "Mozilla/5.0 (Windows NT 5.1; rv: 1.8.3.2) Gecko/13370420 MyBrowser/1.4.9"
client = Browserino.parse ua
client.to_h
# => { :name => :mybrowser,
# :type => :browser,
# :locale => nil,
# :locales => [],
# :architecture => nil,
# :mobile => false,
# :smarttv => false,
# :tablet => false,
# :platform => :windows,
# :platform_version => [5, 1],
# :version => [1, 4, 9],
# :engine_version => [],
# :device => nil,
# :label => nil,
# :engine_label => nil,
# :platform_label => :xp }
client.name
# => :mybrowserIn the above example, I've simply created a fictive UA to simulate how to add a matcher to Browserino. This matcher however, isn't all that powerful as all it does is match a pattern and assign a name and type. Browserino hosts a large list of defaults that you don't have to support anymore, these are all matchers themselves. The matcher for Firefox looks like this for instance:
Browserino.config.define do
# this matcher is written using the dsl style, calling a method and giving
# it a value, something to look for in the user agent, or a block will
# add that method name as a property with the parsed value as result
# match pattern %r{firefox|phoenix}i
match %r{firefox|phoenix}i do
# give this matcher a name of :firefox
name :firefox
# engine is a regexp, these will be matched on the UA and return their
# respective match (what is captured in a capture group)
engine %r{(gecko|servo)}i
# engine_version is also a regexp, because the gecko version isn't defined
# like gecko/[VERSION] but rather rv:[VERSION] while for servo it is
# servo/[VERSION]
engine_version %r{(?:rv:\s?|servo/)([\d\.]+)}i
# last but not least we can also define a block, the block
# will be executed once after all other properties have been defined on a
# client, the block itself will be executed in client context so
# everything you can do on a `client` can also be used within blocks
modern? { version >= 50 }
end
endNow as you may have noticed, there is no type defined in the above matcher, so how does Browserino know that Firefox is a browser?
In truth, you aren't seeing the whole file here, if you want to go take a look, you can find it here. To elaborate, Browserino has a few builtin convenience methods
That allow presetting of type in a nice way using:
Browserino.config.define do
# sets type: :browser for each matcher defined within the block
browsers do
# matcher %r{...}i
# matcher %r{...}i
# matcher %r{...}i
end
# sets type: :email for each matcher defined within the block
emails do
# ....
end
# sets type: :validator for each matcher defined within the block
validators do
# ....
end
# sets type: :bot for each matcher defined within the block
bot do
# ....
end
# sets type: :library for each matcher defined within the block
libraries do
# ....
end
endUnder the hood, these all use a more generic preset method as also seen in the source:
# snipped from Browserino::Config
def emails(opts = {}, &block)
preset opts.merge(type: :email), &block
end
def validators(opts = {}, &block)
preset opts.merge(type: :validator), &block
end
def browsers(opts = {}, &block)
preset opts.merge(type: :browser), &block
end
def bots(opts = {}, &block)
preset opts.merge(type: :bot), &block
end
def libraries(opts = {}, &block)
preset opts.merge(type: :library), &block
endAll that these methods, and preset do is they set an instance variable with all the properties you'll have supplied in an options hash and these will simply be applied to every matcher defined within them. The Firefox matcher could have been written in the following ways:
Browserino.config.define do
# using `browsers`
browsers do
match %r{firefox|phoenix}i do
name :firefox
engine %r{(gecko|servo)}i
engine_version %r{(?:rv:\s?|servo/)([\d\.]+)}i
modern? { version >= 50 }
end
end
# using `preset`
preset type: :browser do
match %r{firefox|phoenix}i do
name :firefox
engine %r{(gecko|servo)}i
engine_version %r{(?:rv:\s?|servo/)([\d\.]+)}i
modern? { version >= 50 }
end
end
# define type inline
match %r{firefox|phoenix}i, type: :browser do
name :firefox
engine %r{(gecko|servo)}i
engine_version %r{(?:rv:\s?|servo/)([\d\.]+)}i
modern? { version >= 50 }
end
# or
match %r{firefox|phoenix}i do
name :firefox
type :browser
engine %r{(gecko|servo)}i
engine_version %r{(?:rv:\s?|servo/)([\d\.]+)}i
modern? { version >= 50 }
end
endYou'll have also noticed that so far, no version property has been defined either, and that when we created the mybrowser matcher, it could actually find it's version without supplying it.
This is a different type of matcher at work. It is not a matcher for a single entity but rather, one that will be applied by default if nothing is specified.
It is then capable of extracting preprocessed information into a pattern that will magically detect the version for you.
They look like this:
Browserino.config.define do
# prop pattern flags
smart_match :version, with: ':name[\s/]?v?([\d\._]+)', flags: [:i]
smart_match :engine_version, with: ':engine[\s/]?([\d\._]+)', flags: [:i]
endWhat the above code does is, if no version property has been supplied to a matcher, it will try to look for a smart_watcher with a prop of version, then, using other parsed properties, it will replace the :name in this case with mybrowser (if we were to use our made-up UA). The pattern would then look like this: /mybrowser[\s/]?v?([\d\.]+)/i and go a head and match itself against the UA to get a value back.
If you supply your own version property, this smart_matcher will not be applied.
Aliasses
Aliasses are a bit simpler than Matchers, they look like this taken from the source:
Browserino.config.define do
# aliasses will be defined after a Client has been initialized
# only the aliasses matching the Client will be defined
alias_for :firefox, :ff
alias_for :windows, :win
alias_for :windows7, :win7
alias_for :windows8, :win8
alias_for :windows10, :win10
alias_for :macintosh, :mac, :osx, :macos
alias_for :blackberry, :bb
alias_for :ie, :internet_explorer
alias_for :facebook, :fb
alias_for :duckduckgo, :ddg
alias_for :chromeos, :cros
endWhat they do is they look for a value within the properties of a specific client and if found, all the aliasses specified will also be applied to that client.
This means that for a client.is? :firefox you can do client.is? :ff or client.ff? instead. This works for all the names like name, label, engine, engine_label, platform and platform_label
Labels
A label could be a codename or a specific OS name for instance, it applies to a name and it's respective version combination. It autodetects against which version it should match, this will always be the correct version. Here are some examples (also not the complete file - source):
# small subset of labels from the source
Browserino.config.define do
label :yosemite, for: :macintosh, range: '10.10'..'10.10.9'
label :el_capitan, for: :macintosh, range: '10.11'..'10.11.9'
label :sierra, for: :macintosh, range: '10.12'..'10.12.9'
endSo now it looks for a value of :macintosh in the properties gathered from a client, if it finds it, it will remember it's key (e.g. platform in this case.) and use it to find out the current version (e.g. platform_version in this case). If a version is supplied it will be compared to be >= min and <= max (which is inclusive) where min and max are the left and right values of the range option respectively.
HTTP headers
Browserino as of version 4.4.0 accepts a hash of HTTP headers as a second argument. This adds more detailed information (primarily #locales property is added and #locale is read from it when not found).
For Rails, this is already implemented and will work out of the box, adding support for it is as simple as supplying a Hash of HTTP headers (say, what you get from a request.headers in Rails or request from Sinatra) as second argument to Browserino.parse.
This user agent does not have a locale but when we supply the HTTP_ACCEPT_LANGUAGE (or just Accept-Language) header it will find all languages ordered by user preference in a #locales property.
For the #locale itself, if it is not found it will attempt to use #locales.first:
client = Browserino.parse(
'Mozilla/5.0 (Linux; Android 5.1; ZTE Blade L6 Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.91 Mobile Safari/537.36',
{'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.9,nl-NL;q=0.6,nl;q=0.7'}
)
client.locales
# => [:en_us :en :nl :nl_nl]
client.locale
# => :en_usThe behavior is defined by prop_missing hooks which will be run just before a new Client (and after all data gathering / processing is done) is initialized.
The hooks for :locales and :locale look like this:
Browserino.config.define do
prop_missing :locales do |http_headers|
http_headers[:accept_language]
.to_s.scan(/(\w{2}(?:[_\-]\w{2})?)(?:;q=([\d.]+))?/i)
.map { |(locale, quality)| [locale, (quality || 1).to_f] }
.sort_by { |a| -a[1] }
.map(&:first)
end
prop_missing :locale do |_http_headers, props|
props[:locales].first
end
endThe first block argument is a processed version of a hash with HTTP headers.
Keys of this hash are "normalized", any HTTP_ prefix is removed, - is replaced with _ and finally the key is lowercased and converted to a symbol.
This allows you to pass in raw header names as seen in the request like Accept-Language or Rails / Sinatra (read: rack) HTTP headers like HTTP_ACCEPT_LANGUAGE. Both will end up as :accept_language allowing for easy usage.
The second block argument are the processed properties. This is all the information from the UA / HTTP headers that Browserino could find combined.
What you may also notice here is that in the second prop_missing we are leveraging the first prop_missing. They are executed in order of definition to make it easy to "chain" property fallbacks.
Methods
The below methods are available by default, all methods with a questionmark at the end return either boolean true or false or nil.
#name
Returns either a symbol containing the name of the agent or nil otherwise.
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.name
# => :colibri#name?(sym, opts = {})
Returns true if supplied sym equals (==) the current client.name, if opts contains a :version key, it will be compared against #version
Returns false if the supplied criteria doesn't match the current client.
Returns nil if sym isn't the current client, regardless of version constraint
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.name? :colibri
# => true
client.name? :colibri, version: '1.0.0'
# => true
client.name? :colibri, version: '1.1.0'
# => false
client.name? :not_colibri
# => nil
client.name? :not_colibri, version: '1.0.0'
# => nil#version
Returns a Browserino::Version object. This object allows for more flexible comparing of long version numbers where simple numbers or floats don't suffice.
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.version
# => [1, 0, 0]
client.version.is_a? Browserino::Version
# => true
# logical operators can be used for comparison
# it can work with integers
client.version >= 1
# => true
# or strings
client.version >= '1.0.0'
# true
client.version.to_s
# or
client.version.full
# => '1.0.0'#version?(version)
Returns true if the supplied version equals (==) the current clients version.
Returns false otherwise
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.version? 1
# true
client.version? '1.0'
# true
client.version? '1.0.0'
# true
client.version? '1.0.1'
# false#engine
Returns either a symbol containing the engine of the agent or nil otherwise.
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.engine
# => :webkit#engine?(sym, opts = {})
Returns true if supplied sym equals (==) the current client.version, if opts contains a :version key, it will be compared against #engine_version
Returns false if the supplied criteria doesn't match the current client.
Returns nil if sym isn't the current client, regardless of version constraint
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.engine? :webkit
# => true
client.engine? :webkit, version: '537.36'
# => true
client.engine? :webkit, version: '537.38'
# => false
client.engine? :not_webkit
# => nil
client.engine? :not_webkit, version: '537.36'
# => nil#engine_version
Returns a Browserino::Version object.
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.engine_version
# => [537, 36]
client.engine_version >= 530
# true
client.engine_version.to_s
# or
client.engine_version.full
# => '537.36'#engine_version?(version)
Returns true if the supplied version equals (==) the current clients engine_version.
Returns false otherwise
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.engine_version? '537.36'
# true#platform
Returns either a symbol containing the platform of the agent or nil otherwise.
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.platform
# => :macintosh#platform?(sym, opts = {})
Returns true if supplied sym equals (==) the current client.platform, if opts contains a :version key, it will be compared against #platform_version
Returns false if the supplied criteria doesn't match the current client.
Returns nil if sym isn't the current client, regardless of version constraint
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.platform? :macintosh
# => true
client.platform? :macintosh, version: '10.12'
# => true
client.platform? :macintosh, version: '10.12.2'
# => false
client.platform? :not_macintosh
# => nil
client.platform? :not_macintosh, version: '10.12.1'
# => nil#platform_label
Returns either a symbol containing the platform_label of the agent or nil otherwise.
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client2 = Browserino.parse 'Mozilla/5.0 (Linux; Android 7.0; LG-H910 Build/NRD90C) AppleWebKit/537.26 (KHTML, like Gecko) Chrome/51.0.2704.90 Mobile Safari/537.36'
# macOS 10.12's name is Sierra
client.platform_label
# => :sierra
# Android 7's name is Nougat
client2.platform_label
# => :nougat#platform_version
Returns a Browserino::Version object.
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.platform_version
# => [10, 12, 1]
client.platform_version >= 10
# => true
client.platform_version.to_s
# or
client.platform_version.full
# => '10.12.1'#platform_version?(version)
Returns true if the supplied version equals (==) the current clients platform_version.
Returns false otherwise
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.platform_version? '10.12'
# => true#device
Returns either a symbol containing the device of the client or nil otherwise
client = Browserino.parse 'Mozilla/5.0 (Linux; Android 5.1; ZTE Blade L6 Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.91 Mobile Safari/537.36'
client.device
# => :zte#device?(sym)
Returns true if the supplied sym equals (==) the current clients device.
client = Browserino.parse 'Mozilla/5.0 (Linux; Android 5.1; ZTE Blade L6 Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.91 Mobile Safari/537.36'
client.device
# => :zte#architecture
Returns either nil, :x32 or :x64 depending on wether it could be found in the user agent
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client2 = Browserino.parse 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36 Vivaldi/1.0.288.3'
client.architecture
# => nil
client2.architecture
# => :x64#architecture?(sym)
sym must be one of :x32 or :x64, returns true if it matches the current client architecture, false otherwise.
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.architecture? :x64
# => false#locale
Returns either nil or a locale if present. Locales are formatted like :en_us for en-US and en_US and just :en for en.
client = Browserino.parse 'Mozilla/5.0 (Macintosh; U; Macintosh; en-US; Valve Steam GameOverlay/1329175982; ) AppleWebKit/534.1 (KHTML, like Gecko) Chrome/6.0.444.0 Safari/534.1'
client.locale
# => :en_us#locale?
Returns true or false based on locale presence.
client = Browserino.parse 'Mozilla/5.0 (Macintosh; U; Macintosh; en-US; Valve Steam GameOverlay/1329175982; ) AppleWebKit/534.1 (KHTML, like Gecko) Chrome/6.0.444.0 Safari/534.1'
client.locale?
# => true#locales
Returns an array of locales found in Accept-Language HTTP header. This only works when Browserino.parse is invoked with a hash containing the headers as second argument.
When locales are found using this method, they will be used instead of the #locale found in the user agent (the locale will be replaced with the highest quality locale from the header).
client = Browserino.parse 'Mozilla/5.0 (Macintosh; U; Macintosh; pt-BR; Valve Steam GameOverlay/1329175982; ) AppleWebKit/534.1 (KHTML, like Gecko) Chrome/6.0.444.0 Safari/534.1',
{'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.9,nl-NL;q=0.8,nl;q=0.7'}
# locale is :en_us because it is present in headers and thus overwrites :pt_br
client.locale
# => :en_us
# the :pt_br locale gets added as the least preferred locale instead
client.locales
# => [:en_us, :en, :nl_nl, :nl, :pt_br]#locales?
Returns true or false depending on wether any locales were found at all (e.g. from UA and/or HTTP headers).
client = Browserino.parse 'Mozilla/5.0 (Macintosh; U; Macintosh; pt-BR; Valve Steam GameOverlay/1329175982; ) AppleWebKit/534.1 (KHTML, like Gecko) Chrome/6.0.444.0 Safari/534.1',
{'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.9,nl-NL;q=0.8,nl;q=0.7'}
client.locales?
# => true#x64?
A shorthand for client.architecture? :x64 returns a boolean value
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.x64?
# => false#x32?
A shorthand for client.architecture? :x32 returns a boolean value
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.x32?
# => false#mobile and #mobile?
Returns boolean true or false depending on wether the device user agent is a mobile device
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.mobile
# or
client.mobile?
# => false#type
There are currently 6 types defined, :browser, :bot, :library, :validator, :email and :unknown (default)
This method simply returns the type of the current client, e.g.
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.type
# => :browser#type?(sym)
Returns true if sym equals (==) the current clients type
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Colibri/1.0.0-beta.9 Chrome/52.0.2743.82 Electron/1.3.13 Safari/537.36'
client.type? :browser
# => true
client.type? :bot
# => false#like
Like is something different. Within the defaults a few browsers are defined to be like others. This is the full list:
- Like
:chromeincludes::brave:vivaldi:colibri:rockmelt:flock:comodo_dragon-
:steam(Game interface) :chromeplus:bluechrome:awesomium:qqbrowser:yabrowser:coolnovo:iridium:origin:puffin:fluid:hana:iron
- Like
:safariincludes::bolt:samsungbrowser:webosbrowser:stainless:omnibrowser:cheshire:skyfire:mercury:rekonq:arora:raptr:icab:silk:qt
- Like
:firefoxincludes::seamonkey-
:minefield(FF nightly) :kmeleon:kninja:granparadiso:tenfourfox:enigmafox:kazehakase:shiretoko:classilla:cometbird:icedragon:palemoon:namoroka:songbird:vonkeror:conkeror:bonecho:chimera:lolifox:lorentz:myibrow:sylera:iceape:madfox:kapiko:kmlite:beonex:galeon:vision:pogo:orca:superswan:firebird:iceweasel:icecat:waterfox:netscape:prism:lunascape:camino
- Like
:ieincludes::avant_browser:deepnet_explorer:slimbrowser:sleipnir:greenbrowser:browzar:theworld:crazy_browser:solid_core:tencenttraveler:enigma_browser:simulbrowse:netcaptor:irider:kkman:lobo:aol
# In this case, seamonkey is like firefox so like will represent the same user agent parsed as firefox to gather information
client = Browserino.parse 'Mozilla/5.0 (Windows NT 5.2; RW; rv:7.0a1) Gecko/20091211 SeaMonkey/9.23a1pre'
client.name
# => :seamonkey
client.is_a? Browserino::Client
# => true
client.like.name
# => :firefox
client.like.is_a? Browserino::Client
# => true
client == client.like
# => false
# This client isn't `like` anything, it's just chrome so in this case, we assign the value of like to itself.
client2 = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'
client2.name
# => :chrome
client2.is_a? Browserino::Client
client.like.name
# => :chrome
client2.like.is_a? Browserino::Client
# => true
client == client.like
# => true#like?(sym, opts = {})
This method acts much like the name? method on a client except that like like method will match a broader set of things like it.
Additionally, you can also supply an optional :version option which will then be compared to the like.version property.
Seamonkey in the last example is the browser I chose to be an example for the like documentation, since Seamonkey is like firefox we can do this:
# In this case, seamonkey is like firefox so like will represent the same user agent parsed as firefox to gather information
client = Browserino.parse 'Mozilla/5.0 (Windows NT 5.2; RW; rv:7.0a1) Gecko/20091211 SeaMonkey/9.23a1pre'
client.name
# => :seamonkey
client.name? :seamonkey
# => true
client.name? :firefox
# => false
client.like? :firefox
# => true
# A version can be supplied too but in this case, FireFox's version number
# isn't present in the user agent
# client.like? :firefox, version: '9.23'
# => false#is?(sym, opts = {})
The is? method is a bit more loose, it will recognize what it is and what it isn't automagically depending on what's passed in.
It can be a more general replacement for #name?, #engine? and #platform?
#not
Inverts the result returned by any method ending in a question mark (e.g. client.version? == true && client.not.version? == false)
#not?(sym, opts = {})
An inverted version of #is?
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'
client.to_h
# => { :name => :chrome,
# :type => :browser,
# :locale => nil,
# :architecture => nil,
# :mobile => false,
# :smarttv => false,
# :tablet => false,
# :platform => :macintosh,
# :platform_version => [10, 11, 2],
# :version => [47, 0, 2526, 106],
# :engine => :webkit,
# :engine_version => [537, 36],
# :device => nil
# :label => nil,
# :engine_label => nil,
# :platform_label => :el_capitan }
client.not? :chrome
# => false
# compares to a name of chrome with version of 47.0
client.not? :chrome, version: '47.0'
# => false
# but it also knows about platforms
client.not? :macintosh
# => false
# the version is matched against the platform_version in this case
client.not? :macintosh, version: '10.11'
# => false
# and engine names
client.not? :webkit
# => false
# where the version is compared to the engine_version
client.not? :webkit, version: 537
# => falseMagic methods
Names
For each of #name, #engine, #platform, #platform_label and #device, upon instantiation of the current client object, the results of these methods will also be defined as methods if they aren't nil e.g:
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'
client.to_h
# => { :name => :chrome,
# :type => :browser,
# :locale => nil,
# :architecture => nil,
# :mobile => false,
# :smarttv => false,
# :tablet => false,
# :platform => :macintosh,
# :platform_version => [10, 11, 2],
# :version => [47, 0, 2526, 106],
# :engine => :webkit,
# :engine_version => [537, 36],
# :device => nil,
# :label => nil,
# :engine_label => nil,
# :platform_label => :el_capitan }
### NAME ###
# since client.name is :chrome, a method #chrome? is defined
client.chrome?
# => true
# an optional version can also be suppied
client.chrome? 47
# => true
# since client.name isn't :firefox, no method named #firefox? is defined
# instead, it is sent to method_missing which will return nil
client.firefox?
# => nil
# supplying a version of course, makes no difference in this case
client.firefox? 47
# => nil
### ENGINE NAME ###
# since client.engine_name is :webkit, a method #webkit? is defined
client.webkit?
# => true
# an optional version can also be suppied
client.webkit? '537.36'
# => true
# since client.engine_name isn't :gecko, no method named #gecko? is defined
# instead, it is sent to method_missing which will return nil
client.gecko?
# => nil
# supplying a version of course, makes no difference in this case
client.gecko? 50
# => nil
### PLATFORM NAME ###
# since client.platform_name is :macintosh, a method #macintosh? is defined
client.macintosh?
# => true
# an optional version can also be suppied
client.macintosh? '10.11'
# => true
# since client.platform_name isn't :windows, no method named #windows? is defined
# instead, it is sent to method_missing which will return nil
client.windows?
# => nil
# supplying a version of course, makes no difference in this case
client.windows? 10
# => nil
### PLATFORM LABEL ###
# since client.platform_label is :el_capitan, a method #el_capitan? is defined
client.el_capitan?
# => true
# an optional version can also be suppied
client.el_capitan? '10.10'
# => trueAliasses
For each of the defined keys in Browserino.config.aliasses that matches with any value of #name, #engine, #platform or #platform_label, define every alias as a method.
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:33.0) Gecko/20100101 Firefox/33.0'
### NAME ###
client.name
# => :firefox
Browserino.config.aliasses[client.name]
# => [:ff]
client.firefox?
# => true
client.ff?
# => true
### PLATFORM NAME ###
client.platform
# => :macintosh
Browserino.config.aliasses[client.platform]
# => [:macos, :osx, :mac]
client.macos?
# => true
client.osx?
# => true
client.mac?
# => trueAliasses can also be used in #name?, #engine?, #platform? and #is? methods, e.g:
client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:33.0) Gecko/20100101 Firefox/33.0'
### NAME ###
client.name
# => :firefox
client.name? :firefox
# => true
client.name? :ff
# => true
client.name? :ff, version: 33
# => true
client.is? :firefox
# => true
client.is? :ff
# => true
client.is? :ff, version: 33
# => true
### PLATFORM NAME ###
client.platform
# => :macintosh
# Browserino.config.aliasses[:macintosh] defines [:mac, :osx, :macos] as aliasses
client.platform? :macintosh
# => true
client.platform? :mac
# => true
client.platform? :osx
# => true
client.platform? :macos
# => true
client.platform? :macos, version: '10.10'
# => trueSupported
Browsers
aol, ion, foxy, lobo, kkman, irider, sleipnir, netcaptor, sitekiosk, gomezagent, solid_core, simulbrowse, crazy_browser, enigma_browser, tencenttraveler, deepnet_explorer, sogou_browser, netflix_desktop, browzar, theworld, smart_bro, slimbrowser, greenbrowser, avant_browser, orca, pogo, epic, kylo, wyzo, light, prism, strata, vision, galeon, icecat, minimo, beonex, kmlite, kapiko, madfox, iceape, fennec, sylera, myibrow, lorentz, lolifox, chimera, sundial, bonecho, k_ninja, k_meleon, netscape, conkeror, vonkeror, firebird, songbird, namoroka, cyberfox, palemoon, swiftfox, cunaguaro, icedragon, blackbird, cometbird, classilla, shiretoko, lunascape, superswan, lightning, multizilla, seamonkey, iceweasel, enigmafox, kazehakase, tenfourfox, swiftweasel, granparadiso, maemo_browser, sailfishbrowser, monyq, waterfox, minefield, fireweb_navigator, camino, maemo, opera_mobile, blackberry_browser, webosbrowser, leechcraft, kindle, nook, xiaomi_miui, qt, coda, silk, bolt, icab, raptr, maple, arora, coast, rekonq, mercury, skyfire, omniweb, teashark, cheshire, stainless, webbrowser, mqqbrowser, nokiabrowser, samsungbrowser, playbook_browser, obigo, qtweb_browser, maxthon_nitro, nichrome, iron, hana, perk,
brave, swing, kinza, fluid, amigo, puffin, origin, yowser, iridium, colibri, vivaldi, safepay, slimboat, coolnovo, rockmelt, polarity, chromeum, yabrowser, qqbrowser, awesomium, mxbrowser, fabrowser, blackhawk, taobrowser, bluechrome, chromeplus, comodo_dragon, coc_coc_browser, whitehat_aviator, steam, maxthon, ucbrowser, edge, opera_mini, opera, escape, flock, sunrise, ie, origyn, webpositive, nintendobrowser, deskbrowse, qupzilla, midori, shiira, element_browser, amigavoyager, browse, mothra, surf, spray_can, bunjalloo, inet_browser, webpro, sundance, ibm_webexplorer, navscape, firefox, chrome, safari, tizenbrowser, epiphany, uzbl, roccat, dolfin, dooble, adobeair, abrowse, vimprobable, osb_browser, edbrowse, amaya, lynx, linemode, elinks, netpositive, mucommander, onebrowser, flashfire, konqueror, cyberdog, offbyone, hotjava, netsurf, contiki, mosaic, netbox, dillo, ice_browser, emacs, openwave_browser, alienblue, ovibrowser, links, oregano, browsex, doris, retawq, orange_browser, alohabrowser, iris, otter, chedot, cm_browser, diglo, diigo_browser, flyflow, freebox, kuaiso, lovense, slimjet, zetakey, wkbrowser, yolobrowser, whale, vivo, jasmine, seraphic_sraf, phantomjs, slimerjs, liebao, w3m, charon, cent, jig_browser_web, blazer
Bots
huaweisymantecspider, atomic_email_hunter, netresearchserver, auto_email_spider, flaming_attackbot, addsugarspiderbot, semanticdiscovery, xaldon_webspider, yooglifetchagent, keyword_density, mass_downloader, safetynet_robot, download_demon, internet_ninja, dataparksearch, boston_project, emailcollector, webemailextrac, sitelockspider, morning_paper, four_anything, aqua_products, arachnophilia, smartdownload, emeraldshield, womlpefactory, israelisearch, issuecrawler, jaxified_bot, stackrambler, turnitinbot, covario_ids, alkalinebot, yahoo_slurp, propowerbot, emailsiphon, backdoorbot, terrawizbot, searchsight, baiduspider, sandcrawler, fyberspider, linguee_bot, big_brother, yahooseeker, noxtrumbot, black_hole, blackwidow, sosospider, duckduckgo, beslistbot, twitterbot, linkdexbot, aitcsrobot, litefinder, mabontland, yasaklibot, httpclient, ahrefsbot, mojeekbot, incywincy, seznambot, girafabot, becomebot, dts_agent, emailwolf, googlebot, omgilibot, labelgrab, altavista, yandexbot, newsgator, instagram, pinterest, gurujibot, lapozzbot, mvaclient, ng_search, youdaobot, webcopier, ips_agent, yodaobot, ldspider, lexxebot, scoutjet, linkedin, bullseye, alexibot, whatsapp, facebook, getright, asterias, catchbot, discobot, geniebot, koepabot, synoobot, rufusbot, rampybot, mogimogi, lmspider, blowfish, superbot, valkyrie, yacybot, jyxobot, orbiter, polybot, accoona, mj12bot, aspider, blexbot, bspider, auresys, bingbot, gaisbot, zealbot, zspider, backrub, harvest, nymesis, radian6, scrubby, gcreep, snappy, vortex, tineye, zyborg, sqworm, qseero, pompos, solbot, ichiro, bizbot, msnbot, exabot, msrbot, dotbot, cosmos, ecatch, scrapy, tumblr, holmes, okhttp, mxbot, moget, occam, acoon, nutch, alexa, atomz, htdig, peew, yeti, wf84, vyu2, acoi, obot, ask, b2w, ipd, zao, furlbot, jakarta, oegp, lwebis, cerberian_drtrs, gigamega, sogou_spider, megaindex, gozilla, larbin, netseer, ntent, sheenbot
Validators
xenu_link_sleuth, screaming_frog_seo_spider, rel_link_checker_lite, a1_website_analyzer, w3c_multipage_validator, cse_html_validator, p3p_validator, w3c_checklink, w3c_i18n_checker, w3c_unicorn, w3c_mobileok, wdg_validator, w3c_validator, fplinkchecker, linkchecker, linkwalker, linkexaminer, feedvalidator, htmlparser, csscheck, checkbot, cynthia, validator_nu, anw_htmlchecker, w3c_css_validator
Libraries
golang, python, luakit, webfetch, pycurl, perl, java, curl, wget, php
Email Clients
:outlook, :airmail, :barca, :gmail, :thunderbird, :postbox, spicebird, icedove
RSS
windows_rss, apple_pubsub, safari_rss, sharpreader, netnewswire, omea_reader, rssbandit, feeddemon, lucknews, inoreader, rss_menu, rss_popper, seznam_rss, nfreader, magpierss, gregarius, newsbreak, blogbridge, yeahreader, newsbeuter, greatnews, bloglines, icatcher, newsfox, quiterss, liferea, aiderss, reeder, rssowl, feedly, abilon, shrook, awasu, sage, akregator, trileet_newsroom, dragonfly_rss, digg_feed_fetcher, yahoofeedseeker, universalfeedparser, feedfetcher_google, fastladder_feedfetcher
Platforms
In addition to just supporting regular platform names as client.android?, there are also specific methods that get added if a certain version matches a platform.
This is the platform_label property and allows you to do things like client.froyo? for instance.
Below are a list of versions the agent can identify so far
Android
Regular: :android
:android, :cupcake, :eclair, :froyo, :gingerbread, :honeycomb, :ice_cream_sandwich, :jelly_bean, :kitkat, :lollipop, :marshmallow, :nougat, :oreo, :pie
Since android version releases follow the alphabet and since every new version since android 5 is contained within a single major version number,
additional methods are defined for all "future" android releases e.g:
label :android_p, for: :android, version: '9'..'9.9.9'
label :android_q, for: :android, version: '10'..'10.9.9'
# ... snipped ...
label :android_y, for: :android, version: '18'..'18.9.9'
label :android_z, for: :android, version: '19'..'19.9.9'So for every unreleased version of android, you can identify it by using :android_ followed by the letter for that version: client.android_p?.
Since some android versions are already known, this system is supported from the letter p up to and including z.
Windows
Regular: :windows
:dos, :windows98, :windows2000, :xp, :vista, :windows7, :windows8, :windows10
NOTE: Windows 10 will be the last major version bump for Windows (for now, at least).
Macintosh
Regular: :macintosh
:cheetah, :puma, :jaguar, :panther, :tiger, :leopard, :snow_leopard, :lion, :mountain_lion, :mavericks, :yosemite, :el_capitan, :sierra, :high_sierra, :mojave
NOTE: macOS version 10 and up increment the minor version instead of the major version in a new major release.
Devices
Finally, Browserino can also detect devices in addition to the above.
htc, kindle, alcatel, appletv, iphone, ipad, archos, asus, zte, blackberry, oneplus, lenovo, nokia, motorola, huawei, nexus, hp, lg, dell, oppo