Skip to content

Instantly share code, notes, and snippets.

@sandrock
Created July 9, 2025 16:53
Show Gist options
  • Select an option

  • Save sandrock/887166123dc48dd0d266addfc9d7c33c to your computer and use it in GitHub Desktop.

Select an option

Save sandrock/887166123dc48dd0d266addfc9d7c33c to your computer and use it in GitHub Desktop.
Report browser settings like whatsmybrowser.org
/*
* Report browser settings like whatsmybrowser.org
* Inspired by
* http://stackoverflow.com/questions/9514179/how-to-find-the-operating-system-version-using-javascript
*/
(function () {
"use strict";
var extractDataFromClient, definePropertySupported;
extractDataFromClient = function (userAgent) {
var report, match, uuid;
userAgent = userAgent || navigator.userAgent;
// initialize object to store results
report = {
"browser": {
"name": null,
"version": null
},
"cookies": null,
"flash": {
"version": null
},
"ip": null,
"java": {
"version": null
},
"os": {
"name": null,
"version": null
},
"screen": {
"colors": null,
"dppx": null,
"height": null,
"width": null
},
"scripts": true,
"userAgent": userAgent,
"viewport": {
"height": null,
"layout": {
"height": null,
"width": null
},
"width": null,
"zoom": null
},
"websockets": null
};
// extract browser name from user agent
if (userAgent.indexOf("Trident") >= 0 || userAgent.indexOf("MSIE") >= 0) {
if (userAgent.indexOf("Mobile") >= 0) {
report.browser.name = "IE Mobile";
} else {
report.browser.name = "Internet Explorer";
}
}
if (userAgent.indexOf("Firefox") >= 0 && userAgent.indexOf("Seamonkey") === -1) {
if (userAgent.indexOf("Android") >= 0) {
report.browser.name = "Firefox for Android";
} else {
report.browser.name = "Firefox";
}
}
if (userAgent.indexOf("Safari") >= 0 && userAgent.indexOf("Chrome") === -1 && userAgent.indexOf("Chromium") === -1 && userAgent.indexOf("Android") === -1) {
if (userAgent.indexOf("CriOS") >= 0) {
report.browser.name = "Chrome for iOS";
} else if (userAgent.indexOf("FxiOS") >= 0) {
report.browser.name = "Firefox for iOS";
} else {
report.browser.name = "Safari";
}
}
if (userAgent.indexOf("Chrome") >= 0) {
if (userAgent.match(/\bChrome\/[.0-9]* Mobile\b/)) {
if (userAgent.match(/\bVersion\/\d+\.\d+\b/) || userAgent.match(/\bwv\b/)) {
report.browser.name = "WebView on Android";
} else {
report.browser.name = "Chrome for Android";
}
} else {
report.browser.name = "Chrome";
}
}
if (userAgent.indexOf("Android") >= 0 && userAgent.indexOf("Chrome") === -1 && userAgent.indexOf("Chromium") === -1 && userAgent.indexOf("Trident") === -1 && userAgent.indexOf("Firefox") === -1) {
report.browser.name = "Android Browser";
}
if (userAgent.indexOf("Edge") >= 0) {
report.browser.name = "Edge";
}
if (userAgent.indexOf("UCBrowser") >= 0) {
report.browser.name = "UC Browser for Android";
}
if (userAgent.indexOf("OPR") >= 0 || userAgent.indexOf("Opera") >= 0) {
if (userAgent.indexOf("Opera Mini") >= 0) {
report.browser.name = "Opera Mini";
} else {
report.browser.name = "Opera";
}
}
if (userAgent.indexOf("BB10") >= 0 || userAgent.indexOf("PlayBook") >= 0 || userAgent.indexOf("BlackBerry") >= 0) {
report.browser.name = "BlackBerry";
}
// extract browser version number from user agent
match = null;
switch (report.browser.name) {
case "Chrome":
case "Chrome for Android":
case "WebView on Android":
match = userAgent.match(/Chrome\/((\d+\.)+\d+)/);
break;
case "Firefox":
case "Firefox for Android":
match = userAgent.match(/Firefox\/((\d+\.)+\d+)/);
break;
case "Firefox for iOS":
match = userAgent.match(/FxiOS\/((\d+\.)+\d+)/);
break;
case "Edge":
case "Internet Explorer":
case "IE Mobile":
if (userAgent.indexOf("Edge") >= 0) {
match = userAgent.match(/Edge\/((\d+\.)+\d+)/);
} else if (userAgent.indexOf("rv:11") >= 0) {
match = userAgent.match(/rv:((\d+\.)+\d+)/);
} else if (userAgent.indexOf("MSIE") >= 0) {
match = userAgent.match(/MSIE\ ((\d+\.)+\d+)/);
}
break;
case "Safari":
case "Android Browser":
match = userAgent.match(/Version\/((\d+\.)+\d+)/);
break;
case "UC Browser for Android":
match = userAgent.match(/UCBrowser\/((\d+\.)+\d+)/);
break;
case "Opera Mini":
match = userAgent.match(/Opera Mini\/((\d+\.)+\d+)/);
break;
case "Opera":
if (userAgent.match(/OPR/)) {
match = userAgent.match(/OPR\/((\d+\.)+\d+)/);
} else if (userAgent.match(/Version/)) {
match = userAgent.match(/Version\/((\d+\.)+\d+)/);
} else {
match = userAgent.match(/Opera\/((\d+\.)+\d+)/);
}
break;
case "BlackBerry":
match = userAgent.match(/Version\/((\d+\.)+\d+)/);
break;
default:
match = userAgent.match(/\/((\d+\.)+\d+)$/);
break;
}
if (match && match[1]) {
report.browser.version = match[1];
}
// pull in browser window size from the visual viewport
report.viewport.width = window.innerWidth || document.documentElement.clientWidth;
report.viewport.height = window.innerHeight || document.documentElement.clientHeight;
/*
* test if Object.defineProperty function is fully supported
*/
try {
Object.defineProperty({}, "x", {});
definePropertySupported = true;
} catch (e) {
definePropertySupported = false;
}
/*
* helper function to safely log warning messages
*/
function warning(msg) {
if (window.console) {
if (console.warn) {
console.warn(msg);
} else {
console.log(msg);
}
}
}
// deprecate report.browser.size
if (definePropertySupported) {
Object.defineProperty(report.browser, "size", {
get: function () {
warning("browser.size is deprecated; use viewport.width and viewport.height");
return report.viewport.width + " x " + report.viewport.height;
}
});
}
// pull in raw values for layout viewport
report.viewport.layout.width = document.documentElement.clientWidth;
report.viewport.layout.height = document.documentElement.clientHeight;
// define viewport zoom property
report.viewport.zoom = report.viewport.layout.width / report.viewport.width;
// are cookies enabled
report.cookies = !!navigator.cookieEnabled;
// double check if cookies are enabled
if (!report.cookies) {
// generate UUID
uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
uuid = uuid.replace(/[xy]/g, function (c) {
var r, v;
r = Math.random() * 16 | 0;
v = c === 'x'
? r
: (r & 0x3 | 0x8);
return v.toString(16);
});
document.cookie = uuid;
if (document.cookie.indexOf(uuid) >= 0) {
report.cookies = true;
}
document.cookie = uuid + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
}
// check plugins
(function (plugins) {
var i, l, plugin;
if (plugins) {
l = plugins.length;
for (i = 0; i < l; i += 1) {
plugin = plugins.item(i);
// what version of Adobe Flash
if (plugin.name.indexOf("Flash") >= 0) {
match = plugin.description.match(/\b((\d+\.)+\d+)\b/);
if (match && match[1]) {
report.flash.version = match[1];
}
}
// what version of Java
if (plugin.name.indexOf("Java") >= 0) {
match = plugin.description.match(/\b((\d+\.)+\d+)\b/);
if (match && match[1]) {
report.java.version = match[1];
}
}
}
}
}(navigator.plugins));
// extract operating system name from user agent
if (userAgent.indexOf("Windows") >= 0) {
if (userAgent.indexOf("Windows Phone") >= 0) {
report.os.name = "Windows Phone";
} else {
report.os.name = "Windows";
}
}
if (userAgent.indexOf("OS X") >= 0 && userAgent.indexOf("Android") === -1) {
report.os.name = "OS X";
}
if (userAgent.indexOf("Linux") >= 0) {
report.os.name = "Linux";
}
if (userAgent.indexOf("like Mac OS X") >= 0) {
report.os.name = "iOS";
}
if ((userAgent.indexOf("Android") >= 0 || userAgent.indexOf("Adr") >= 0) && userAgent.indexOf("Windows Phone") === -1) {
report.os.name = "Android";
}
if (userAgent.indexOf("BB10") >= 0) {
report.os.name = "BlackBerry";
}
if (userAgent.indexOf("RIM Tablet OS") >= 0) {
report.os.name = "BlackBerry Tablet OS";
}
if (userAgent.indexOf("BlackBerry") >= 0) {
report.os.name = "BlackBerryOS";
}
// extract operating system version from user agent
match = null;
switch (report.os.name) {
case "Windows":
case "Windows Phone":
if (userAgent.indexOf("Win16") >= 0) {
report.os.version = "3.1.1";
} else if (userAgent.indexOf("Windows CE") >= 0) {
report.os.version = "CE";
} else if (userAgent.indexOf("Windows 95") >= 0) {
report.os.version = "95";
} else if (userAgent.indexOf("Windows 98") >= 0) {
if (userAgent.indexOf("Windows 98; Win 9x 4.90") >= 0) {
report.os.version = "Millennium Edition";
} else {
report.os.version = "98";
}
} else {
match = userAgent.match(/Win(?:dows)?(?: Phone)?[\ _]?(?:(?:NT|9x)\ )?((?:(\d+\.)*\d+)|XP|ME|CE)\b/);
if (match && match[1]) {
switch (match[1]) {
case "6.4":
match[1] = "10.0";
break;
case "6.3":
match[1] = "8.1";
break;
case "6.2":
match[1] = "8";
break;
case "6.1":
match[1] = "7";
break;
case "6.0":
match[1] = "Vista";
break;
case "5.2":
match[1] = "Server 2003";
break;
case "5.1":
match[1] = "XP";
break;
case "5.01":
match[1] = "2000 SP1";
break;
case "5.0":
match[1] = "2000";
break;
case "4.0":
match[1] = "4.0";
break;
default:
// nothing
break;
}
}
}
break;
case "OS X":
match = userAgent.match(/OS\ X\ ((\d+[._])+\d+)\b/);
break;
case "Linux":
// linux user agent strings do not usually include the version
report.os.version = null;
break;
case "iOS":
match = userAgent.match(/OS\ ((\d+[._])+\d+)\ like\ Mac\ OS\ X/);
break;
case "Android":
match = userAgent.match(/(?:Android|Adr)\ ((\d+[._])+\d+)/);
break;
case "BlackBerry":
case "BlackBerryOS":
match = userAgent.match(/Version\/((\d+\.)+\d+)/);
break;
case "BlackBerry Tablet OS":
match = userAgent.match(/RIM Tablet OS ((\d+\.)+\d+)/);
break;
default:
// no good default behavior
report.os.version = null;
break;
}
if (match && match[1]) {
// replace underscores in version number with periods
match[1] = match[1].replace(/_/g, ".");
report.os.version = match[1];
}
// pull in screen info from W3C standard properties
report.screen.width = screen.width;
report.screen.height = screen.height;
report.screen.colors = screen.colorDepth;
if (window.devicePixelRatio && !isNaN(window.devicePixelRatio)) {
report.screen.dppx = window.devicePixelRatio;
} else {
report.screen.dppx = 1;
}
// deprecate report.screen.size
if (definePropertySupported) {
Object.defineProperty(report.screen, "size", {
get: function () {
warning("screen.size is deprecated; use screen.width and screen.height");
return report.screen.width + " x " + report.screen.height;
}
});
}
// deprecate report.screen.resolution
if (definePropertySupported) {
Object.defineProperty(report.screen, "resolution", {
get: function () {
warning("screen.resolution is deprecated; multiply screen.width and screen.height by screen.dppx");
return (report.screen.dppx * report.screen.width) + " x " + (report.screen.dppx * report.screen.height);
}
});
}
// are web sockets supported
report.websockets = !!window.WebSocket;
// preferred language(s) for displaying pages
report.lang = navigator.languages || navigator.language;
// local date, time, and time zone
report.timestamp = (new Date()).toString();
return report;
};
window.browserReport = extractDataFromClient();
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment