server-side browser detection? node.js

JavascriptBrowsernode.jsBrowser Detection

Javascript Problem Overview


Most implementations i've seen are for browser detection on the client side. I was just wondering if it was possible to do browser detection before sending any resources to the client.

Thanks.

Javascript Solutions


Solution 1 - Javascript

var ua = request.headers['user-agent'],
    $ = {};

if (/mobile/i.test(ua))
    $.Mobile = true;

if (/like Mac OS X/.test(ua)) {
    $.iOS = /CPU( iPhone)? OS ([0-9\._]+) like Mac OS X/.exec(ua)[2].replace(/_/g, '.');
    $.iPhone = /iPhone/.test(ua);
    $.iPad = /iPad/.test(ua);
}

if (/Android/.test(ua))
    $.Android = /Android ([0-9\.]+)[\);]/.exec(ua)[1];

if (/webOS\//.test(ua))
    $.webOS = /webOS\/([0-9\.]+)[\);]/.exec(ua)[1];

if (/(Intel|PPC) Mac OS X/.test(ua))
    $.Mac = /(Intel|PPC) Mac OS X ?([0-9\._]*)[\)\;]/.exec(ua)[2].replace(/_/g, '.') || true;

if (/Windows NT/.test(ua))
    $.Windows = /Windows NT ([0-9\._]+)[\);]/.exec(ua)[1];

That should work for you. Just put it in your response handler.

Solution 2 - Javascript

The ua-parser library for node (npm install ua-parser) exposes a big set of regexes for browser user-agent strings. I'd strongly recommend it for your needs.

Solution 3 - Javascript

I threw this together using ua-parser-js. I'm sure it can be improved but it's functional.

Install the package:

sudo npm install ua-parser-js

In your routes file require UAParser:

var UAParser = require('ua-parser-js');

Do some stuff with it:

function ensureLatestBrowser(req, res, next) {
  var parser = new UAParser();
  var ua = req.headers['user-agent'];
  var browserName = parser.setUA(ua).getBrowser().name;
  var fullBrowserVersion = parser.setUA(ua).getBrowser().version;
  var browserVersion = fullBrowserVersion.split(".",1).toString();
  var browserVersionNumber = Number(browserVersion);
  
  if (browserName == 'IE' && browserVersion <= 9)
    res.redirect('/update/');
  else if (browserName == 'Firefox' && browserVersion <= 24)
    res.redirect('/update/');
  else if (browserName == 'Chrome' && browserVersion <= 29)
    res.redirect('/update/');
  else if (browserName == 'Canary' && browserVersion <= 32)
    res.redirect('/update/');
  else if (browserName == 'Safari' && browserVersion <= 5)
    res.redirect('/update/');
  else if (browserName == 'Opera' && browserVersion <= 16)
    res.redirect('/update/');
  else
    return next();
}

and then in your route just call:

app.all(/^(?!(\/update)).*$/, ensureLatestBrowser);

If you want to see what other information you can get with UAParser check out their demo page.

Solution 4 - Javascript

I wanted to do a simple redirection to a mobile version of my site, so user-agent is reliable enough. I wanted to do it server-side so I didn't waste time loading unnecessary css and js on the client. http://detectmobilebrowsers.com/ had the most robust regex to match. So I threw together some express middleware that will let you do the redirection by just adding two lines of code to your app.

npm install detectmobilebrowsers to install

express = require 'express'
mobile  = require 'detectmobilebrowsers'

app = express()
app.configure () ->
  app.use mobile.redirect 'http://m.domain.com'
app.get '/', (req, res) ->
  res.send 'Not on Mobile'
app.listen 3000

Solution 5 - Javascript

I released device-detector-js a couple months ago.

It's a TypeScript port of Matomo device-detector, a powerful device detection library originally written in PHP.

It can parse any user agent and detect the browser, operating system, device used (desktop, tablet, mobile, tv, cars, console, etc.), brand and model.

Installation

npm install device-detector-js

Example - simple user agent detection:

const DeviceDetector = require("device-detector-js");

const deviceDetector = new DeviceDetector();
const userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36";
const device = deviceDetector.parse(userAgent);

console.log(device);

Take a look at the full API documentation.

Solution 6 - Javascript

ua = request.headers['user-agent'];
if( /firefox/i.test(ua) )
  browser = 'firefox';
else if( /chrome/i.test(ua) )
  browser = 'chrome';
else if( /safari/i.test(ua) )
  browser = 'safari';
else if( /msie/i.test(ua) )
  browser = 'msie';
else
  browser = 'unknown';

Solution 7 - Javascript

Most browsers provide an HTTP request header called "User-Agent" This is the same as the navigator.userAgent property on the client side.

Solution 8 - Javascript

Solution 9 - Javascript

if your using express you can easily check the ua with something like this:

app.get('/ua', function(req, res){
    res.send('user ' + req.headers['user-agent']);
});

Solution 10 - Javascript

Solution 11 - Javascript

I improved a bit @duck5auce's code to be actually useful and support IE 10-12 (Edge).

var getDevice = function(ua) {
    var $ = {active: false, subactive: false};

    if (/mobile/i.test(ua)) {
        $.active = 'mobile';
        $.Mobile = true;
    }

    if (/like Mac OS X/.test(ua)) {
        $.active = 'iOS';
        $.iOS = /CPU( iPhone)? OS ([0-9\._]+) like Mac OS X/.exec(ua)[2].replace(/_/g, '.');
        if (/like Mac OS X/.test(ua)) {
            $.subactive = 'iPhone';
            $.iPhone = /iPhone/.test(ua);
        }
        if (/like Mac OS X/.test(ua)) {
            $.subactive = 'iPad';
            $.iPad = /iPad/.test(ua);
        }
    }

    if (/Android/.test(ua)) {
        $.active = 'Android';
        $.Android = /Android ([0-9\.]+)[\);]/.exec(ua)[1];
    }

    if (/webOS\//.test(ua)) {
        $.active = 'webOS';
        $.webOS = /webOS\/([0-9\.]+)[\);]/.exec(ua)[1];
    }

    if (/(Intel|PPC) Mac OS X/.test(ua)) {
        $.active = 'Safari';
        $.Safari = /(Intel|PPC) Mac OS X ?([0-9\._]*)[\)\;]/.exec(ua)[2].replace(/_/g, '.') || true;
    }

    if (/Windows NT/.test(ua)) {
        $.active = 'IE';
        $.IE = /Windows NT ([0-9\._]+)[\);]/.exec(ua)[1];
    }
    if (/MSIE/.test(ua)) {
        $.active = 'IE';
        $.IE = /MSIE ([0-9]+[\.0-9]*)/.exec(ua)[1];
    }
    if (/Trident/.test(ua)) {
        $.active = 'IE';
        $.IE = /Trident\/.*rv:([0-9]+[\.0-9]*)/.exec(ua)[1];
    }
    if (/Edge\/\d+/.test(ua)) {
        $.active = 'IE Edge';
        $.IE = /Edge\/(\d+)/.exec(ua)[1];
    }

    return $.active + ' ' + $[$.active] + ($.subactive && ' ' + $.subactive + ' ' + $[$.subactive]);
};

Solution 12 - Javascript

Powerfull npm useragent. Useragent allows you to parse user agent string with high accuracy by using hand tuned dedicated regular expressions for browser matching. This database is needed to ensure that every browser is correctly parsed as every browser vendor implements it's own user agent schema. This is why regular user agent parsers have major issues because they will most likely parse out the wrong browser name or confuse the render engine version with the actual version of the browser.

Solution 13 - Javascript

If you want to control mobile in the templating layer, I just wrote a module for that. https://github.com/Fresheyeball/isMobile-node

Solution 14 - Javascript

You might want to have a look at Apache DeviceMap.

JavaScript libraries out of the box are more on the client side right now, but much will work on Node.JS or Angular in a similar way. Unlike simple pattern matching of UA strings DeviceMap comes with a vast range of devices and device families in its Device Description Repository (DDR) based on W3C standards.

Solution 15 - Javascript

[Here is another variation or assimilation for your consideration.]

It is more versatile and simplified further.

You can pass the Request or any object with a 'headers' property or it could be the headers property and you can pick any label to search for the parameter on the object or the headers or the actual user agent string itself.

It used the previously posted Mobile and Table Checking Regex, and simply returns that result, but by first sanctifying the input, one can plug various things in.

You can even override the default regex optionally passable as an argument. {I'll leave that further extension to the inspired.} Also one could have another way to default to the globally stored user-agent from the request if in scope etc.

mobTabCheck: function( ua, lbl, rgx ) {  /* mobile tablet check; UserAgent or request, or any object with optional search label  */
	if( ua === und ) return false;
	if( ua !== und && ua.constructor !== String ) {
		if( lbl === und ) lbl = 'user-agent';
		if( ua.headers !== und ) ua = ua.headers[ lbl ];
		else ua = ua[ lbl ];
	}
	if( rgx === und ) rgx = /Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|NetFront|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune/;
	if( rgx.constructor === String ) rgx = new RegExp( rgx );
	return rgx.test( ua );
}

This Regex came from here... https://gist.github.com/dalethedeveloper/1503252/931cc8b613aaa930ef92a4027916e6687d07feac

The 98% Solution. I don't know if it checks tablets like my function title implies.

Really the title of this function (and some arguments) should be rename maybe?... serachObjectForLabelThatMatchesThisRegex

except all the defaults make it a single argument purposed thing.

Also I leave the function set as a key's value, which you can store however you prefer like... just promise me no var or const if you use it.

let mobTabCheck = function() {};

Solution 16 - Javascript

I had a similar requirement and I came across this node package called detect-browser.

const { detect } = require('detect-browser');
const browser = detect();

if (browser) {
  console.log(browser.name);
  console.log(browser.version);
  console.log(browser.os);
}

Or if you wanted to perform any action depending on a specific browser you could also use a switch case like below

const { detect } = require('detect-browser');
const browser = detect();

// handle the case where we don't detect the browser
switch (browser && browser.name) {
  case 'chrome':
  case 'firefox':
    console.log('supported');
    break;

  case 'edge':
    console.log('kinda ok');
    break;

  default:
    console.log('not supported');
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionfancyView Question on Stackoverflow
Solution 1 - JavascriptMcKaylaView Answer on Stackoverflow
Solution 2 - JavascriptS MView Answer on Stackoverflow
Solution 3 - JavascriptDonaldView Answer on Stackoverflow
Solution 4 - JavascriptOverflow289View Answer on Stackoverflow
Solution 5 - JavascriptEtienne MartinView Answer on Stackoverflow
Solution 6 - JavascriptNino PaoloView Answer on Stackoverflow
Solution 7 - JavascriptMazView Answer on Stackoverflow
Solution 8 - JavascripttomislavView Answer on Stackoverflow
Solution 9 - JavascriptbhurlowView Answer on Stackoverflow
Solution 10 - Javascriptuser1113641View Answer on Stackoverflow
Solution 11 - JavascriptEvgenyKolyakovView Answer on Stackoverflow
Solution 12 - JavascriptJomy JosephView Answer on Stackoverflow
Solution 13 - JavascriptFresheyeballView Answer on Stackoverflow
Solution 14 - JavascriptWerner KeilView Answer on Stackoverflow
Solution 15 - JavascriptMaster JamesView Answer on Stackoverflow
Solution 16 - JavascriptdarkHorseView Answer on Stackoverflow