Using the navigator object to detect client's browser
Last updated: January 20th, 15'
Until one browser remains standing on the web (if ever), browser detection will continue to be part of any good JavaScripter's life. Whether you're gliding a div across the screen or creating an image rollover, it's fundamental that only relevant browsers pick up on your code. In this tutorial we'll probe the navigator object of JavaScript, and show how to use it to perform browser detection, whether the subject is Firefox, Internet Explorer, Opera, etc.
The navigator object
The navigator object was conceived back in the days when Netscape Navigator reined supreme. These days it serves as much as an irony of Netscape's demise as way of probing browser information.
The navigator object of JavaScript contains the following core properties:
Properties | Description |
---|---|
appCodeName | The code name of the browser. |
appName | The name of the browser. In Firefox for example the
returned value is "Netscape ", while in IE10 and below,
it's "Microsoft
Internet Explorer " as can be expected. Starting in IE11+,
however, the returned value of appName is also "Netscape ". |
appVersion | Version information for the browser
(ie: 5.0 (Windows) ). |
cookieEnabled | Boolean that indicates whether the browser has cookies enabled. |
language | Returns the default language of the
browser version (ie: en-US ). NS and Firefox only. |
maxTouchPoints | The maximum number of simultaneous touch contacts supported by the device. IE10+ only. |
mimeTypes[] | An array of all MIME types supported by the client. NS and Firefox only. |
onLine | A Boolean that returns true if the browser is
online, false if not. Note that different browsers have different
minimum requirements when deciding if the browser is online, which
may not accurately correlate to whether the browser is in fact able
to access the web. In other words, you should not solely rely on the
onLine property to detect whether the user is online. |
platform[] | The platform of the client's computer
(ie: Win32 ). |
plugins | An array of all plug-ins currently installed on the client. NS and Firefox only. |
systemLanguage | Returns the default language of the operating system
(ie: en-us ). IE only. |
userAgent | String passed by browser as user-agent header. The
userAgent value for IE9 is "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT
6.1; )" while for Mozilla Firefox 35, it's "Mozilla/5.0
(Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0 ".
Starting in IE11+, the
You can probe the //returns true if user is using one of the following mobile browsers |
userLanguage | Returns the preferred language setting of the user
(ie: en-ca ). IE only. |
Let's see exactly what these properties reveal of the browser you're currently using:
At a glance
At a glance at the above table, you may be swayed towards turning to the following two properties to do your browser detection bidding:
navigator.appName
navigator.appVersion
After all, you are trying to detect a browser's name and
version right? However, they both will most likely mislead you. In
browsers such as various versions of Netscape and Firefox, these two
properties return simply "Netscape" for appName
, and 5.0
for appVersion
without any further distinction for Firefox
and its version, and hence are pretty much useless in the real world.
For example, in both Firefox 5.x and Firefox 35, these two properties
return:
appName: Netscape appVersion: 5.0 (Windows)
We need to turn to a property that's more thorough in its
investigative work if we want more consistency and accuracy, and that
turns out to be navigator.userAgent
.
Detecting Firefox x.x
In Firefox 5.0 for example,
the userAgent
property reads:
UserAgent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101 Firefox/5.0
And in Firefox 35:
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0
The detail we're interested in apparently lies at the very
end, or Firefox/35.0
for example. Different versions of Firefox will
contain a different version number, but the pattern is consistent enough.
The part we're interested in occurs after the string "Firefox/
",
or the exact version number. There are many ways to get to it using either
standard String
or RegExp
methods- I'm opting for the later here:
<script type="text/javascript">
//Note: userAgent in FF2.0.0.13 WinXP returns: Mozilla/5.0 (Windows; U;
Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13
// userAgent in FF35 Win7 returns: Mozilla/5.0 (Windows NT 6.1; WOW64;
rv:35.0) Gecko/20100101 Firefox/35.0
if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)){ //test for
Firefox/x.x or Firefox x.x (ignoring remaining digits);
var ffversion=new Number(RegExp.$1) // capture x.x portion and store as
a number
if (ffversion>=35)
document.write("You're using FF 35 or above")
else if (ffversion>=5)
document.write("You're using FF 5.x or above")
else if (ffversion>=4)
document.write("You're using FF 4.x or above")
else if (ffversion>=3)
document.write("You're using FF 3.x or above")
else if (ffversion>=2)
document.write("You're using FF 2.x")
else if (ffversion>=1)
document.write("You're using FF 1.x")
}
else
document.write("n/a")
</script>
Output:
Basically, I'm capturing just the versonMajor.versionMinor portion of the full version number of Firefox (ie: 2.0.0.13 becomes simply 2.0), and using that as basis to detect the various versions of Firefox. Delving any deeper, and the returned version may no longer be a number but a string (ie: 2.0.0), which makes numeric comparisons cumbersome.
Detecting IE x.x
In IE until the advent of IE11, the token "MSIE
"
exist inside the userAgent
property that tells us the pedigree
of the browser. In IE 7.0 for example,
the userAgent
property reads:
UserAgent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)
However, starting in IE11, the userAgent
return value takes a drastic departure from all older versions' of IE.
For example in IE11 Windows 8 the returned string is:
UserAgent: Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko
This is different from previous versions in the following notable ways:
- The compatible ("compatible") and browser ("MSIE") keywords have
been removed, meaning you can no longer just look for "MSIE" in the
userAgent
to sniff out IE in IE11 or above browsers. - The version of the browser is now reported by a new revision ("
rv
") keyword.
Details of the change is discussed in this
IE blog post. With the dramatic change, it means testing for IE now
needs to take two separate routes, one that looks for the "MSIE" token and
version number that follows, and the other, the version number contained
inside the "rv" token where the "Trident" token exists inside the
userAgent
string.
Note that some variants of older IE versions also contain "Trident" in
its userAgent
string, so do not rely just on "Trident" alone to
separate IE11+ from the rest of the herd- it's only the presence of BOTH
"Trident' and a "rv" token that uniquely indicates this is a IE11 or above
browser.
The following detection scheme takes into account this and sniffs out any version of IE:
<script type="text/javascript">
//userAgent in IE7 WinXP returns: Mozilla/4.0 (compatible; MSIE 7.0;
Windows NT 5.1; .NET CLR 2.0.50727)
//userAgent in IE11 Win7 returns: Mozilla/5.0 (Windows NT 6.3;
Trident/7.0; rv:11.0) like Gecko
if (navigator.userAgent.indexOf('MSIE') != -1)
var detectIEregexp = /MSIE (\d+\.\d+);/ //test for MSIE x.x
else // if no "MSIE" string in userAgent
var detectIEregexp = /Trident.*rv[ :]*(\d+\.\d+)/ //test for rv:x.x or rv
x.x where Trident string exists
if (detectIEregexp.test(navigator.userAgent)){ //if some form of IE
var ieversion=new Number(RegExp.$1) // capture x.x portion and store as
a number
if (ieversion>=12)
document.write("You're using IE12 or above")
else if (ieversion>=11)
document.write("You're using IE11 or above")
else if (ieversion>=10)
document.write("You're using IE10 or above")
else if (ieversion>=9)
document.write("You're using IE9 or above")
else if (ieversion>=8)
document.write("You're using IE8 or above")
else if (ieversion>=7)
document.write("You're using IE7.x")
else if (ieversion>=6)
document.write("You're using IE6.x")
else if (ieversion>=5)
document.write("You're using IE5.x")
}
else{
document.write("n/a")
}
</script>
Output:
If you're only interested in detecting IE11 or greater, you
can simply test for the presence of "Trident" while at the same time the
absense of "MSIE" inside userAgent
:
var ie11andabove = navigator.userAgent.indexOf('Trident') != -1 && navigator.userAgent.indexOf('MSIE') == -1 // IE11 or above Boolean
Or, should you only be interested in detecting IE browsers less than 11, the following will do:
var ie10andbelow = navigator.userAgent.indexOf('MSIE') != -1 // IE10 or below Boolean
Detecting Opera 15 and above
Opera starting in Opera 15+ on both desktop and Android uses
the Chromium engine under their hood (the same engine that powers Google
Chrome), and with the brain transplant, now returns a userAgent
string that's more Chrome than Opera. In Opera 25 for example, this is the
returned string:
UserAgent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.101 Safari/537.36 OPR/25.0.1614.50
Straight from Opera itself: On all platforms, the digits after "OPR/" tell you version and minor version number - in this case "25.0" (The subsequent numbers are internal identifiers and build numbers.). Opera 15+ for Android contains the string "Mobile" and also contains "OPR/" followed by version number, as both Opera 15+ for desktop and Android are based on Chromium 28.
This means to detect if the user is using Opera 15+, we can simply look
for the "OPR/" token inside userAgent
, and to detect the
specific version, parse out the floating point number that follows. Here's
an example of each:
var opera15andabove = navigator.userAgent.indexOf('OPR/') != -1 // Opera 15+ Boolean
var opera15andabovever = /OPR\/(\d+\.\d+)/i.test(navigator.userAgent)
// test and capture Opera 15+ version
if (opera15andabovever){
var operaver = new Number(RegExp.$1) // contains exact Opera15+ version,
such as 25 for Opera 25.0
document.write("You're using Opera" + operaver)
}
else{
document.write("n/a")
}
Output:
Detecting old versions of Opera (pre Opera 15)
In Opera pre version 15, there exists a property
window.opera
that returns true to quickly filter out those
browsers as a group. However, getting the exact version gets a lot more
confounding, stemming from the browser's past split personality. You see, Opera 8 and below by default identifies itself as IE6
(or lower) in the navigator
object. Users can override this
setting under "Edit Site Settings" in the toolbar to identify as
Opera or even another browser instead. Starting in Opera 9, the browser
regains its confidence and identifies by default as itself, Opera,
though users can still modify this setting manually in the toolbar. The
bottom line is, Opera can appear as either Opera, Internet Explorer, or
another browser within a designated list in the navigator
object.
Lets take a
look at what navigator.userAgent
in Opera 8.5 returns
depending on what it has chosen to identify itself as (whether
automatically or manually):
As IE6: Mozilla/4.0 (compatible; MSIE 6.0; Windows XP) Opera 8.5
[en]
As Moz5: Mozilla/5.0 (Windows XP; U) Opera 8.5 [en]
As Opera: Opera/8.5 (Windows XP; U) [en]
Notice how if it's set to identify as IE, MSIE 6.0
appears
within the string, while if set to identify as Mozilla,
Mozilla/5.0
appears instead. As Opera itself, Opera/8.5
appears. In all three cases, the one commonality that we can exploit to
actually detect Opera and its true version regardless of which identify
it's decided to take on is the string "Opera x.x
" or "Opera/x.x
"
within navigator.userAgent
. In other words, there are two
versions of the target string we need to be aware of. With that said,
here's how you might go about testing for a specific version of Opera,
which turns out to be no different than the technique used for
detecting, say, Firefox:
<script
type="text/javascript">
//Note: userAgent in Opera9.24 WinXP returns: Opera/9.24 (Windows NT 5.1; U;
en)
// userAgent in Opera
8.5 (identified as IE) returns: Mozilla/4.0 (compatible; MSIE 6.0; Windows
NT 5.1) Opera 8.50 [en]
// userAgent in Opera
8.5 (identified as Opera) returns: Opera/8.50 (Windows NT 5.1; U) [en]
if (/Opera[\/\s](\d+\.\d+)/.test(navigator.userAgent)){ //test for Opera/x.x
or Opera x.x (ignoring remaining decimal places);
var oprversion=new Number(RegExp.$1) // capture x.x portion and store as a
number
if (oprversion>=10)
document.write("You're using Opera 10.x or above")
else if (oprversion>=9)
document.write("You're using Opera 9.x")
else if (oprversion>=8)
document.write("You're using Opera 8.x")
else if (oprversion>=7)
document.write("You're using Opera 7.x")
else
document.write("n/a")
}
else
document.write("n/a")
</script>
Output:
Conclusion
We've seen how to use navigator to detect the browser type of your visitors. If the potential pitfalls and complexity of usage of it is a little too much for you, an alternative is to use Object Detection. Whichever method you choose, just be sure to choose one!