Finally a browser detector you can depend on. Let's face it, with all of the browsers on the market today, you need a slightly more sophisticated tool than just searching for 'MSIE' in the user agent, right?

There are browsers that spoof as other browsers so they get accepted at more sites (Opera spoofing as IE); there are browsers built out of other browsers (AOL browser).

  • How are you supposed to keep up with who's capable of doing what?
  • How many times have you adjusted your detection algorithm?
  • Or does it still just look for IE4 and NS4?
  • Do you want to run the kind of site that rejects an Opera user because your site requires IE 5.x or higher?

Browser detection is not for the faint of heart. That's why you should be using the earthli Browser Detector. We've done all of the leg work for you and come up with a solid approach to picking apart a user agent and getting at the facts.

What's so special about it?

All browser detectors have to work with the user agent string. User agents can happily lie about who they are. A liar will fool any browser detector, including this one. Most browsers don't lie, and even those that spoof can't help writing their name in the user agent string somewhere.

Where this browser detector parts ways with most is that it clearly separates its tasks:

Find out the name of the browser.
That's the name the user's going to recognize. Users are a little confused when you tell them they're browsing with IE when they're clearly using the MSN browser. Users neither know nor care about the branding and the browser wars.
Find out the renderer being used.
This is the part that's important to your web code. Your website couldn't care less whether an MSN or AOL or pure IE browser is making the request: the important detail is which version of IE is making the request
Find out the operating system the browser is running on.
Though most of the cross-platform browsers use cross-platform engines, the most notable one that doesn't is also the most popular. I'm not naming names.

The detector will reliably figure out which browser and operating system is being used, then consults a table of capabilities to let you know if a particular operation should be supported. The algorithm, described below, should be quite forward-compatible (and has indeed proved to be with subsequent browser releases) and only needs to be updated when:

  • A new renderer hits the market, like Safari and Omniweb for the Mac moving to the KHTML platform. Omniweb 5.0 is detected as based on the KHTML renderer, whereas previous versions still identify as based on the Omniweb 4.x platform. OmniWeb 5.x and Safari are the same browser as far as you're concerned because the rendering engine is the same.
  • A renderer suddenly sprouts new capabilities (like Opera did when moving from 6.x to 7.x (Presto)).

The detector is table-driven, so even these types of changes were handled in 'data', without changing the algorithm at all.

What's the super-secret algorithm already?

After careful analysis of an enormous list of available user agents, a few similarities cropped up:

  • Most browsers list a few browsers with which they are compatible. These are specified in order of importance, from left to right. They are there to fool simpler detectors that only do a substring search.
  • The actual name of the browser (MSN, AOL) comes after the list of renderers with which the browser is compatible.
  • Some browsers (IE and Gecko variants) allow plugins to alter the user agent. These are usually appended after the browser's real name.
  • Most browsers include the operating system information somewhere in the user agent.
  • All of these pieces of information are specified as 'name' 'separator' 'version numbers'. The separator is not always the same (can be /-\: or a space).

The earthli Browser Detector then defines a few tables from the information above:

  • A list of names for known rendering technologies.
  • A list of known operating systems.
  • A list of known plugin names.

Armed with these, the algorithm reads from left to right, pulling out name/version pairs and executing the following logic.

  1. Is this a recognized rendering technology?
    1. If no renderer is recorded, use this one.
    2. If this renderer is more specific than the current one, replace it.

      What does this mean? Most browsers specify Mozilla/4.0 compatibility, but they almost always specify a more specific renderer later in the string. That allows things like 'Mozilla/4.0 MSIE/5.0' to be properly recognized as an Internet Explorer rather than Mozilla browser.

  2. Is this an operating system name? (Linux browsers tend to provide specific information)
    1. Record the name and version of the OS.
  3. Is this a known plugin name?
    1. If not, record it as the browser's name and version. The last non-ignored pair encountered is always treated as the browser's true name.
  4. Finish determining the operating system name and version?
    1. Search the user agent for known OS strings that don't necessarily match the name/version pair analyzed in the first phase.

      The information found here is mixed with any OS information already determined above. The OS info is actually available in two parts: system_name and interpreted_system_name. The first is the version info directly extracted from the string; the second is a user-friendly version recognizable to the user. For example, if Windows NT 5.0 is specified in the user agent, interpreted_system_name will return Windows 2000.

How did you test it?

The Phoenix browser (I know, I know, but that's what it was called when I did my tests) provides a preference to change the user agent transmitted in the HTTP header. This was used along with aforementioned list of user agents to spoof as many different browsers in testing.

How do I use it?

All of the cool properties and values discovered during analysis are best used only for displaying or recording information about a browser. Use the supports function to find out whether a browser can or can't do something, like Alpha-PNGs, CSS2 or DHTML. If you need to check a property that isn't covered by supports and its flags, you'll have to use the is and the various name and version functions to do the test yourself.

There is full documentation for every function and property you need. You can look up how supports uses is and version numbers.

If you do come up with a useful check, let me know and we'll build it into supports directly. Or, better yet, do it yourself and mail it to me. I'll post an update with your changes in it.

What about porting? Is this PHP only?

The implementation is PHP only, but the algorithm is quite language-independent and can easily be ported to any other language with regular expressions. At some point, there should be a JavaScript version for those that would rather know all this stuff client-side. If you're in a hurry, try porting it yourself ... it's relatively well-documented and should port pretty much one-to-one.