A UserAgent sniffer with Rails >= 3.2.0 integration
Useragent references:
- http://useragentstring.com/
- http://www.zytrax.com/tech/web/mobile_ids.html
- http://www.user-agents.org/
dates are in dd-mm-yyyy format
older changes can be found in the CHANGELOG.md
- Replaced
require
withrequire_relative
where possible - Fixed cli not loading due to failing
require
-
Added support for the servo browser:
- Added
servo?
method
- Added
-
Added detection for various programming languages:
- Added
library?
method - Added
php?
method - Added
perl?
method - Added
python?
method - Added
java
method - Added
curl
method - Added
pycurl
method
- Added
-
Stricter checking for:
social_media?
bot?
browser?
platform?
These methods used to be callable with unrelated symbols (e.g
agent.platform?(:firefox) # => true
), they will now correctly return false. -
Added support for consoles
- Added
console?
method - Added
wii?
,playstation?
,xbox?
andnintendo_ds?
methods
- Added
-
Added general
name
method to store any browser / bot / search engine / social media agent -
social_media_name
,search_engine_name
andbot_name
are now aliasses ofname
-
removed
:bot_name
from data structure (now stored in a generalname
property) -
removed
:browser_name
from data structure (now stored in a generalname
property) -
Added
console_name
method to get the name of a console
Add the following to your applications Gemfile:
gem 'browserino'
And then execute:
$ bundle
Or install it yourself with:
$ gem install browserino
Browserino is tested with the following ruby versions
- 1.9.3
- 2.0.0
- 2.1.0
- 2.2.1
- 2.3.0
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>'
Browserino is also usable in the command line
~$ browserino parse <ua>
Output
name: chrome, browser_version: 50.0.2661.102, engine_name: webkit, engine_version: 537.36, system_name: macintosh, system_architecture: nil
If you're using Rails (>= 3.2.0) you'll have access to an agent
object. Browserino will initialize itself using the request.headers['User-Agent']
A quick example on how to get going:
class ApplicationController < ActionController::Base
def some_method
render json: agent
end
end
the parse
method will always return a Browserino::Agent
object.
Browserino.parse '<user agent>' # => #<Browserino::Agent:0x007f9b09b1fae8 ... >
If a property isn't available or not known to Browserino it's return value will always be nil
, this can be tested by supplying an empty string (''
) to parse
:
agent = Browserino.parse ''
agent.name
# => nil
If a value is found then you'll recieve a lowercase string containing the information:
agent = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) brave/0.7.7 Chrome/47.0.2526.73 Electron/0.36.2 Safari/537.36'
agent.name
# => 'brave'
# or using browser_name
agent.browser_name
# => 'brave'
agent.browser_version
# => '0.7.7'
agent.engine_name
# => 'webkit'
Browserino also has some question methods, these will always return either true
or false
. The exceptions to this rule are methods that can take a name, for instance the bot?
method:
agent = Browserino.parse ''
agent.bot?
# => true (empty UA's count as anonymous bots)
agent.googlebot?
# => false
agent.non_supported_bot?
# => NoMethodError
agent.bot? :non_supported_bot
# => NoMethodError
The samples below are all valid calls with their respective outputs, using the agent
defined below.
agent = Browserino.parse 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko'
The methods social_media_name
, search_engine_name
, bot_name
and browser_name
are all aliasses of the general name
method.
The exceptions to this rule are system_name
and console_name
. They each have their own method.
agent.name
# => 'ie'
# always returns real version, also when IE is in compat
agent.browser_version
# => '11.0'
# to get the compat version that IE is running in
# returns real version if not in compat mode
agent.browser_version compat: true
# => '11.0'
agent.library_name
# => nil
agent.library_version
# => nil
agent.engine_name
# => 'trident'
agent.engine_version
# => '7.0'
agent.system_name
# => 'windows'
# system_name attempts to find the operating systems version name
# when full: true is used
# returning an array with either the version name or nil if not found
agent.system_name full: true
# => ['windows', '7']
agent.system_version
# => '6.1'
agent.system_architecture
# => 'x64'
agent.console_name
# => nil
# two formats possible: 'aa' or `aa-bb`
agent.locale
# => 'as'
Browserino also provides some question methods.
# only for Internet Explorer
agent.compat?
# => false
# returns true if name is present
agent.known?
# => true
# returns true if browser is known
agent.browser?
# => true
# returns true if specific browser
agent.browser? :ie
# => true
# returns true if specific browser and version
agent.browser? :ie, version: '11.0'
# returns true if library is known
agent.library?
# returns true if specific library
agent.library? :php
# returns true if specific library and version
agent.library? :php, version: '5.9.0'
# returns true if there is a social media bot on your website
agent.social_media?
# => false
# returns true if platform is known
agent.platform?
# => true
# returns true if specific platform
agent.platform? :windows
# => true
# returns true if specific platform and version
agent.platform? :windows, version: '7'
# => true
# returns true if console is known
agent.console?
# => false
# returns true if specific console
agent.console? :xbox
# => false
# returns true if user agent is empty or a bot is recognized
agent.bot?
# => false
agent.x64?
# => true
agent.x32?
# => false
agent.mobile?
# => false
The above methods are the base questions you can ask but there are a lot more methods you can call on the agent
. Every supported browser, operating system or bot is basically a question method so you could do this:
agent.windows?
# => true
# based on full name
agent.windows? '7'
# => true
# NT versions also work
agent.windows? 6.1
# => true
Browserino implements to_a
, to_h
and to_s
to allow for collected data to be moved around without attaching the entire object with methods.
to_s
Returns a compiled string of properties based on available information.
agent.to_s
# => 'ie ie11 trident trident7 windows x64'
# a seperator can be passed to format the name + version combo's
agent.to_s '-'
# => 'ie ie-11 trident trident-7 windows x64'
If the agent object can't find a property in the user agent, that property will be excluded from the string.
For instance, if the browser_version
and engine_version
of the agent
object are nil
then the following will be returned:
agent.to_s
# => ie trident windows x64
to_a
Returns an array with key => value pairs.
agent.to_a
# => [[:name, "ie"],
# [:browser_version, "11.0"],
# [:engine_name, "trident"],
# [:engine_version, "7.0"],
# [:system_name, "windows"],
# [:system_version, "6.1"],
# [:system_architecture, "x64"],
# [:console_name, nil],
# [:locale, "as"]]
to_h
Returns a hash with key => value pairs.
agent.to_h
# => {:name=>"ie",
# :browser_version=>"11.0",
# :engine_name=>"trident",
# :engine_version=>"7.0",
# :system_name=>"windows",
# :system_version=>"6.1",
# :system_architecture=>"x64",
# :console_name => nil,
# :locale=>"as"}
Consider this parsed string:
agent = Browserino.parse 'Mozilla/5.0 (Linux; U; Android 4.1.2; en-us; SM-T210R Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30 UCBrowser/2.3.2.300'
# output for system_name
agent.system_name
# => 'android'
# output for system_name full: true
agent.system_name full: true
# => ['android', 'Jelly Bean 16']
When supplying a version to a method that supports it, you have multiple options for the format of that version.
- Using a symbol or string without version:
:jelly_bean
or'jelly_bean'
- Using a symbol or string with version:
:jelly_bean_16
or'jelly_bean_16'
- Using a string:
'4.1.2'
- Using a float:
4.1
- Using an int:
4
When calling the platform?
or android?
functions with the above examples, they would all match since the method that compares versions also checks how specific the version is that you want to compare against.
If you pass in 4.1
as a version the matcher will look for x.x
in the extracted version and discard the unspecified value, this allows for you to be explicitly less specific to allow for a greater range of systems to be matched.
4.1.2
will match4.1.2
4.1
will match4.1.x
4
will match4.x.x
Examples using platform?
agent.platform? :android, version: '4.1.2'
# => true
agent.platform? :android, version: 4.1
# => true
agent.platform? :android, version: 4
# => true
agent.platform? :android, version: :jelly_bean
# => true
agent.platform? :android, version: :jelly_bean_16
# => true
As you've seen above, the platform?
function can take two arguments, a symbol with the system name and optionally a hash with a :version
key to supply a version, the browser?
and library?
method works in exactly the same way.
The bot?
and social_media?
methods however aren't that complex since you don't need to know a bot / social media version or anything other than it's name so inside these methods, only a name can be passed:
Every social media match is automatically a bot, but a bot isn't automatically social media, This is also true for the search_engine?
method
# when a bot UA gets parsed
agent = Browserino.parse 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)'
agent.bot?
# => true
agent.social_media?
# => true
agent.bot? :facebook
# => true
agent.social_media? :facebook
# => true
agent.bot? :facebook, version: 1.1
# => ArgumentError
Every name you see in the below lists can be passed as symbol or string to their respective method
search engine
google
bing
yahoo_slurp
baiduspider
duckduckgo
orddg
Examples:
agent.google?
agent.baiduspider?
# using the search_engine? method
agent.search_engine? :google
# using shorthand
agent.search_engine? :ddg
consoles
xbox
nintendo_ds
wii
playstation
Examples:
agent.playstation?
agent.wii?
agent.console?
agent.console? :facebook
social media
facebook
orfb
twitter
linkedin
instagram
pinterest
tumblr
Examples:
agent.facebook?
agent.tumblr?
# using the social_media? method
agent.social_media? :facebook
# using shorthand
agent.social_media? :fb
agent.social_media? :tumblr
bot
google
msn
bing
yahoo_slurp
baiduspider
yandex
sosospider
exa
sogou_spider
Examples:
agent.google?
agent.exa?
# using the bot? method
agent.bot? :google
agent.bot? :exa
library
php
perl
curl
python
java
pycurl
Examples:
agent.php?
agent.pycurl?
agent.library?
agent.library? :curl
agent.library? :curl, version: 7.21
browser
chrome
firefox
orff
servo
seamonkey
opera
opera_mini
vivaldi
ucbrowser
maxthon
bolt
brave
safari
ie
edge
Examples:
agent.firefox?
agent.chrome? 42
# using the browser? method
agent.browser? :firefox
# using shorthand
agent.browser? :ff
agent.browser? :chrome, version: 42
operating system
windows
orwin
macintosh
orosx
linux
bsd
solaris
android
ios
blackberry
orbb
windows_phone
Examples:
agent.macintosh?
agent.windows_phone? 7
# to check for windows vista one could do
agent.windows? 6
# a more readable equivelant
agent.windows? :vista
# using the platform? method
agent.platform? :macintosh
# using shorthand
agent.platform? :osx
agent.platform? :windows_phone, version: 7
Notes:
linux?
doesn't support any versionsbsd?
doesn't support any versionssolaris?
only supports numeric versions- named versions are only supported if they are present in a map
Bug reports and pull requests are welcome on GitHub at https://github.com/SidOfc/browserino. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT License.