Lightweight Device-Detection in PHP

One problem that keeps cropping up when developing mobile content is how to differentiate between mobile devices and desktop browsers. We need to be able to do this before we can think about content adaptation. The "proper" way to do this is to use a full device detection database such as DeviceAtlas (see our tutorial here) but the following method may be sufficient to get you started.

Update: We have an improved version of the algorithm which includes tablet detection here.

This PHP code implements a mobile device detection algorithm that works for a good percentage of mobile browsers out there. This code is the work of Andy Moore. The algorithm used is fairly lightweight—the code is mostly based on a list of about 90 well-known mobile browser User-Agent string snippets, with a couple of special cases for Opera Mini, the W3C Default Delivery Context and some other Windows browsers. The code also looks to see if the browser advertises WAP capabilities as a hint.

In our experience, this code does a fairly good job. It could probably be improved but it's certainly not a bad start, and is lightweight enough not to cause major problems. For more accurate detection and increased performance we recommend using a dedicated device detection such as DeviceAtlas. Doing so will result in much higher performance, reduced load on your server and much better accuracy.

The changes changes made from Andy's original version are:

  • Adding the W3C User-Agent string (Default Delivery Context)
  • Special case detection for Opera Mini
  • Catch-all exception for devices with Windows in the UA string (Opera 9 for Windows was being recognised as a mobile device)
  • Android User-Agent snippet added

If anyone has any improvements on this code, or implementations for other languages, please let us know!

See also an ASP version.

45 Comments

  • cwbash says:

    I’ve got this code running and find everything fine down to the line which says
    if($mobile_browser>0)
    do something

    What I’d like to do at that point is redirect this link to another page. I’m told from other articles that the solution is to use “header (Location:”, but when I do so, I’m told “Cannot modify header information – headers already sent”.

    There’s nothing in my php script except the php code (line 1 is the “< ?php" so the classic example of inserting HTML at the beginning hasn't been done. Any thoughts about why headers have already been sent? I would like suggestions about how to "do something" that can stay on the server. If I can't, can you supply code that would set an HTML or Javascript variable so just a few lines on the client would do the redirect? You can see my full code at http://www.lighthousesrus.org/mobile/test.php

  • robman says:

    Hi Ronan,

    I’d be interested in what you (and the people that are using your script) think of the discussion I’ve started with James (see my post here).

    I think there’s some real benefits in turning your approach around the other way – we call this the “Not-Device” Detection Strategy.

    From our experience over the last 2 years this provides better coverage and better performance, without the maintenance issues as new devices are released.

    roBman

  • pascalv says:

    I used the original code, and changed the comments given above.

    Also I changed the detection for “windows”. If there is a “Windows CE”, then it doesn’t have to look further.

    My new changed code:


    $mobile_browser = '0';

    if(preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone)/i', strtolower($_SERVER['HTTP_USER_AGENT']))) {
    $mobile_browser++;
    }

    if((strpos(strtolower($_SERVER['HTTP_ACCEPT']),'application/vnd.wap.xhtml+xml')>0) or ((isset($_SERVER['HTTP_X_WAP_PROFILE']) or isset($_SERVER['HTTP_PROFILE'])))) {
    $mobile_browser++;
    }

    $mobile_ua = strtolower(substr($_SERVER['HTTP_USER_AGENT'],0,4));
    $mobile_agents = array(
    'w3c ','acs-','alav','alca','amoi','audi','avan','benq','bird','blac',
    'blaz','brew','cell','cldc','cmd-','dang','doco','eric','hipt','inno',
    'ipaq','java','jigs','kddi','keji','leno','lg-c','lg-d','lg-g','lge-',
    'maui','maxo','midp','mits','mmef','mobi','mot-','moto','mwbp','nec-',
    'newt','noki','oper','palm','pana','pant','phil','play','port','prox',
    'qwap','sage','sams','sany','sch-','sec-','send','seri','sgh-','shar',
    'sie-','siem','smal','smar','sony','sph-','symb','t-mo','teli','tim-',
    'tosh','tsm-','upg1','upsi','vk-v','voda','wap-','wapa','wapi','wapp',
    'wapr','webc','winw','winw','xda','xda-');

    if(in_array($mobile_ua,$mobile_agents)) {
    $mobile_browser++;
    }

    if (strpos(strtolower($_SERVER['ALL_HTTP']),'operamini')>0) {
    $mobile_browser++;
    }

    if (strpos(strtolower($_SERVER['HTTP_USER_AGENT']),' ppc;')>0) {
    $mobile_browser++;
    }

    if (strpos(strtolower($_SERVER['HTTP_USER_AGENT']),'windows ce')>0) {
    $mobile_browser++;
    }
    else if (strpos(strtolower($_SERVER['HTTP_USER_AGENT']),'windows')>0) {
    $mobile_browser=0;
    }

    if (strpos(strtolower($_SERVER['HTTP_USER_AGENT']),'iemobile')>0) {
    $mobile_browser++;
    }

    if($mobile_browser>0) {
    // do something
    // YES MOBILE
    }
    else {
    // do something else
    // NOT MOBILE
    }

  • torweb says:

    I have a version of this working but the above looks better. My question is how do I complete the code…the part:

    if($mobile_browser>0) {
    // do something
    // YES MOBILE
    }
    else {
    // do something else
    // NOT MOBILE
    }

    I’m new at this….

    Thanks

  • onesearch says:

    Hi, Dont want to sound stupid, but, New to PHP and was wondering the same as the last message, What do i replace/add to complete the code.

    Thanks in Advance

  • magicman2000 says:

    has anyone tried a web service like handsetdetection.com? I think that it is PHP friendly

  • JMANJ says:

    Thanks for this code ! After some tests we identified a problem with Macintosh browsers such like Opera.
    For example, the UserAgent of a typical Opera installation on Mac OS is : “Opera/9.63 (Macintosh : PPC Mac OS X : U : fr) Presto / 2.1.1”

    In this case, the code identifies the browser like a mobile_browser which is not the case. It comes from the $mobile_agents array which contains the string “oper”. So each Opera browser on Macintosh is seen like a mobile browser (not the on Windows because of the ‘windows’ test).

    Any idea on a patch to avoid that (deleting “oper” string doesn’t look like the best solution) ?
    Thanks in advance,
    Jmanj

  • EseMismo says:

    Hi,

    I’ve been reading recently some posts, and maybe a little explanation ’bout basic app architecture could bring some light – where to go, and how to take advantage of the “location” function.
    This post has a twofold goal:
    * Show an explicit URL to go (wether mobile or not)
    * Overcome the infamous “Cannot modify header information – headers already sent” error message 😉

    What you need is a page that looks something like this:

    [code]
    < ? PHP /* Put here any PHP code - i.e. the detection script AND/OR any functions, includes, etc. ... ... */ /* Now, it's **VERY IMPORTANT** This holds the entire page's output buffer, until it's time to SEND HEADERS */ [b]ob_start();[/b] ?>



    < ? PHP if($mobile_browser>0) {
    // YES MOBILE – do something
    header(“Location: mobile.php”); // go to mobile URL
    }
    else {
    // NOT MOBILE – do something else
    header(“Location: desktop.php”); // go to desktop URL
    }

    /*
    Now, it’s **VERY IMPORTANT AGAIN**
    This allows headers & content to be sent to the browser
    */
    [b]ob_end_flush();[/b]
    ?>

    [/code]

    Really, this example could grow a bit more, to become something called “page controller” (look in Google or Wikipedia for more on programming patterns): you have an almost blank “index” page, and depending on some conditions, you execute or call (include or require) one or another “code chunk”.
    Of course, this is just a skeleton – you should taylor it to your specific needs – but while being basic, it works.
    Hope you find it useful.

    EseMismo

  • john.boxall says:

    Be careful with this kind of thing – you’re playing with fire.

    This script will [b]always[/b] redirect mobile devices to the mobile page – depending on how well you’ve designed your mobile site and whether you’ve hidden functionality or not – this may not always be what the user wants.

    Play it safe and allow the user a way to force either the full or mobile versions of the site – you can do this easily with an extra GET parameter on requests:

    In your HTML always include likes to both versions of the site w/ the special force mode parameters:
    [code]
    View Mobile Site
    View Full Site[/code]

    In your PHP always check for the parameters before you do the User-Agent happy dance:
    [code]
    < ?php if ($_GET['mobile']) { $is_mobile = true; } if ($_GET['full']) { $is_mobile = false; } [/code] Cheers, John P.S Dotmobi dudes, this input box is super small - we're not typing a tweet here - this is for a post! [b]Update[/b] in my habit of reading the oldest posts first I missed James’ post on doing what I described above.

  • microgers206 says:

    hey guys, i am currently building a buddy of mine a web site for his business, and I am trying to create a mobile site (as his index is a flash intro, and cannot be seen by most mobile devices.) I am extremely new to the mobile device web design, and am not too experienced with php or asp. Can you give me a step by step to introducing this redirect on my site? thank you very much and greatly appreciated.

  • ifuschini says:

    Hi,
    you can use Apache Mobile Filter and the keep the information of capability as environment variable, I think it’s a good solution for work with any language supported with Apache Web Server (Ruby, PHP, JSP, perl).

    See the info here: http://www.idelfuschini.it/it/apache-mobile-filter-v2x.html

  • Teli says:

    ————————

    Hello –

    The above code does not work and the original code does not work either. Ofcourse, I justed copied and pasted the code but have had no luck and ideas would be appricated.

    Thanks for your time,
    Teli

  • David123 says:

    My php script except the php code (line 1 is the “< ?php" so the classic example of inserting HTML at the beginning hasn't been done. Any thoughts about why headers have already been sent? I would like suggestions about how to "do something" that can stay on the server

  • David123 says:

    Thank you for your expression of picture I’ll just try my iphone device…

  • turbowebguy says:

    Why not just make a landing page with an option: [b]Click here for mobile site[/b]
    I’m kidding. Great page, cool site, lots of info.

  • econn_designer says:

    Hello Everyone

    I am new in making mobile based website. My question is :
    [i]My website is fully static and made in simple html pages. I have made the mobile version and make its subdomain “www.m.abc.com”
    Now is there any script which can redirect the user when he/she open my website on mobile and redirect he/she when seeing my website on desktop

    Will wait for your help
    Regards

  • whoisstan says:

    made a very compact php mobile detection method if you need one:

    function is_mobile(){
    $regex_match="/(nokia|iphone|android|motorola|^mot\-|softbank|foma|docomo|kddi|up\.browser|up\.link|";
    $regex_match.="htc|dopod|blazer|netfront|helio|hosin|huawei|novarra|CoolPad|webos|techfaith|palmsource|";
    $regex_match.="blackberry|alcatel|amoi|ktouch|nexian|samsung|^sam\-|s[cg]h|^lge|ericsson|philips|sagem|wellcom|bunjalloo|maui|";
    $regex_match.="symbian|smartphone|midp|wap|phone|windows ce|iemobile|^spice|^bird|^zte\-|longcos|pantech|gionee|^sie\-|portalmmm|";
    $regex_match.="jig\s browser|hiptop|^ucweb|^benq|haier|^lct|opera\s*mobi|opera\*mini|320x320|240x320|176x220";
    $regex_match.=")/i";
    return isset($_SERVER['HTTP_X_WAP_PROFILE']) or isset($_SERVER['HTTP_PROFILE']) or preg_match($regex_match, strtolower($_SERVER['HTTP_USER_AGENT']));
    }

  • 1kipp says:

    To WHOISSTAN,
    I havent tried your code above yet but i believe it works fine. Now, how is a mobile device redirected? I havent seen any redirecting codes or links, thanks.

  • mobiforgestinks says:

    @WHOISSTAN, thanks a million for your concise code. Works as expected.

    @1KIPP and @everyone,

    To use WHOISSTAN’s code, include an IF statement. For example:
    [code]if(is_mobile()) {
    //it’s a mobile browser, do something
    header(“Location: http://www.yoursite.com/mobile“);
    } else {
    //it’s not a mobile browser, do something else
    header(“Location: http://www.yoursite.com/desktop“);
    }[/code]

  • Daniel2010 says:

    [quote=whoisstan]made a very compact php mobile detection method if you need one:[/quote]

    where do i put my html code in this, can you show an example of how i would do this?

    thanks,
    dan

  • vilehelm says:

    This was really helpful. Thanks.

    I had an instance where it made sense to push an iPad to alternative mobile content (instead of a flash site) so I added this snippet:

    [code]if (strpos(strtolower($_SERVER[‘HTTP_USER_AGENT’]),’ipad’)>0) {
    $mobile_browser++;
    }
    [/code]

    Worked like a peach.

    Thanks again.

Other Afilias Products

Try the world’s leading device detection solution at
DeviceAtlas - Try the world’s leading mobile device detection solution

Create amazing web presences on any screen with
goMobi - Create amazing web presences on any screen.

Evaluate your websites’ mobile readiness with
mobiReady - Evaluate your websites’ mobile readiness.

© 2016 Afilias Technologies Ltd. All rights reserved.

This is a website of Afilias Technologies Ltd, a private company limited by shares, incorporated and registered in the Republic of Ireland with registered number 398040 and registered office at 6th Floor, 2 Grand Canal Square, Dublin 2, Ireland