UPDATE 11/30/09: After two years, I have decided to stop maintaining and updating this code. I'm not currently using it and it was getting to be in need of an overhaul with all the devices that keep changing the landscape. I'd suggest the open source DetectMobileBrowser.com.
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.
UPDATE July 2009: Small code clean-up and addition of another false positive exclusion to the "badmatches" array. Please keep those notes and comments coming.
UPDATE August 2009: WebOS added to the uamatches array to catch Palm Pre. Please keep those notes and comments coming.
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("OfficeLiveConnector","MSIE\ 8\.0","OptimizedIE8","MSN\ Optimized","Creative\ AutoUpdate","Swapper");
foreach($badmatches as $badstring){
if(preg_match("/".$badstring."/i",$_SERVER["HTTP_USER_AGENT"])) return false;
}
// Now we'll go for positive matches
$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","webos");
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.
You can now add "iphone" to the badmatches array and have it treated as a false positive if you want to exclude iPhone.
Thanks, and I hope this works for you.