mozilla

Revision 17915 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: 17915
  • Created:
  • Creator: Sheppy
  • Is current revision? No
  • Comment copy edit, more to come; 760 words added, 695 words removed

Revision Content

Serving different Web pages or services to different browsers is usually a bad idea. The Web is meant to be accessible to everyone, regardless of which browser or device they're using. There are ways to develop your web site to progressively enhance itself based on the availability of features rather than by targeting specific browsers.

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 correctly as possible.

Important: It's worth re-iterating: it's very rarely a good idea to use user agent sniffing. You can almost always find a better, more broadly compatible way to solve your problem!

Considerations before using browser detection

When considering using the user agent string to detect which browser is being used, your first step is to try to avoid it if possible. Start by trying to identify why you want to do it.

Are you trying to work around a specific bug in some version of a browser?
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. You can 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 (Mozilla; WebKit; Opera) This step may seem unhelpful, but it is not! First, contrary to popular belief, browser makers pay attention to bug reports (though some may occasionally pass unnoticed through their triaging teams); second, analysis may hint about other work-arounds for the bug; third, without a bug report, the odds that the bug will be corrected in the future is lower.
Are you trying to check for the existence of a specific feature?
Your site needs to use a specific Web feature that some browsers don't yet support, and you want to send those users to an older Web site with fewer features but that you know will work. This is the worst reason to use user agent detection, because odds are eventually all the other browsers will catch up. You should do your best to avoid using user agent sniffing in this scenario.
Do you want to provide different HTML depending on which browser is being used?
This is usually a bad practice, but there are some cases in which this is necessary. In these cases, you should first analyze your situation to be sure it's really necessary. Can you prevent it by adding some non-semantic {{ HTMLElement("div") }} or {{ HTMLElement("span") }} elements? The difficulty of successfully using user agent detection is worth a few disruptions to the purity of your HTML. Also, rethink your design: can you use progressive enhancement or fluid layouts to help remove the need to do this?

Avoiding user agent detection

If you want to try to avoid using user agent detection, there are options in some cases!

Feature detection
Feature detection is where you don't try to figure out which browser is rendering your page, but instead you check to see if the specific feature you need is available. If it's not, you use a fallback. You should, of course, never use feature detection to try to determine which browser you're using, since other browsers may implement the feature in the future, but differently. Bugs caused by this can be insidiously hard to find and fix.
Progressive enhancement
This design technique involves developing your Web site in layers, using a bottom-up approach, starting with a simpler layer and improving the capabilities of the site in successive layers, each using more features.
Graceful degradation
This is a top-down approach in which you build the best possible site using all the features you want, then tweaking it to make it work on older browsers. This can be harder to do, and less effective, than progressive enhancement, but may be useful in some cases.

Identifying the precise information you need

OK, so you've decided you need to do user agent detection. It is the time to determine what exact information you need. Buried in the user agent string you can find this information:

Browser name and version
This looks like it ought to be the most useful version, but it's usually not. That's because there are a lot of browsers out there, but only a handful of engines doing the heavy lifting. In other words, what really matters is the engine. The only time you need the browser name and version is to work around a browser bug, rather than an engine bug. This isn't very common.
Engine name and version
This is much more useful: although you should use feature detection as much as possible, working around old bugs in an engine sometimes is necessary; in that case, this is the information you need. Since there are only a few different engines around, this is the best way to work around their bugs without leaving out some lesser-known browsers that still use one of those engines.
Mobile or desktop
Nowadays, this is the most common reason to do browser sniffing; you want to serve different content depending on whether the reader is on a mobile device or a desktop browser. The OS, engine, or browser name doesn't matter. You just want to know if it's a mobile browser.
Operating system name
This is rarely useful. It might be useful to work around an OS bug that occurs when using a particular engine, but this is incredibly rare.
Note: Some people use the OS name to determine whether or not a browser is mobile, but this is a bad idea, because there are many mobile operating systems, and occasionally new ones come along.

When identifying the precise information you need, be sure not to forget one of the fundamental rules of writing forward-compatible Web sites: only test 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

Since user agent strings don't necessarily have a uniform syntax, this can be tricky.

Browser name and version

Most browsers set the name and version in the format BrowserName/VersionNumber, 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, so you can't simply discover the name of the browser. Instead, you can only look to see if the name you're looking for is there.

But some browsers lie! For example, Google Chrome identifies itself both as Chrome and as Safari. So to detect Safari you have to check for the Safari string and the absence of the Chrome string. Along similar lines, Chromium often reports itself as Chrome as well, and SeaMonkey sometimes reports itself as Firefox.

Also pay attention not to use a simple regular expression on the browser name, since user agents also contain strings that don't use the Keyword/Value syntax. Safari and Chrome contain a string "like Gecko", for instance.

  Must contains Must not contain  
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 a check of the version number (since hijacking of past versions is less likely).

Revision Source

<p>Serving different Web pages or services to different browsers is usually a bad idea. The Web is meant to be accessible to everyone, regardless of which browser or device they're using. There are ways to develop your web site to progressively enhance itself based on the availability of features rather than by targeting specific browsers.</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 correctly as possible.</p>
<div class="warning"><strong>Important:</strong> It's worth re-iterating: it's very rarely a good idea to use user agent sniffing. You can almost always find a better, more broadly compatible way to solve your problem!</div>
<h2>Considerations before using browser detection</h2>
<p>When considering using the user agent string to detect which browser is being used, your first step is to try to avoid it if possible. Start by trying to identify <strong>why</strong> you want to do it.</p>
<dl> <dt>Are you trying to work around a specific bug in some version of a browser?</dt> <dd>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. You can 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 (<a class=" link-https" href="https://bugzilla.mozilla.org" title="https://bugzilla.mozilla.org">Mozilla</a>; <a class=" external" href="http://bugs.webkit.org" title="http://bugs.webkit.org">WebKit</a>; <a class=" link-https" href="https://bugs.opera.com/" title="https://bugs.opera.com/">Opera</a>) This step may seem unhelpful, but it is not! First, contrary to popular belief, browser makers pay attention to bug reports (though some may occasionally pass unnoticed through their triaging teams); second, analysis may hint about other work-arounds for the bug; third, without a bug report, the odds that the bug will be corrected in the future is lower.</dd> <dt>Are you trying to check for the existence of a specific feature?</dt> <dd>Your site needs to use a specific Web feature that some browsers don't yet support, and you want to send those users to an older Web site with fewer features but that you know will work. This is the worst reason to use user agent detection, because odds are eventually all the other browsers will catch up. You should do your best to avoid using user agent sniffing in this scenario.</dd> <dt>Do you want to provide different HTML depending on which browser is being used?</dt> <dd>This is usually a bad practice, but there are some cases in which this is necessary. In these cases, you should first analyze your situation to be sure it's really necessary. Can you prevent it by adding some non-semantic {{ HTMLElement("div") }} or {{ HTMLElement("span") }} elements? The difficulty of successfully using user agent detection is worth a few disruptions to the purity of your HTML. Also, rethink your design: can you use progressive enhancement or fluid layouts to help remove the need to do this?</dd>
</dl>
<h2>Avoiding user agent detection</h2>
<p>If you want to try to avoid using user agent detection, there are options in some cases!</p>
<dl> <dt>Feature detection</dt> <dd>Feature detection is where you don't try to figure out which browser is rendering your page, but instead you check to see if the specific feature you need is available. If it's not, you use a fallback. You should, of course, never use feature detection to try to determine which browser you're using, since other browsers may implement the feature in the future, but differently. Bugs caused by this can be insidiously hard to find and fix.</dd> <dt>Progressive enhancement</dt> <dd>This design technique involves developing your Web site in layers, using a bottom-up approach, starting with a simpler layer and improving the capabilities of the site in successive layers, each using more features.</dd> <dt>Graceful degradation</dt> <dd>This is a top-down approach in which you build the best possible site using all the features you want, then tweaking it to make it work on older browsers. This can be harder to do, and less effective, than progressive enhancement, but may be useful in some cases.</dd>
</dl>
<h2>Identifying the precise information you need</h2>
<p>OK, so you've decided you need to do user agent detection. It is the time to determine what exact information you need. Buried in the user agent string you can find this information:</p>
<dl> <dt>Browser name and version</dt> <dd>This looks like it ought to be the most useful version, but it's usually not. That's because there are a lot of browsers out there, but only a handful of engines doing the heavy lifting. In other words, what really matters is the engine. The only time you need the browser name and version is to work around a browser bug, rather than an engine bug. This isn't very common.</dd> <dt>Engine name and version</dt> <dd>This is much more useful: although you should use feature detection as much as possible, working around old bugs in an engine sometimes is necessary; in that case, this is the information you need. Since there are only a few different engines around, this is the best way to work around their bugs without leaving out some lesser-known browsers that still use one of those engines.</dd> <dt>Mobile or desktop</dt> <dd>Nowadays, this is the most common reason to do browser sniffing; you want to serve different content depending on whether the reader is on a mobile device or a desktop browser. The OS, engine, or browser name doesn't matter. You just want to know if it's a mobile browser.</dd> <dt>Operating system name</dt> <dd>This is rarely useful. It might be useful to work around an OS bug that occurs when using a particular engine, but this is incredibly rare.</dd>
</dl>
<div class="note"><strong>Note:</strong> Some people use the OS name to determine whether or not a browser is mobile, but this is a bad idea, because there are many mobile operating systems, and occasionally new ones come along.</div>
<p>When identifying the precise information you need, be sure not to forget one of the fundamental rules of writing forward-compatible Web sites: only test 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>Since user agent strings don't necessarily have a uniform syntax, this can be tricky.</p>
<h3>Browser name and version</h3>
<p>Most browsers set the name and version in the format <em>BrowserName/VersionNumber</em>, 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, so you can't simply discover the name of the browser. Instead, you can only look to see if the name you're looking for is there.</p>
<p>But some browsers lie! For example, Google Chrome identifies itself both as Chrome and as Safari. So to detect Safari you have to check for the Safari string and the absence of the Chrome string. Along similar lines, Chromium often reports itself as Chrome as well, and SeaMonkey sometimes reports itself as Firefox.</p>
<p>Also pay attention not to use a simple regular expression on the browser name, since user agents also contain strings that don't use the Keyword/Value syntax. Safari and Chrome contain 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 contain</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 a check of the version number (since hijacking of past versions is less likely).</p>
Revert to this revision