reliable user browser detection with php

96,410

Solution 1

Using an existing method (ie get_browser) is probably better than writing something yourself, since it has (better) support and will be updated with newer versions. There might be also usable libraries out there for getting the browser id in a reliable way.

Decoding the $_SERVER['HTTP_USER_AGENT'] is difficult, since a lot of browsers have quite similar data and tend to (mis)use it for their own benefits. But if you really want to decode them, you could use the information on this page for all available agent ids. This page also shows that your example output indeed belongs to IE 7. More information about the fields in the agent id itself can be found on this page, but as I said already browsers tend to use it for their own benefits and it could be in a (slightly) other format.

Solution 2

Check this code , I've found this is useful. Don't check Mozilla because most browser use this as user agent string

if(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE)
   echo 'Internet explorer';
 elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Trident') !== FALSE) //For Supporting IE 11
    echo 'Internet explorer';
 elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox') !== FALSE)
   echo 'Mozilla Firefox';
 elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== FALSE)
   echo 'Google Chrome';
 elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini') !== FALSE)
   echo "Opera Mini";
 elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== FALSE)
   echo "Opera";
 elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') !== FALSE)
   echo "Safari";
 else
   echo 'Something else';

Solution 3

User Agent can be faked and its better not to depend upon user agent string rather then you can use a CSS3 media queries if you only want to detect orientation (you can explore the CSS of the famous responsive framework bootstrap to check how you can handle the orientation part using CSS)

Here is little CSS :

    @media only screen and (max-width: 999px) {
     /* rules that only apply for canvases narrower than 1000px */
    }

    @media only screen and (device-width: 768px) and (orientation: landscape) {
    /* rules for iPad in landscape orientation */
    }

    @media only screen and (min-device-width: 320px) and (max-device-width: 480px) {
    /* iPhone, Android rules here */
    }    

Read more : About CSS orientation detection

OR You can find the orientation using JavaScript :

    // Listen for orientation changes
    window.addEventListener("orientationchange", function() {
        // Announce the new orientation number
        alert(window.orientation);
    }, false);

Read more : About detect orientation using JS

Finally if you really wants to go with user agent string then this code will help you alot, work fine almost on every browser :

<?php
class BrowserDetection {

    private $_user_agent;
    private $_name;
    private $_version;
    private $_platform;

    private $_basic_browser = array (
       'Trident\/7.0' => 'Internet Explorer 11',
    'Beamrise' => 'Beamrise',
    'Opera' => 'Opera',
    'OPR' => 'Opera',
    'Shiira' => 'Shiira',
    'Chimera' => 'Chimera',
    'Phoenix' => 'Phoenix',
    'Firebird' => 'Firebird',
    'Camino' => 'Camino',
    'Netscape' => 'Netscape',
    'OmniWeb' => 'OmniWeb',
    'Konqueror' => 'Konqueror',
    'icab' => 'iCab',
     'Lynx' => 'Lynx',
    'Links' => 'Links',
    'hotjava' => 'HotJava',
    'amaya' => 'Amaya',
    'IBrowse' => 'IBrowse',
    'iTunes' => 'iTunes',
    'Silk' => 'Silk',
    'Dillo' => 'Dillo', 
    'Maxthon' => 'Maxthon',
    'Arora' => 'Arora',
    'Galeon' => 'Galeon',
    'Iceape' => 'Iceape',
    'Iceweasel' => 'Iceweasel',
    'Midori' => 'Midori',
    'QupZilla' => 'QupZilla',
    'Namoroka' => 'Namoroka',
    'NetSurf' => 'NetSurf',
    'BOLT' => 'BOLT',
    'EudoraWeb' => 'EudoraWeb',
    'shadowfox' => 'ShadowFox',
    'Swiftfox' => 'Swiftfox',
    'Uzbl' => 'Uzbl',
    'UCBrowser' => 'UCBrowser',
    'Kindle' => 'Kindle',
    'wOSBrowser' => 'wOSBrowser',
     'Epiphany' => 'Epiphany', 
    'SeaMonkey' => 'SeaMonkey',
    'Avant Browser' => 'Avant Browser',
    'Firefox' => 'Firefox',
    'Chrome' => 'Google Chrome',
    'MSIE' => 'Internet Explorer',
    'Internet Explorer' => 'Internet Explorer',
     'Safari' => 'Safari',
    'Mozilla' => 'Mozilla'  
    );

     private $_basic_platform = array(
        'windows' => 'Windows', 
     'iPad' => 'iPad', 
      'iPod' => 'iPod', 
    'iPhone' => 'iPhone', 
     'mac' => 'Apple', 
    'android' => 'Android', 
    'linux' => 'Linux',
    'Nokia' => 'Nokia',
     'BlackBerry' => 'BlackBerry',
    'FreeBSD' => 'FreeBSD',
     'OpenBSD' => 'OpenBSD',
    'NetBSD' => 'NetBSD',
     'UNIX' => 'UNIX',
    'DragonFly' => 'DragonFlyBSD',
    'OpenSolaris' => 'OpenSolaris',
    'SunOS' => 'SunOS', 
    'OS\/2' => 'OS/2',
    'BeOS' => 'BeOS',
    'win' => 'Windows',
    'Dillo' => 'Linux',
    'PalmOS' => 'PalmOS',
    'RebelMouse' => 'RebelMouse'   
     ); 

    function __construct($ua = '') {
        if(empty($ua)) {
           $this->_user_agent = (!empty($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:getenv('HTTP_USER_AGENT'));
        }
        else {
           $this->_user_agent = $ua;
        }
       }

    function detect() {
        $this->detectBrowser();
        $this->detectPlatform();
        return $this;
    }

    function detectBrowser() {
     foreach($this->_basic_browser as $pattern => $name) {
        if( preg_match("/".$pattern."/i",$this->_user_agent, $match)) {
            $this->_name = $name;
             // finally get the correct version number
            $known = array('Version', $pattern, 'other');
            $pattern_version = '#(?<browser>' . join('|', $known).')[/ ]+(?<version>[0-9.|a-zA-Z.]*)#';
            if (!preg_match_all($pattern_version, $this->_user_agent, $matches)) {
                // we have no matching number just continue
            }
            // see how many we have
            $i = count($matches['browser']);
            if ($i != 1) {
                //we will have two since we are not using 'other' argument yet
                //see if version is before or after the name
                if (strripos($this->_user_agent,"Version") < strripos($this->_user_agent,$pattern)){
                    @$this->_version = $matches['version'][0];
                }
                else {
                    @$this->_version = $matches['version'][1];
                }
            }
            else {
                $this->_version = $matches['version'][0];
            }
            break;
        }
       }
   }

    function detectPlatform() {
      foreach($this->_basic_platform as $key => $platform) {
            if (stripos($this->_user_agent, $key) !== false) {
                $this->_platform = $platform;
                break;
            } 
      }
    }

   function getBrowser() {
      if(!empty($this->_name)) {
           return $this->_name;
      }
   }        

   function getVersion() {
       return $this->_version;
    }

    function getPlatform() {
       if(!empty($this->_platform)) {
          return $this->_platform;
       }
    }

    function getUserAgent() {
        return $this->_user_agent;
     }

     function getInfo() {
         return "<strong>Browser Name:</strong> {$this->getBrowser()}<br/>\n" .
        "<strong>Browser Version:</strong> {$this->getVersion()}<br/>\n" .
        "<strong>Browser User Agent String:</strong> {$this->getUserAgent()}<br/>\n" .
        "<strong>Platform:</strong> {$this->getPlatform()}<br/>";
     }
}  

$obj = new BrowserDetection();

echo $obj->detect()->getInfo();

The above code works for me almost on every browser and i hope it will help you a bit.

Solution 4

class Browser { 
    /** 
    Figure out what browser is used, its version and the platform it is 
    running on. 

    The following code was ported in part from JQuery v1.3.1 
    */ 
    public static function detect() { 
        $userAgent = strtolower($_SERVER['HTTP_USER_AGENT']); 

        // Identify the browser. Check Opera and Safari first in case of spoof. Let Google Chrome be identified as Safari. 
        if (preg_match('/opera/', $userAgent)) { 
            $name = 'opera'; 
        } 
        elseif (preg_match('/webkit/', $userAgent)) { 
            $name = 'safari'; 
        } 
        elseif (preg_match('/msie/', $userAgent)) { 
            $name = 'msie'; 
        } 
        elseif (preg_match('/mozilla/', $userAgent) && !preg_match('/compatible/', $userAgent)) { 
            $name = 'mozilla'; 
        } 
        else { 
            $name = 'unrecognized'; 
        } 

        // What version? 
        if (preg_match('/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/', $userAgent, $matches)) { 
            $version = $matches[1]; 
        } 
        else { 
            $version = 'unknown'; 
        } 

        // Running on what platform? 
        if (preg_match('/linux/', $userAgent)) { 
            $platform = 'linux'; 
        } 
        elseif (preg_match('/macintosh|mac os x/', $userAgent)) { 
            $platform = 'mac'; 
        } 
        elseif (preg_match('/windows|win32/', $userAgent)) { 
            $platform = 'windows'; 
        } 
        else { 
            $platform = 'unrecognized'; 
        } 

        return array( 
            'name'      => $name, 
            'version'   => $version, 
            'platform'  => $platform, 
            'userAgent' => $userAgent 
        ); 
    } 
} 


$browser = Browser::detect(); 

Solution 5

Most PHP packages that I've found seemed to be pretty good but I couldn't find a good one that gave me everything I needed so I built a Laravel helper to combine 3 of them.

Here are the packages:

jenssegers/agent

whichbrowser/parser

cbschuld/browser.php

And here's my function:

function browser($userAgent)
{
    $agent = new \Jenssegers\Agent\Agent();
    $agent->setUserAgent($userAgent);

    $result = new \WhichBrowser\Parser($userAgent);

    $browser = new \Browser($userAgent);

    return new class($agent, $result, $browser)
    {
        public function __construct($agent, $result, $browser)
        {
            $this->agent = $agent;
            $this->result = $result;
            $this->browser = $browser;
        }
        public function device()
        {
            return $this->agent->device() ?: $this->result->device->toString() ?: $this->browser->getPlatform();
        }
        public function browser()
        {
            return $this->agent->browser() ?: $this->result->browser->name ?: $this->browser->getBrowser();
        }
        public function platform()
        {
            return $this->agent->platform() ?: $this->result->os->name ?: $this->browser->getPlatform();
        }
        public function isMobile()
        {
            return $this->agent->isPhone() ?: $this->result->isType('mobile') ?: $this->browser->isMobile();
        }
        public function isTablet()
        {
            return $this->result->isType('tablet') ?: $this->browser->isTablet();
        }
        public function isDesktop()
        {
            return $this->agent->isDesktop() ?: $this->result->isType('desktop') ?: (! $this->browser->isMobile() && ! $this->browser->isTablet());
        }
        public function isRobot()
        {
            return $this->agent->isRobot() ?: $this->browser->isRobot();
        }
    };

Here's how to use it:

$browser = browser($userAgent);

$browser->device();
$browser->platform();
$browser->browser();
$browser->isMobile();
$browser->isTablet();
$browser->isDesktop();
$browser->isRobot();
Share:
96,410
Gal
Author by

Gal

Updated on June 11, 2020

Comments

  • Gal
    Gal about 4 years

    Trying to detect a user's browser with PHP only, is $_SERVER['HTTP_USER_AGENT'] a reliable way? Should I instead opt for the get_browser function? which one do you find brings more precise results?

    If this method is pragmatic, is it ill advised to use it for outputting pertinent CSS links, for example:

    if(stripos($_SERVER['HTTP_USER_AGENT'],"mozilla")!==false)
       echo '<link type="text/css" href="mozilla.css" />';
    

    I noticed this question, however I wanted to clarify whether this is good for CSS-oriented detection.

    UPDATE: something really suspicious: I tried echo $_SERVER['HTTP_USER_AGENT']; on IE 7 and this is what it output:

    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618)

    Safari gave something weird with "mozilla" in it too. What gives?

  • rap-2-h
    rap-2-h over 10 years
    Does not work for IE 11 (have a look here: nczonline.net/blog/2013/07/02/… )
  • Fernando Silva
    Fernando Silva about 10 years
    @Farhad Hi, I'm using this bit of code of yours, but I'm just curious if a switch statement wouldn't be faster. Personally it just feels like a switch statement would be the better fit. But thanks, that sorted my issue
  • Michael Walter
    Michael Walter over 9 years
    why are you creating a class with only one method in it? why not using a normal function instead?
  • LifeInstructor
    LifeInstructor over 9 years
    That is your choice do as you want.I am giving an example how to detect the browser. I have taken from one of my working projects. Also using objects is more preferable for all developers.
  • o0'.
    o0'. about 9 years
    If it's faked, who cares? It's not like you are relying security on it, it's just about displaying something to the user…
  • user151496
    user151496 about 9 years
    oh boy but you don't even know what he wants to do with that information and go suggesting media queries ...
  • Gerardo Jaramillo
    Gerardo Jaramillo almost 8 years
    This worked for me, to fix the safari/chrome issue: if ( stripos($userAgent, 'Firefox') !== false ) { $name = 'firefox'; } elseif ( stripos($userAgent, 'MSIE') !== false ) { $name = 'ie'; } elseif ( stripos($userAgent, 'Trident') !== false ) { $name = 'ie'; } elseif ( stripos($userAgent, 'Chrome') !== false ) { $name = 'chrome'; } elseif ( stripos($userAgent, 'Safari') !== false ) { $name = 'safari'; }
  • The EasyLearn Academy
    The EasyLearn Academy almost 7 years
    not working, script shows return chrome in case of browser is opera.
  • ViliusL
    ViliusL about 6 years
    This function will not work on every server. Tried 3 servers - 0/3.
  • Mohammad Salehi
    Mohammad Salehi over 5 years
    to check Edge browser you can add elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Edge') !== FALSE) echo 'Microsoft Edge'; after if
  • Admin
    Admin almost 5 years
    This works really well, I have no idea why tho. Care to explain?
  • JSG
    JSG over 4 years
    As ViliusL says, it won't work on every server because it requires the path to it's ini file to be set in the php.ini or the" http.config" file on Apache. This means you have to have access to it.
  • Leo Galleguillos
    Leo Galleguillos about 4 years
    By the way, in case anyone has tried, setting the browscap directive at the script level using ini_set('browscap', '/path/to/browscap.ini'); does not seem to work. This directive must be set in a php config file (as stated in the above comment).
  • ciberelfo
    ciberelfo over 3 years
    A small detail, in Edge it detects it as Chrome, to fix it just add in the _basic_browser array before Chrome the 'Edg' => 'Microsoft Edge',
  • DrCustUmz
    DrCustUmz over 3 years
    the updated method to detect Edge is elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Edg') !== FALSE) echo 'Microsoft Edge'; for some reason they removed the e from the agent name. almost 8 years old and this method still works great
  • user3495363
    user3495363 about 3 years
    it shows "Safari" both on my Desktop Chrome->inspect mode, and on my mobile Safari