UPDATE: The code has just been tested against the WURFL database of over 6,750 different mobile browser User Agent IDs, and proved 94.34% effective at catching the User Agent IDs in their database, yet providing NO false positives on the 63 most popular browser/OS combos on the desktop. And remember, that's just one of three checks this function performs.

UPDATE #2: Need help using the code in this article? I've written a second article with code to help you handle your mobile users when this piece of code detects them.

UPDATE December 2008: Looks like IE8 has a trick of adding all sorts of software to the user agent string. Someone sent me one that listed the version of Zune software they were using and "Creative AutoUpdate" which was triggering the substring search for "pda", meaning a whole bunch of people were getting false positives on IE8. I've added an exception to catch the "Creative AutoUpdate" string.

UPDATE June 2009: As reported in the comments and occasionally by e-mail, the Office Live Connector in IE 8 was causing false positives with the check to see if you're running an NEC phone. People were adding their own lines to the code to check for this, but I figured I'd group the checks for known false positives the same way the grouping for known positives is done. That way you can just add an item to the array and not keep adding lines and lines of code.

When it comes to detecting PDA and cell phone web browsers visiting your web site, you'd think there would be a standard "hi, I'm a mobile browser" handshake that a mobile browser would send to your server. And if you thought that (like I did), you'd be wrong.

Let's skip the story and get to the PHP code.

While working on a new site, I wanted to make a few pages "mobile aware" so they reformatted themselves for mobile phones. And while I could do some of that with CSS, detecting mobile browsers with PHP so I can customize the HTML that's delivered is even better.

But I found that there's no standardized way this works. A lot of sites had a piece of the puzzle, but most were only partially effective. I even ran across a British doofus who wanted $20 for a commercial license to code that couldn't catch a Treo.

So, what I did, was... hunt the triggers that identify most PDA and phone browsers without scoring false positives on major browsers. I culled through huge lists of User Agent IDs to find unique bits I could test for, plus found a couple of other tests at various sites, and pulled them all together. Oddly enough, despite all the pages I went to that discussed how to do this, none of them did all of these tests.

I've tested the following code against 63 desktop browser versions across Linux, Mac, and multiple versions of Windows, using a free trial at BrowserCam. From Konqueror to AOL to Opera to Firefox to IE, no false positives. That pretty much guarantees no false positives for 99.9% of your visitors using desktop browsers.

For catching mobile browsers, it's caught every mobile browser I've thrown at it... 3 real ones (Palm Blazer, Opera Mini, Google's web to plain old text converter) and 2 simulated ones (Sony K750, Nokia N70). It also scored 94.34% against a database of 6,788 mobile browser User Agent ID codes via the WURFL database. And since its WURFL score was only based on one of three different tests the script does, and the ones it wasn't catching were from more obscure browsers, I'd estimate this little chunk of code should be able to identify 97% of mobile visitors, if not more.

function checkmobile(){

if(isset($_SERVER["HTTP_X_WAP_PROFILE"])) return true;

if(preg_match("/wap\.|\.wap/i",$_SERVER["HTTP_ACCEPT"])) return true;

if(isset($_SERVER["HTTP_USER_AGENT"])){

// Quick Array to kill out matches in the user agent
// that might cause false positives

$badmatches = array("Creative\ AutoUpdate","OfficeLiveConnector","MSIE\ 8\.0");

foreach($badmatches as $badstring){
if(preg_match("/".$badstring."/i",$_SERVER["HTTP_USER_AGENT"])) return false;
}

// Now we'll go for positive matches

if(preg_match("/Creative\ AutoUpdate/i",$_SERVER["HTTP_USER_AGENT"])) return false;

$uamatches = array("midp", "j2me", "avantg", "docomo", "novarra", "palmos", "palmsource", "240x320", "opwv", "chtml", "pda", "windows\ ce", "mmp\/", "blackberry", "mib\/", "symbian", "wireless", "nokia", "hand", "mobi", "phone", "cdm", "up\.b", "audio", "SIE\-", "SEC\-", "samsung", "HTC", "mot\-", "mitsu", "sagem", "sony", "alcatel", "lg", "erics", "vx", "NEC", "philips", "mmm", "xx", "panasonic", "sharp", "wap", "sch", "rover", "pocket", "benq", "java", "pt", "pg", "vox", "amoi", "bird", "compal", "kg", "voda", "sany", "kdd", "dbt", "sendo", "sgh", "gradi", "jb", "\d\d\di", "moto");

foreach($uamatches as $uastring){
if(preg_match("/".$uastring."/i",$_SERVER["HTTP_USER_AGENT"])) return true;
}

}
return false;
}

It's pretty simple. Line 1 of the function checks to see if the browser is sending a WAP profile. No desktop browser would want or need to, and based on my testing, none do. OTOH, Blazer on my Treo 700p sends one, but Opera Mini doesn't, so it's far from the only test needed.

The second line looks for WAP formats in the HTTP Accept string, which tells the server the types of content the browser can accept.

The rest of the code checks the User Agent ID for bits of text that you'll find in mobile browser IDs but not in the IDs of major desktop browsers. Each of these text snippets are meaningful indicators pulled from real PDA and mobile phone User Agent IDs.

If you'd like to test this code, I've got a test page at http://www.brainhandles.com/testmobile.php. Not only will it tell you if your browser registers as mobile, but what tests out of the three (WAP profile, WAP accepted, User Agent substrings) your mobile browser scored a hit on. If the script scores a false positive (desktop browser shows up as mobile) or doesn't identify your mobile browser as mobile, instructions for reporting it are provided.

SECOND UPDATE: It's been brought to my attention that some site owners like the iPhone's method of rendering regular (i.e. not optimized for mobile) pages and want to exclude the iPhone from the list. Luckily, the Safari on the iPhone is nice enough to identify itself in its User Agent ID. To exclude the iPhone, add in the following line of code near the top as the first check the script performs.

if(preg_match("/iphone/i",$_SERVER["HTTP_USER_AGENT"])) return false;

That will create an exclusion for the iPhone and treat it as if it were a desktop browser.

Thanks, and I hope this works for you.

  • Share/Save/Bookmark
34 Responses to “Detecting Mobile Browsers”
  1. HeavyWave says:

    Will it detect Opera Mobile?

  2. Greg Bulmash says:

    @HeavyWave,

    Opera Mini (the java based version of Opera for mobile phones) is detected by the script.

    You can test this by going to the Opera Mini Simulator and then browsing to my test page at http://www.brainhandles.com/testmobile.php

  3. HeavyWave says:

    Didn't know there's a simulation. I just used my phone to check. :)

    Nice script, thanks a lot.

  4. [...] #1 Web sites can automatically detect what platform a visitor is accessing the site through. Go to facebook.com on your phone, you end up at m.facebook.com. Its hassle-free to the end user. [...]

  5. [...] While a lot of people have written in with kudos on my PHP code for detecting mobile browsers, others have written in with questions on how to use it. [...]

  6. Alex Grim says:

    DIGG: This link does not appear to be a working link. Please check the URL and try again.

    Sorry, i tried to digg ya. Great job man.

  7. john says:

    Opera Mini and Opera Mobile are different...

    http://www.opera.com/products/

    [Editor's Note: But in his follow-up, HeavyWave said he'd checked the script/demo with his phone, so it's a bit of a moot point.]

  8. whoever says:

    If we're to believe http://www.mobileopera.com/reference/ua , Opera Mobile should be detected no problem, since it contains a platform and device strings at the very least in the UA string.

    Anyway, thank you from me aswell for this code snippet. Works like a charm ;)

    P.S.: it was interesting to find out that preg_match is actually faster than stripos. I always assumed it'd be the opposite :P

  9. jane says:

    Hi,

    I'm just learning PHP.

    Can you explain to me why you do the foreach loop -- rather than just formatting $uamatches directly in regex syntax?

    Is this more efficient processing, or more organized for you, or avoids some possible error getting thrown?

    Thanks!

  10. Greg Bulmash says:

    Jane,

    This is actually complex enough an answer to deserve its own post.

    - Greg

  11. Larry says:

    Script looks great but I wish you had a ASP/vbscript version.....Like your site by the way....

    Larry

  12. kier says:

    Larry,

    detection for browsers in ASP(VBScript):

    <%
    str = Request.ServerVariables("http_user_agent")
    if InStr(1, str, "msie", 1) 0 then
    browserIE = "true"
    elseif InStr(1, str, "firefox", 1) 0 then
    browserFirefox = "true"
    elseif InStr(1, str, "safari", 1) 0 then
    browserFirefox = "true"
    elseif InStr(1, str, "iphone", 1) 0 then
    browserIPhone = "true"
    end if

    if browserIPhone "" then response.redirect ("index_iphone.asp")

    %>

    pretty long winded but effective none the less, hope it helps!!

    Kier

    Greg's Note: This is a browser "sniffer" looking for "Msie", "Firefox", "Safari", or "iphone" in the user_agent string and then setting a string related to that browser as true. You'll need to act upon whether browserIE, browserFirefox (which it sets to true for Firefox or Safari), or browserIPhone is true, not on whether a mobile browser has been detected. And if you base your action on just that, a lot of smaller browsers that are desktop-based, but don't use one of those 4 strings in their user_agent strings, will be treated as mobile browsers.

    Also, unless you have a specific page for an IPhone at index_iphone.asp, you may want to take out the last line of code.

  13. Greg Harris says:

    Awesome!

    I just created a SQL Server function using C# and .NET to build a pre-screener before we hit WURFL and other device databases. This post directly influenced the final code. Thanks for the ideas! I can now do this right in a database query, thousands of user-agents in seconds.

    Thanks!

    Greg Harris
    http://www.mobilytics.net

  14. Brandon Eley says:

    It seems that the checkmobile function creates a false positive on AOL 10. I have the function exactly as you have it here, and it is returning true on the preg_match on the 'eric' user agent string.

    In looking at the Sony/Ericsson user agents, I think changing it to 'erics' should work. Please let me know what you come up with also.

  15. [...] found this script at http://www.brainhandles.com/2007/10/15/detecting-mobile-browsers/ that detects mobile phones. It’s very simple to implement. I call this script and use it to [...]

  16. James Duvall says:

    Thanks Greg! It works great.

  17. sd says:

    I wondered why my Firefox (on a regular Windows PC) was detected as "mobile" by a lot of sites, that wanted then to display me their "mobile" version.
    Turns out that I had once an extension to enable it to wiew WAP, so the option (in "about:config") "network.http.accept.default" was set to "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5,text/vnd.wap.wml;q=0.6".
    I reseted it to default value and all works well since then.

    So it could be a hint for people that would like to test their mobile site on a regular Firefox; just change "network.http.accept.default" accordingly.

  18. ansgar says:

    Hi, thanks for your snippet!

    There's a false positive wir following user agent:

    Microsoft Internet Explorer 4.0 (compatible; MSIE 7.0; Windows NT 6.0; FunWebProducts; SIMBAR={EE6D7371-250B-4A40-9B2F-C9311D99A0D6}; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506; Swapper 1.0.6)
    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; FunWebProducts; SIMBAR={EE6D7371-250B-4A40-9B2F-C9311D99A0D6}; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506; Swapper 1.0.6)

    I assume "Swapper" triggers this.

  19. Greg Bulmash says:

    Yup, Swapper does. It triggers the WAP substring identifier. Which phone/browser is this from?

  20. ansgar says:

    I'm not quite sure, I guess it's a IE 7 with some weird extension. On a desktop, no phone.

  21. Oliver says:

    Hi there

    I'm up against a strange one.

    I've built a "project room" feature that dynamically generates an RSS feeds using mod_rewrite to parse the URL - e.g. http://www.spyfilms.com/projects/feed/ben_steiger_levine/showreel - and the Zend Framework to generate the feed based on the resulting variables.

    I want iPhone users directed to the feed to be served scaled-down m4v files as the feed enclosures and everyone else - browsers, feed readers, iTunes, etc - QuickTime files of much higher resolution.

    The problem is that the user agent string when viewing a feed is not the standard iPhone / iPod ua, but Apple-PubSub/65.1.1, regardless of whether the browser is desktop or mobile: i.e. *any* version of Safari has the same user agent string when viewing a feed.

    Any suggestions on how t differentiate them?

  22. Kenny says:

    Hi Everyone-

    Sorry, I don't have a solution for you Oliver but I really need to ask a question to all developers of this PHP redirect script..... I actually use the script and it works flawlessly! but my host just informed me that they do not support PHP on their server. Can someone help me convert the above redirect script to ASP VB script ????

    Thanks!

  23. Laurent says:

    have you ever considered using uaprof instead of user-agent for mobile detection? There are many different user agent versions for the same phone (same specifications) while there are only a few uaprofs for every handset models. My detection mechanism is based on uaprof and uses user agent as a back up, it's working quite well.

    You can try it out here: http://www.mobilemultimedia.be/en/
    Check out for MobileDetect, it's a free API to insert mobile detection in your pages.
    Tell me what you think.

    Thanks
    Laurent

  24. Ben says:

    Very nice! Works well. You saved me the trouble of looking up all HTTP_USER_AGENT possibilities.

    Thanks a lot!

    Ben

  25. Synapticfury says:

    Thanks for this script. I thought I should update everyone on a problem I'm having. A lot of user agents have "OfficeLiveConnector" in them which triggers the substring search for "NEC" causing a lot of false positives. A few other false positives include user agents with "MSN Optimized" which triggers the substring search for "pt" and "SeekmoToolbar" (spyware) which triggers the substring search for "moto". I have corrected them in a manner similar to the "Creative AutoUpdate" fix. These three cases account for 99% of my false positives so far, so hopefully we'll have clear sailing from here on out.

  26. himenez says:

    Hi,
    I want to suggest a good solution, it's call "Apache Mobile FIlter".
    The URL of the project is: https://sourceforge.net/projects/mobilefilter/

  27. vinod says:

    my company have 2 versions one mobile and regular website,
    my problem is when i accessing the website in opera 9.60 it takeing me to mobile version is there any solution or setting to take to regular website in asp mobile detection code..

    thanks in advance..

  28. Keith says:

    I use IE8 and was getting the false positive, so I researched a bit and found out that Microsoft is sending a Trident user agent. I modified the code as appears below and it now works perfect. Thanks for the script. Its great.

    if(preg_match("/Trident/i",$_SERVER["HTTP_USER_AGENT"])) return false;

  29. Keith says:

    Checked my site with my wife's laptop which has not gone to IE8 and found that it was routing to the WAP site. So, I replaced the if(preg_match("/Creative\ AutoUpdate/i",$_SERVER["HTTP_USER_AGENT"])) return false; which didn't seem to have any effect. So, I added the following line if(preg_match("/MSIE/i",$_SERVER["HTTP_USER_AGENT"])) return false;. Now it seems to work just fine. I can't test with other versions of IE or Mozilla, so if anyone else notices a problem please tell me.

    Thanks.

  30. Toby says:

    Thanks. The algorithm works very well, though I did have to make a few tweaks.

    First, I removed "pt" from the list of strings to search through, because that is the language code for Portuguese and I had a user agent string with that code. What type of mobile device was this supposed to detect, and is there another string that can be used instead?

    Second, I added "archos" to the list. When I saw this user agent string, "Opera/9.02 (Linux armv5tejl; U; ARCHOS; GOGI; a605; en),Opera 9.02", I did a Google search, and it does represent a mobile device.

  31. Idel says:

    I have published the new version of Apache Mobile Filter, now the filter is give to you the information of capabilities as apache environment.
    Now you can develope in any language (php,jsp, ruby etc.) and have the information of mobile capability.

    Read more info here: http://www.idelfuschini.it/it/apache-mobile-filter-v2x.html

  32. Luke Dearnley says:

    Hi Greg,

    thank you for an excellent script. I have used it on some sites.

    Recently however I had a few people using IE7 (on a desktop machine) who were complaining they got redirected to the mobile version of our site.

    After a bit of frigging round I discovered they had the string OfficeLiveConnector in their User Agent which was triggering the script to think they were browsing from an NEC phone (since it contains the letters NEC)

    To fix this I added a line into your script after this one:

    if(preg_match("/Creative\ AutoUpdate/i",$_SERVER["HTTP_USER_AGENT"])) return false;

    and that line is:

    if(preg_match("/OfficeLiveConnector/i",$_SERVER["HTTP_USER_AGENT"])) return false;

    maybe you would consider adding this to your script above. Or if not hopefully people using this great script and having the same problem will read this comment and have their problem solved.

    thanks again
    :L

  33. Luke Dearnley says:

    oh just noticed SynapticFury already mentioned OfficeLiveConnector.... oops!

  34.  
Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>


Register Login
Get an angel for your site An Angel Watches Over This Site