views:

1728

answers:

15
+6  Q: 

Browser Detection

What's the best / simplest / most accurate way to detect the browser of a user?

Ease of extendability and implementation is a plus.

The less technologies used, the better.

The solution can be server side, client side, or both. The results should eventually end up at the server, though.

The solution can be framework agnostic.

The solution will only be used for reporting purposes.

A: 

Client side or server side?

Dan
+4  A: 

The JQuery Browser Plugin will do it client-side for you.

What is the jQuery Browser Plugin?

The jQuery Browser Plugin is an addon for jQuery that makes it easy to uniquely identify your visitors' browsers.

What does it do?

It gives you an object in javascript that contains all of the information about the browser being used. It also adds CSS browser selectors, which means you can style elements or write functions for specific browsers, browser versions, layouts, layout versions, and even operating systems. Image of the jQuery Browser Plugin in action.

The plug-in makes $.browser available, which you can re-submit to your server via an AJAX call, if you really need it server-side.

alert($.browser.name);  // Alerts Firefox for me

The plug-in will only be as effective as the browsers it's been tested against, however. The plugin listed above has a list of browsers recognised in it's tests, but there's always the risk that a new browser will come sneaking out (Google Chrome..) that will require a re-write of the recognition rules. That said, this plug-in seems to be regularly updated.

ConroyP
A: 

as Dan said: it depends on the used technology.

For PHP server side browser detection i recommend Harald Hope's Browser detection:

http://techpatterns.com/downloads/php_browser_detection.php

Published under GPL.

Johannes Hädrich
+1  A: 

Since I just posted this in a (now-deleted question) and it's still in my paste buffer, I'll just repost. Note: this is a server-side PHP solution

I currently use the following code for this. It is not nearly an exhausting solution, but it should be easy to implement more browsers. I didn't know about user-agents.org (thanks PConroy), "one of these days" I'll loop through it and see if I can update and add to my list.

define("BROWSER_OPERA","Opera");
define("BROWSER_IE","IE");
define("BROWSER_OMNIWEB","Omniweb");
define("BROWSER_KONQUEROR","Konqueror");
define("BROWSER_SAFARI","Safari");
define("BROWSER_MOZILLA","Mozilla");
define("BROWSER_OTHER","other");

$aBrowsers = array
(
  array("regexp" => "@Opera(/| )([0-9].[0-9]{1,2})@", "browser" => BROWSER_OPERA, "index" => 2),
  array("regexp" => "@MSIE ([0-9].[0-9]{1,2})@", "browser" => BROWSER_IE, "index" => 1),
  array("regexp" => "@OmniWeb/([0-9].[0-9]{1,2})@", "browser" => BROWSER_OMNIWEB, "index" => 1),
  array("regexp" => "@(Konqueror/)(.*)(;)@", "browser" => BROWSER_KONQUEROR, "index" => 2),
  array("regexp" => "@Safari/([0-9]*)@", "browser" => BROWSER_SAFARI, "index" => 1),
  array("regexp" => "@Mozilla/([0-9].[0-9]{1,2})@", "browser" => BROWSER_MOZILLA, "index" => 1)
);

foreach($aBrowsers as $aBrowser)
{
  if (preg_match($aBrowser["regexp"], $_SERVER["HTTP_USER_AGENT"], $aBrowserVersion))
  {
    define("BROWSER_AGENT",$aBrowser["browser"]);
    define("BROWSER_VERSION",$aBrowserVersion[$aBrowser["index"]]);
    break;
  }
}
Twan
Thanx for reposting. The deleted question obviously wasn't very good.
Jrgns
The question itself got a couple of down-votes for some reason, the asker must have decided not to take any further risk on their rep. Can be annoying alright when you've put a fair bit of thought into an answer!
ConroyP
It did start to go down, and I realised the question could be better formatted, so I deleted it. Sorry about the loss of answers...
Jrgns
This is why browser detection is bad. Your code above fails to detect Opera 10 (which is currently in alpha). A perfect example of why feature detection is superior.For reference: `Opera/10.00 (Windows NT 5.2; U; en) Presto/2.2.2`
fearphage
This is obviously easily fixed by updating the corresponding regular expression. @Opera(/| )([0-9]{1,2}.[0-9]{1,2})@ should do the trick. Feature detecting might be outdated less often, but requires maintenance as well. Plus, I'm using this to create clean CSS files (so alongside feature detecting in my scripting).
Twan
+9  A: 

On the server you're pretty much limited to the UserAgent string the browser provides (which is fraught with problems, have a read about the UserAgent string's history).

On the client (ie in Javascript), you have more options. But the best option is to not actually worry about working out which browser it is. Simply check to make sure whatever feature you want to use actually exists.

For example, you might want to use setCapture, which only MSIE provides:

if (element.setCapture) element.setCapture()

Rather than working out what the browser is, and then inferring its capabilities, we're simply seeing if it supports something before using it - who knows what browsers will support what in the future, do you really want to have to go back and update your scripts if Safari decides to support setCapture?

Dan
+3  A: 

When using javascript: Don't use browser detection

Write code that tests itself for given cases exhibited by browsers, otherwise you'll simply be writing code for a very very small population. Its better to use "typeof foo == 'undefined'" and browser specific tricks where you need them.

jQuery does this all over its codebase ( if you look at the code you'll see it implementing behaviours for different browser tecnologies )

Its better in the long run.

Kent Fredric
If you want performance, though, executing checks can be expensive. There are some cases where knowing in advance which techniques to use is better than using error checking and changing course every time you run into one.
Adam Davis
A: 

about what web framework are we talking about?

A: 

A good soultion for those using asp.net is given at the following link: http://www.codeproject.com/KB/aspnet/browsercaps.aspx

rAm
A: 

For internet explorer and Style sheets you can use the following syntax:

<!--[if lte IE 6]><link href="/style.css" rel="stylesheet" type="text/css" /><![endif]-->

This applys to IE 6 or earlier. You can change the IE version and also have:

<!--[if eq IE 7]> = Equal too IE 7
<!--[if gt IE 6]> = Greater than IE 6

Im not sure if this works with other parts of the page but works when placed within the <head> tag. See this example for more information

Toby Mills
+2  A: 

Don't use browser detection:

  • Browser detection is not 100% reliable at the best of times, but things get worse than this:
  • There are lots of variants of browsers (MSIE customisations etc)
  • Browsers can lie about their identity (Opera actually has this feature built-in)
  • Gateways hide or obfuscate the browser's identity
  • Customisation and gateway vendors write their own rubbish in the USER_AGENT

It's better to do feature detection in client-script. You hopefully only need browser-detection to work around a bug in a specific browser and version.

MarkR
A: 

I originally asked the question because I want to be able to record the browsers and operations systems people use to access my site. Yes, the user agent string can't be trusted, and yes, you shouldn't use browser detection to determine what code to run in JS, but, I'd like to have as accurate as possible statistics.

I did the following.

I'm using a combination of JavaScript and PHP to record the stats. JavaScript to determine what browser and OS (as this is probably the most accurate), and PHP to record it:

The JavaScript comes from Quirksmode, the PHP is rather self evident. I use the MooTools JS framework.

Add the following to the BrowserDetect script:

window.addEvent('domready', function() {
    if (BrowserDetect) {
        var q_data = 'ajax=true&browser=' + BrowserDetect.browser + '&version=' + BrowserDetect.version + '&os=' + BrowserDetect.OS;
        var query = 'record_browser.php'
        var req = new Request.JSON({url: query, onComplete: setSelectWithJSON, data: q_data}).post();
    }
});

This determines the browser, browser version and OS of the user's browser, and sends it to the record_browser.php script. The record_browser.php script just add's the information, along with the PHP session_id and the current user_id, if present.

MySQL Table:

CREATE TABLE `browser_detects` (
  `id` int(11) NOT NULL auto_increment,
  `session` varchar(255) NOT NULL default '',
  `user_id` int(11) NOT NULL default '0',
  `browser` varchar(255) NOT NULL default '',
  `version` varchar(255) NOT NULL default '',
  `os` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `sessionUnique` (`session`)
)

PHP Code:

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $session = session_id();
    $user_id = isset($user_id) ? $user_id ? 0;
    $browser = isset($_POST['browser']) ? $_POST['browser'] ? '';
    $version = isset($_POST['version']) ? $_POST['version'] ? '';
    $os = isset($_POST['os']) ? $_POST['os'] ? '';
    $q = $conn->prepare('INSERT INTO browser_detects (`session`, `user`, `browser`, `version`, `os`) VALUES (:session :user, :browser, :version, :os)');
    $q->execute(array(
                    ':session' => $session,
                    ':user' => $user_id,
                    ':browser' => $browser,
                    ':version' => $version,
                    ':os' => $os
                ));
}
Jrgns
A: 

Generally, when a browser makes a request, it sends a bunch of information to you (time, name date, user-agent...). You should try to look at the headers the client sent and go to the one that tells you their browser (I think it's "User-Agent:".

stalepretzel
A: 

As stated by many, browser detection can go very wrong... however in the interests of Code Golf.

This is a very fast way to detect IE.

<script>
  if('\v'=='v'){
    alert('I am IE');
  } else {
    alert('NOT IE');
  }
</script>

Its pretty neat actually because it picks out IE without tripping up on Opera.

Bonus points if you know why this works in IE. ;-)

scunliffe
A: 

OESIS Framework supports programmatic detection and management several browsers. A brief description of the browser module and a list of supported browsers is at http://www.opswat.com/products/oesis-frameworkae/oesis-local/web-browsers

A: 

This is the best and simplest solution I've seen. It's pure Javascript and very light weight, too. It's actually based on the code that JQuery uses for browser detection, but it's been modified a bit to add recognition for Chrome. It's small, simple and gets the browser version number too. Works great for us!

<script type="text/javascript">
    // <![CDATA[
    var BrowserCheck = Class.create({
        initialize: function () {
            var userAgent = navigator.userAgent.toLowerCase();
            this.version = (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1];
            this.safari = /webkit/.test(userAgent) && !/chrome/.test(userAgent);
            this.opera = /opera/.test(userAgent);
            this.msie = /msie/.test(userAgent) && !/opera/.test(userAgent);
            this.mozilla = /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent);
            this.chrome = /chrome/.test(userAgent);
        }
    });    
    // ]]>
</script>

Don't forget that you need to initialize it to use it, so put this in your code:

var UserBrowser = new BrowserCheck();

And then check for a browser type and version like so: (e.g. Internet Explorer 8)

if ((UserBrowser.msie == true) && (UserBrowser.version == 8))

etc.

Hope it does the job for you like it has for us, but remember that no browser detection is bullet proof!

Django Reinhardt