mozilla

Revision 17913 of Browser detection using the user agent

  • Revision slug: Browser_detection_using_the_user_agent
  • Revision title: Browser detection using the user agent
  • Revision id: 17913
  • Created:
  • Creator: teoli
  • Is current revision? No
  • Comment 332 words added, 1 words removed

Revision Content

Serving different Web pages or services to different browsers are usually bad practices. The Web aimed at a complete accessibility, and at browser agnosticism. Numerous good practices has been identified during the year like progressive enhancement, feature detection or how to write future-compatible Web sites.

But browsers and standards are not perfect and there are still some edge cases where detecting the browser is needed. Using the user agent to detect the browser looks simple, but doing it well is in fact a very hard problem. This document will guide you in doing this as much correctly as possible.

Before relying to browser detection...

When considering the detection of the browser using the user agent, the first step is to try to avoid it. Start by identifying why you want to browser detection:

  • Do you want to go around a specific bug in some version of a browsers?

    Look, or ask, in specialized forums: you're unlikely to be the first to hit this problem. Also experts, or simply people with another point of view, can give you ideas for working around the bug.

    Sometimes start by checking if this bug has been reported to the browser vendor, don't hesitate to asks on forum or to report it on their bug tracking system (For Mozilla: https://bugzilla.mozilla.org ; For Webkit: http://bugs.webkit.org; For Opera: https://bugs.opera.com/) This step may seems unuseful, but it is not! First, contrary to the popular belief, browser makers pay attention to bug reports (though some may pass unnoticed through their triaging teams); second, analysis may hint about other work-around the bug; third, without a bug report, the odds that the bug will be corrected in the futur is lower.
  • Do you want to check the existence of a specific feature?

    Your Web site needs some modern feature and some Web browser still don't detect it. You would like to send to them the old Web site, less fancy, but that you know is working.

    This is the worst case for user-agent sniffing: you don't know what will happen in the future and what browsers unknown to you are supporting. You should try to avoid this case as much as possible.

    To do that, several techniques does exists:
    • Feature detection. You don't try to discover what browser is displaying your page, but you dectect if a specific feature you use is available, if not you trigger the fallback case. Note that you never should use feature detection to perform browser detection. If the given browser add the missing feature in the future, it will be then erroneously recognized for another browser. Bugs resulting for such erroneous detection are often cryptic as difficult to reproduce without the exact same configuration, which is not necessary easy to get, both because the user is often not providing this information and because some browser with low marketshare may be involved (like a beta or alpha version).
    • Progressive enhancement. This design techniques allows the development of Web sites in layers in a bottom-up approach, that is starting with the less fancy layer and improving the capabilities of the site in successive layers.
    • Graceful degradation. Being a top-down approach, this design techniques focus on building the best possible site and then tweaking it to make it work in older browsers. This is more complex and less effective than progressive enhancement, where the content is at the center, not the browser capabilities, but may be useful in some cases
  • Do you want to provide a different HTML in some case?
    You know that this is bad practice, but there are some cases where you need to do that. In these cases, first conduct an analysis if this really needed. Can you prevent this if you add a few non-semantic {{ HTMLElement("div") }} or {{ HTMLElement("span") }} elements. The difficulty to use reliably user-agent detection is worth a few infringement to HTML purity. Also rethought of your design: thinks like progressive enhancement or liquid layouts could help you removing some needs of different HTML for different case.

Identifying the precise information you need

Ok, so now you know that you need UA sniffing. It is the time to determine what exact information you need. Buried in the user agent string you can find these kind of information:

  1. Browser name and version. This looks the most useful information, but most of the time is not: there are numerous browsers out there and most of them use the same engine and therefore will be behave very similarly. Sniffing for browser name and version is the most uncommon case: it is needed to work-around a browser bug, but that's all.
  2. Engine name and version. This is much more useful: even if you should use feature detections as much as possible, to work around about old bugs in the engine, this is the way to go. There are very few engines out there and you will have far less risk to ignore some browsers by doing this.
  3. Mobile or desktop? This is today the most common case of browser sniffing. You want to serve different HTML for mobile and the desktop. To do that, you don't really want to know the OS, the engine or the browser name. What you really want is to know if the browser is mobile or not.
  4. OS Name. This is rarely the good way to do things: it may be useful to work-around some bug related to the OS, in conjunction with some engine. Some people use it as a way to know if the browser is mobile or not, but that's not reliable as an OS like Android is working on laptop and tablet too.

When identifying the precise information you need, be sure not to forget one of the fundamental rules to write forward-compatible Web sites: only tests for older version of browsers or engines and consider unknown results as passing.

Which part of the user agent contains the information you are looking for

As there is no uniformity of the different part of the user agent string, this is the tricky part.

Browser Name and version

Most browser set the name and version in the format BrowserName/VersionNumber format, with the notable exception of Internet Explorer. But as the name is not the only information in a user agent string that is in that format, you can not discover the name of the browser, you can only check if the name you are looking for. But pay attention that some browsers are lying: Chrome for example reports both as Chrome and Safari. So to detect Safari you have to check for the Safari string and the absence of the Chrome string, Chromium often reports himself as Chrome too or Seamonkey sometimes reports himself as Firefox.

Also pay attention not to use a simple regular expression on the BrowserName, user agents also contains strings outside the Keyword/Value syntax. Safari & Chrome contains a string 'like Gecko', for instance.

  Must contains Must not contains  
Firefox Firefox/xyz Seamonkey/xyz  
Seamonkey Seamonkey/xyz    
Chrome Chrome/xyz Chromium/xyz  
Chromium Chromium/xyz    
Safari Safari/xyz Chrome/xyz or Chromium/xyz  
Opera Opera/xyz   Pay attention to the position of the version number at Opera
Internet Explorer ;MSIE xyz;   Internet Explorer doesn't put its name in the BrowserName/VersionNumber format

Of course, there is absolutely no guarantee that another browser will not hijack some of these things (like Chrome hijacked the Safari string in the past). That's why browser detection using the user agent string is unreliable and should be done only with the check of version number (hijacking of past versions are less likely).

Revision Source

<p>Serving different Web pages or services to different browsers are usually bad practices. The Web aimed at a complete accessibility, and at browser agnosticism. Numerous good practices has been identified during the year like progressive enhancement, feature detection or how to write future-compatible Web sites.</p>
<p>But browsers and standards are not perfect and there are still some edge cases where detecting the browser is needed. Using the user agent to detect the browser looks simple, but doing it well is in fact a very hard problem. This document will guide you in doing this as much correctly as possible.</p>
<h2>Before relying to browser detection...</h2>
<p>When considering the detection of the browser using the user agent, the first step is to try to avoid it. Start by identifying <em>why</em> you want to browser detection:</p>
<ul> <li><em>Do you want to go around a specific bug in some version of a browsers?</em><br> <br> Look, or ask, in specialized forums: you're unlikely to be the first to hit this problem. Also experts, or simply people with another point of view, can give you ideas for working around the bug.<br> <br> Sometimes start by checking if this bug has been reported to the browser vendor, don't hesitate to asks on forum or to report it on their bug tracking system (For Mozilla: <a class=" link-https" href="https://bugzilla.mozilla.org" rel="freelink">https://bugzilla.mozilla.org</a> ; For Webkit: <a class=" external" href="http://bugs.webkit.org" rel="freelink">http://bugs.webkit.org</a>; For Opera: <a class=" link-https" href="https://bugs.opera.com/" rel="freelink">https://bugs.opera.com/</a>) This step may seems unuseful, but it is not! First, contrary to the popular belief, browser makers pay attention to bug reports (though some may pass unnoticed through their triaging teams); second, analysis may hint about other work-around the bug; third, without a bug report, the odds that the bug will be corrected in the futur is lower.</li> <li><em>Do you want to check the existence of a specific feature?</em><br> <br> Your Web site needs some modern feature and some Web browser still don't detect it. You would like to send to them the old Web site, less fancy, but that you know is working.<br> <br> This is the worst case for user-agent sniffing: you don't know what will happen in the future and what browsers unknown to you are supporting. You should try to avoid this case as much as possible.<br> <br> To do that, several techniques does exists: <ul> <li>Feature detection. You don't try to discover what browser is displaying your page, but you dectect if a specific feature you use is available, if not you trigger the fallback case. Note that you never should use feature detection to perform browser detection. If the given browser add the missing feature in the future, it will be then erroneously recognized for another browser. Bugs resulting for such erroneous detection are often cryptic as difficult to reproduce without the exact same configuration, which is not necessary easy to get, both because the user is often not providing this information and because some browser with low marketshare may be involved (like a beta or alpha version).</li> <li>Progressive enhancement. This design techniques allows the development of Web sites in layers in a bottom-up approach, that is starting with the less fancy layer and improving the capabilities of the site in successive layers.</li> <li>Graceful degradation. Being a top-down approach, this design techniques focus on building the best possible site and then tweaking it to make it work in older browsers. This is more complex and less effective than progressive enhancement, where the content is at the center, not the browser capabilities, but may be useful in some cases</li> </ul> </li> <li><em>Do you want to provide a different HTML in some case?</em><br> You know that this is bad practice, but there are some cases where you need to do that. In these cases, first conduct an analysis if this really needed. Can you prevent this if you add a few non-semantic {{ HTMLElement("div") }} or {{ HTMLElement("span") }} elements. The difficulty to use reliably user-agent detection is worth a few infringement to HTML purity. Also rethought of your design: thinks like progressive enhancement or liquid layouts could help you removing some needs of different HTML for different case.</li>
</ul>
<h2>Identifying the precise information you need</h2>
<p>Ok, so now you know that you need UA sniffing. It is the time to determine what exact information you need. Buried in the user agent string you can find these kind of information:</p>
<ol> <li>Browser name and version. This looks the most useful information, but most of the time is not: there are numerous browsers out there and most of them use the same engine and therefore will be behave very similarly. Sniffing for browser name and version is the most uncommon case: it is needed to work-around a browser bug, but that's all.</li> <li>Engine name and version. This is much more useful: even if you should use feature detections as much as possible, to work around about old bugs in the engine, this is the way to go. There are very few engines out there and you will have far less risk to ignore some browsers by doing this.</li> <li>Mobile or desktop? This is today the most common case of browser sniffing. You want to serve different HTML for mobile and the desktop. To do that, you don't really want to know the OS, the engine or the browser name. What you really want is to know if the browser is mobile or not.</li> <li>OS Name. This is rarely the good way to do things: it may be useful to work-around some bug related to the OS, in conjunction with some engine. Some people use it as a way to know if the browser is mobile or not, but that's not reliable as an OS like Android is working on laptop and tablet too.</li>
</ol>
<p>When identifying the precise information you need, be sure not to forget one of the fundamental rules to write forward-compatible Web sites: only tests for older version of browsers or engines and consider unknown results as passing.</p>
<h2>Which part of the user agent contains the information you are looking for</h2>
<p>As there is no uniformity of the different part of the user agent string, this is the tricky part.</p>
<h3>Browser Name and version</h3>
<p>Most browser set the name and version in the format <em>BrowserName/VersionNumber</em> format, with the notable exception of Internet Explorer. But as the name is not the only information in a user agent string that is in that format, you can not discover the name of the browser, you can only check if the name you are looking for. But pay attention that some browsers are lying: Chrome for example reports both as Chrome and Safari. So to detect Safari you have to check for the Safari string and the absence of the Chrome string, Chromium often reports himself as Chrome too or Seamonkey sometimes reports himself as Firefox.</p>
<p>Also pay attention not to use a simple regular expression on the BrowserName, user agents also contains strings outside the Keyword/Value syntax. Safari &amp; Chrome contains a string 'like Gecko', for instance.</p>
<table border="1" cellpadding="1" cellspacing="1" style="table-layout: fixed; width: 100%;"> <thead> <tr> <th scope="col"> </th> <th scope="col">Must contains</th> <th scope="col">Must not contains</th> <th scope="col"> </th> </tr> </thead> <tbody> <tr> <td>Firefox</td> <td>Firefox/xyz</td> <td>Seamonkey/xyz</td> <td> </td> </tr> <tr> <td>Seamonkey</td> <td>Seamonkey/xyz</td> <td> </td> <td> </td> </tr> <tr> <td>Chrome</td> <td>Chrome/xyz</td> <td>Chromium/xyz</td> <td> </td> </tr> <tr> <td>Chromium</td> <td>Chromium/xyz</td> <td> </td> <td> </td> </tr> <tr> <td>Safari</td> <td>Safari/xyz</td> <td>Chrome/xyz or Chromium/xyz</td> <td> </td> </tr> <tr> <td>Opera</td> <td>Opera/xyz</td> <td> </td> <td>Pay attention to the position of the version number at Opera</td> </tr> <tr> <td>Internet Explorer</td> <td>;MSIE xyz;</td> <td> </td> <td>Internet Explorer doesn't put its name in the <em>BrowserName/VersionNumber</em> format</td> </tr> </tbody>
</table>
<p>Of course, there is absolutely no guarantee that another browser will not hijack some of these things (like Chrome hijacked the Safari string in the past). That's why browser detection using the user agent string is unreliable and should be done only with the check of version number (hijacking of past versions are less likely).</p>
Revert to this revision