最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

User Agent parsing in Javascript - Stack Overflow

programmeradmin2浏览0评论

I need to extract the Operating System's name and the browser's name from the user agent string.

Sample of user agent:

Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.9) Gecko/20100825 Ubuntu/9.10 (karmic) Firefox/3.6.9

How can I get just the operating system (example "Linux i686" and "Firefox 3.6.9")?

Here is my codes in fiddle link which is as follows:

function getBrowserAndOS(userAgent, elements) {
  var browserList = {
      'Chrome': [/Chrome\/(\S+)/],
      'Firefox': [/Firefox\/(\S+)/],
      'MSIE': [/MSIE (\S+);/],
      'Opera': [
        /Opera\/.*?Version\/(\S+)/,
        /Opera\/(\S+)/
      ],
      'Safari': [/Version\/(\S+).*?Safari\//]
    },
    re, m, browser, version;


  var osList = {
      'Windows': [/Windows\/(\S+)/],
      'Linux': [/Linux\/(\S+)/]
    },
    re2, m2, os;

  if (userAgent === undefined)
    userAgent = navigator.userAgent;

  if (elements === undefined)
    elements = 2;
  else if (elements === 0)
    elements = 1337;

  for (browser in browserList) {
    while (re = browserList[browser].shift()) {
      if (m = userAgent.match(re)) {
        version = (m[1].match(new RegExp('[^.]+(?:\.[^.]+){0,' + --elements + '}')))[0];
        //version = (m[1].match(new RegExp('[^.]+(?:\.[^.]+){0,}')))[0];
        //return browser + ' ' + version;
        console.log(browser + ' ' + version);
      }
    }
  }


  for (os in osList) {
    while (re2 = osList[os].shift()) {
      if (m2 = userAgent.match(re2)) {
        //version = (m[1].match(new RegExp('[^.]+(?:\.[^.]+){0,' + --elements + '}')))[0];
        //version = (m[1].match(new RegExp('[^.]+(?:\.[^.]+){0,}')))[0];
        //return browser + ' ' + version;
        console.log(os);
      }

    }
  }

  return null;
}

console.log(getBrowserAndOS(navigator.userAgent, 2));

I need to extract the Operating System's name and the browser's name from the user agent string.

Sample of user agent:

Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.9) Gecko/20100825 Ubuntu/9.10 (karmic) Firefox/3.6.9

How can I get just the operating system (example "Linux i686" and "Firefox 3.6.9")?

Here is my codes in fiddle link which is as follows:

function getBrowserAndOS(userAgent, elements) {
  var browserList = {
      'Chrome': [/Chrome\/(\S+)/],
      'Firefox': [/Firefox\/(\S+)/],
      'MSIE': [/MSIE (\S+);/],
      'Opera': [
        /Opera\/.*?Version\/(\S+)/,
        /Opera\/(\S+)/
      ],
      'Safari': [/Version\/(\S+).*?Safari\//]
    },
    re, m, browser, version;


  var osList = {
      'Windows': [/Windows\/(\S+)/],
      'Linux': [/Linux\/(\S+)/]
    },
    re2, m2, os;

  if (userAgent === undefined)
    userAgent = navigator.userAgent;

  if (elements === undefined)
    elements = 2;
  else if (elements === 0)
    elements = 1337;

  for (browser in browserList) {
    while (re = browserList[browser].shift()) {
      if (m = userAgent.match(re)) {
        version = (m[1].match(new RegExp('[^.]+(?:\.[^.]+){0,' + --elements + '}')))[0];
        //version = (m[1].match(new RegExp('[^.]+(?:\.[^.]+){0,}')))[0];
        //return browser + ' ' + version;
        console.log(browser + ' ' + version);
      }
    }
  }


  for (os in osList) {
    while (re2 = osList[os].shift()) {
      if (m2 = userAgent.match(re2)) {
        //version = (m[1].match(new RegExp('[^.]+(?:\.[^.]+){0,' + --elements + '}')))[0];
        //version = (m[1].match(new RegExp('[^.]+(?:\.[^.]+){0,}')))[0];
        //return browser + ' ' + version;
        console.log(os);
      }

    }
  }

  return null;
}

console.log(getBrowserAndOS(navigator.userAgent, 2));

I just need to extract the OS name and the browser name with their respective versions. How can I parse it to get those string?

Share Improve this question edited Apr 9, 2019 at 10:10 Kunal Mukherjee 5,8533 gold badges28 silver badges55 bronze badges asked Jun 24, 2014 at 0:00 jeewanjeewan 1,6055 gold badges24 silver badges41 bronze badges 2
  • 1 What is the point of the single value arrays? – Ryan Commented Jun 24, 2014 at 0:02
  • @RPM I guess the intent is that you could have multiple REs in the array, and it will try them all to decide that you're running that OS. – Barmar Commented Jun 24, 2014 at 0:06
Add a comment  | 

4 Answers 4

Reset to default 6

I wouldn't recommend doing this yourself. I'd use a parser like Platform.js, which works like this:

<script src="platform.js"></script>
<script>
var os = platform.os;
var browser = platform.name + ' ' + platform.version;
</script>

This is a native JavaScript solution for identifying the OS, however would need to be manually updated whenever a new OS is introduced:

function getOs (userAgent) {

     //Converts the user-agent to a lower case string
     var userAgent = userAgent.toLowerCase();

     //Fallback in case the operating system can't be identified
     var os = "Unknown OS Platform";

     //Corresponding arrays of user-agent strings and operating systems
     match = ["windows nt 10","windows nt 6.3","windows nt 6.2","windows nt 6.1","windows nt 6.0","windows nt 5.2","windows nt 5.1","windows xp","windows nt 5.0","windows me","win98","win95","win16","macintosh","mac os x","mac_powerpc","android","linux","ubuntu","iphone","ipod","ipad","blackberry","webos"];
     result = ["Windows 10","Windows 8.1","Windows 8","Windows 7","Windows Vista","Windows Server 2003/XP x64","Windows XP","Windows XP","Windows 2000","Windows ME","Windows 98","Windows 95","Windows 3.11","Mac OS X","Mac OS X","Mac OS 9","Android","Linux","Ubuntu","iPhone","iPod","iPad","BlackBerry","Mobile"];

     //For each item in match array
     for (var i = 0; i < match.length; i++) {

              //If the string is contained within the user-agent then set the os 
              if (userAgent.indexOf(match[i]) !== -1) {
                   os = result[i];
                   break;
              }

     }

     //Return the determined os
     return os;
}

Useragents aren't a set of metadata useful for asking qualitative questions such as "what are you?", they're really only useful for yes/no questions like "are you linux?", or "what version of Firefox are you?".

Let me illustrate, here's a script that converts useragents to lovely json-serialisable objects:

parseUA = (() => {
    //useragent strings are just a set of phrases each optionally followed by a set of properties encapsulated in paretheses
    const part = /\s*([^\s/]+)(\/(\S+)|)(\s+\(([^)]+)\)|)/g;
    //these properties are delimited by semicolons
    const delim = /;\s*/;
    //the properties may be simple key-value pairs if;
    const single = [
        //it is a single comma separation,
        /^([^,]+),\s*([^,]+)$/,
        //it is a single space separation,
        /^(\S+)\s+(\S+)$/,
        //it is a single colon separation,
        /^([^:]+):([^:]+)$/,
        //it is a single slash separation
        /^([^/]+)\/([^/]+)$/,
        //or is a special string
        /^(.NET CLR|Windows)\s+(.+)$/
    ];
    //otherwise it is unparsable because everyone does it differently, looking at you iPhone
    const many = / +/;
    //oh yeah, bots like to use links
    const link = /^\+(.+)$/;

    const inner = (properties, property) => {
        let tmp;

        if (tmp = property.match(link)) {
            properties.link = tmp[1];
        }
        else if (tmp = single.reduce((match, regex) => (match || property.match(regex)), null)) {
            properties[tmp[1]] = tmp[2];
        }
        else if (many.test(property)) {
            if (!properties.properties)
                properties.properties = [];
            properties.properties.push(property);
        }
        else {
            properties[property] = true;
        }

        return properties;
    };

    return (input) => {
        const output = {};
        for (let match; match = part.exec(input); '') {
            output[match[1]] = {
                ...(match[5] && match[5].split(delim).reduce(inner, {})),
                ...(match[3] && {version:match[3]})
            };
        }
        return output;
    };
})();
//parseUA('user agent string here');

Using this, we can convert out the following useragents:

`Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)`

{
    "Mozilla": {
        "compatible": true,
        "MSIE": "7.0",
        "Windows": "NT 6.0",
        "WOW64": true,
        "Trident": "4.0",
        "SLCC1": true,
        ".NET CLR": "3.0.30729",
        ".NET4.0C": true,
        ".NET4.0E": true,
        "version": "4.0"
    }
}

`Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-S8500-BOUYGUES/S8500AGJF1; U; Bada/1.0; fr-fr) AppleWebKit/533.1 (KHTML, like Gecko) Dolfin/2.0 Mobile WVGA SMM-MMS/1.2.0 NexPlayer/3.0 profile/MIDP-2.1 configuration/CLDC-1.1 OPN-B`

{
    "Mozilla": {
        "SAMSUNG": true,
        "SAMSUNG-GT-S8500-BOUYGUES": "S8500AGJF1",
        "U": true,
        "Bada": "1.0",
        "fr-fr": true,
        "version": "5.0"
    },
    "AppleWebKit": {
        "KHTML": "like Gecko",
        "version": "533.1"
    },
    "Dolfin": {
        "version": "2.0"
    },
    "Mobile": {},
    "WVGA": {},
    "SMM-MMS": {
        "version": "1.2.0"
    },
    "NexPlayer": {
        "version": "3.0"
    },
    "profile": {
        "version": "MIDP-2.1"
    },
    "configuration": {
        "version": "CLDC-1.1"
    },
    "OPN-B": {}
}

`Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Comodo_Dragon/4.1.1.11 Chrome/4.1.249.1042 Safari/532.5`

{
    "Mozilla": {
        "Windows": "NT 5.1",
        "U": true,
        "en-US": true,
        "version": "5.0"
    },
    "AppleWebKit": {
        "KHTML": "like Gecko",
        "version": "532.5"
    },
    "Comodo_Dragon": {
        "version": "4.1.1.11"
    },
    "Chrome": {
        "version": "4.1.249.1042"
    },
    "Safari": {
        "version": "532.5"
    }
}

`Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36`

{
    "Mozilla": {
        "X11": true,
        "Fedora": true,
        "Linux": "x86_64",
        "version": "5.0"
    },
    "AppleWebKit": {
        "KHTML": "like Gecko",
        "version": "537.36"
    },
    "Chrome": {
        "version": "73.0.3683.86"
    },
    "Safari": {
        "version": "537.36"
    }
}

`Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0`

{
    "Mozilla": {
        "X11": true,
        "Fedora": true,
        "Linux": "x86_64",
        "rv": "66.0",
        "version": "5.0"
    },
    "Gecko": {
        "version": "20100101"
    },
    "Firefox": {
        "version": "66.0"
    }
}

`Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36`

{
    "Mozilla": {
        "X11": true,
        "Linux": "x86_64",
        "version": "5.0"
    },
    "AppleWebKit": {
        "KHTML": "like Gecko",
        "version": "537.36"
    },
    "Chrome": {
        "version": "73.0.3683.103"
    },
    "Safari": {
        "version": "537.36"
    }
}

`Mozilla/5.0 (Linux; Android 6.0.1; SM-G920V Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36`

{
    "Mozilla": {
        "Linux": true,
        "Android": "6.0.1",
        "SM-G920V": "Build/MMB29K",
        "version": "5.0"
    },
    "AppleWebKit": {
        "KHTML": "like Gecko",
        "version": "537.36"
    },
    "Chrome": {
        "version": "52.0.2743.98"
    },
    "Mobile": {},
    "Safari": {
        "version": "537.36"
    }
}

`Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1 (compatible; AdsBot-Google-Mobile; +http://www.google.com/mobile/adsbot.html)`

{
    "Mozilla": {
        "iPhone": true,
        "properties": [
            "CPU iPhone OS 9_1 like Mac OS X"
        ],
        "version": "5.0"
    },
    "AppleWebKit": {
        "KHTML": "like Gecko",
        "version": "601.1.46"
    },
    "Version": {
        "version": "9.0"
    },
    "Mobile": {
        "version": "13B143"
    },
    "Safari": {
        "compatible": true,
        "AdsBot-Google-Mobile": true,
        "link": "http://www.google.com/mobile/adsbot.html",
        "version": "601.1"
    }
}

If you expand that you'll see, that as a human, you can easily read out the Operating System versions: Mozilla.Windows = NT 6.0, Mozilla.Bada = 1.0, Mozilla.Fedora && Mozilla.Linux = x86_64.
But do you see the issue? None of them say OS = "Windows", OS = "Samsung Bada", et cetera.

To ask the questions you want to you will need to be privy to all the possible values, kind of like what @Peter Wetherall attempted above, or say "I only care about these handful of browsers/OS's", like what you have in your question.

If that's okay, and you're not using the information to change how the code works (which shouldn't be done as per @Sophit), just wanting to display stuff about the browser, I'd use the above parseUA() in combination with manually checking Mozilla.Windows || Mozilla.Linux || //et cetera which will be less error-prone than trying to get lucky with regex's over the raw useragent string (which will lead to false positives: see the browser Comodo_Dragon says "Chrome" in it).

Were you planning to control your website’s behavior based on the browser “sniffed” from the User-Agent (UA) string?

Please don’t; use feature detection instead.

Poorly implemented (non-futureproof) User-Agent sniffing has proven to be the top compatibility problem encountered each time a new version of Internet Explorer ships. As a consequence, the logic around the user-agent string has grown increasingly complicated over the years; the introduction of Compatibility Modes has meant that the browser now has more than one UA string, and legacy extensibility of the string was deprecated after years of abuse.

By default, Internet Explorer 11 on Windows 8.1 sends the following User-Agent string:

Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko

This string is deliberately designed to cause most UA-string sniffing logic to interpret it either Gecko or WebKit. This design choice was a careful one—the IE team tested many UA string variants to find out which would cause the majority of sites to “just work” for IE11 users.

Here are two links that will actually help you. You may also want to view the original source of much of my comment.

发布评论

评论列表(0)

  1. 暂无评论