1068

I have 5 addons/extensions for Firefox, Chrome, Internet Explorer(IE), Opera, and Safari.

How can I correctly recognize the user browser and redirect (once an install button has been clicked) to download the corresponding addon?

IT goldman
  • 14,885
  • 2
  • 14
  • 28
FrankC
  • 11,113
  • 4
  • 16
  • 21
  • 4
    try detectjs, it can be used for all browsers – dude Mar 09 '16 at 10:54
  • 1
    Possible duplicate of [Browser detection in JavaScript?](http://stackoverflow.com/questions/2400935/browser-detection-in-javascript) – Matthijs Wessels Sep 02 '16 at 10:23
  • 3
    detect.js is no longer maintained (according to https://github.com/darcyclarke/Detect.js), they recommend https://github.com/lancedikson/bowser – YakovL Apr 25 '18 at 17:02
  • I used UAParser Plugin, it is written in Vanilla JavaScript. Source: [How to detect browser, engine, OS, CPU, and device using JavaScript?](http://justcode.me/how-to/detect-browser-engine-os-cpu-and-device-using-javascript/) – Luzan Baral May 23 '18 at 06:22
  • 1
    Possible duplicate of [How can you detect the version of a browser?](https://stackoverflow.com/questions/5916900/how-can-you-detect-the-version-of-a-browser) – KyleMit Feb 14 '19 at 14:05
  • The MDN docs are useful: https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent – Elijah Mock Jan 30 '20 at 03:11
  • 4
    I'd like to re-surface this question - is there a reliable & simple answer to this yet? There are many (old) questions like this on SO and yet most of them work off the `userAgent` function which even w3schools acknowledges is inaccurate. I've tested some of the answers to this question and similar ones, and none of them seem reliable. If I'm better off asking a new question please let me know. – AutoBaker Mar 17 '21 at 16:20
  • See https://stackoverflow.com/questions/2400935/browser-detection-in-javascript – Shivam Jha Jun 14 '21 at 12:31

30 Answers30

1999

Googling for browser reliable detection often results in checking the User agent string. This method is not reliable, because it's trivial to spoof this value.
I've written a method to detect browsers by duck-typing.

Only use the browser detection method if it's truly necessary, such as showing browser-specific instructions to install an extension. Use feature detection when possible.

Demo: https://jsfiddle.net/6spj1059/

// Opera 8.0+
var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;

// Firefox 1.0+
var isFirefox = typeof InstallTrigger !== 'undefined';

// Safari 3.0+ "[object HTMLElementConstructor]" 
var isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && window['safari'].pushNotification));

// Internet Explorer 6-11
var isIE = /*@cc_on!@*/false || !!document.documentMode;

// Edge 20+
var isEdge = !isIE && !!window.StyleMedia;

// Chrome 1 - 79
var isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);

// Edge (based on chromium) detection
var isEdgeChromium = isChrome && (navigator.userAgent.indexOf("Edg") != -1);

// Blink engine detection
var isBlink = (isChrome || isOpera) && !!window.CSS;


var output = 'Detecting browsers by ducktyping:<hr>';
output += 'isFirefox: ' + isFirefox + '<br>';
output += 'isChrome: ' + isChrome + '<br>';
output += 'isSafari: ' + isSafari + '<br>';
output += 'isOpera: ' + isOpera + '<br>';
output += 'isIE: ' + isIE + '<br>';
output += 'isEdge: ' + isEdge + '<br>';
output += 'isEdgeChromium: ' + isEdgeChromium + '<br>';
output += 'isBlink: ' + isBlink + '<br>';
document.body.innerHTML = output;

Analysis of reliability

The previous method depended on properties of the rendering engine (-moz-box-sizing and -webkit-transform) to detect the browser. These prefixes will eventually be dropped, so to make detection even more robust, I switched to browser-specific characteristics:

  • Internet Explorer: JScript's Conditional compilation (up until IE9) and document.documentMode.
  • Edge: In Trident and Edge browsers, Microsoft's implementation exposes the StyleMedia constructor. Excluding Trident leaves us with Edge.
  • Edge (based on chromium): The user agent include the value "Edg/[version]" at the end (ex: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.16 Safari/537.36 Edg/80.0.361.9").
  • Firefox: Firefox's API to install add-ons: InstallTrigger
  • Chrome: The global chrome object, containing several properties including a documented chrome.webstore object.
  • Update 3 chrome.webstore is deprecated and undefined in recent versions
  • Safari: A unique naming pattern in its naming of constructors. This is the least durable method of all listed properties and guess what? In Safari 9.1.3 it was fixed. So we are checking against SafariRemoteNotification, which was introduced after version 7.1, to cover all Safaris from 3.0 and upwards.
  • Opera: window.opera has existed for years, but will be dropped when Opera replaces its engine with Blink + V8 (used by Chromium).
  • Update 1: Opera 15 has been released, its UA string looks like Chrome, but with the addition of "OPR". In this version the chrome object is defined (but chrome.webstore isn't). Since Opera tries hard to clone Chrome, I use user agent sniffing for this purpose.
  • Update 2: !!window.opr && opr.addons can be used to detect Opera 20+ (evergreen).
  • Blink: CSS.supports() was introduced in Blink once Google switched on Chrome 28. It's of course, the same Blink used in Opera.

Successfully tested in:

  • Firefox 0.8 - 61
  • Chrome 1.0 - 71
  • Opera 8.0 - 34
  • Safari 3.0 - 10
  • IE 6 - 11
  • Edge - 20-42
  • Edge Dev - 80.0.361.9

Updated in November 2016 to include detection of Safari browsers from 9.1.3 and upwards

Updated in August 2018 to update the latest successful tests on chrome, firefox IE and edge.

Updated in January 2019 to fix chrome detection (because of the window.chrome.webstore deprecation) and include the latest successful tests on chrome.

Updated in December 2019 to add Edge based on Chromium detection (based on the @Nimesh comment).

Adam M.
  • 1,071
  • 1
  • 7
  • 23
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • 9
    FYI This doesn't work with Chrome Extensions as ```window.chrome.webstore``` is undefined there. Haven't checked it with Firefox Extensions. ```is.js``` mentioned elsewhere does work in both Chrome and Firefox Extensions. – nevf Aug 31 '16 at 07:11
  • 82
    `isSafari` doesn't work with Safari 10. I'm going to argue this is a bad solution (not that I have a good one). There's no guarantee many of the things your checking for won't be removed OR won't be added by other browsers. Every site that was using this code for check for Safari just broke with macOS Sierra or Safari 10 upgrades :( – gman Sep 29 '16 at 05:16
  • 2
    @gman I agree with you. This solution works fine when you deploy it, but is not really future-proof as browsers evolves. – Sebastien Lorber Sep 29 '16 at 16:36
  • @gman I also agree with you. Regardless, I just evolved my solution to include Safaris from 9.1.3 and up :) – pilau Nov 02 '16 at 12:57
  • This breaks JS execution in Safari 10.0.1 as it doesn't know the objects "opr" and window.chrome, therefore I added two checks: – Marek Möhling Nov 15 '16 at 23:13
  • 1
    `var oprAddons = (typeof opr === 'object')? opr.addons : false;` – Marek Möhling Nov 15 '16 at 23:13
  • 1
    `var isOpera = (!!w.opr && !!oprAddons) || !!window.opera || n.userAgent.indexOf(' OPR/') >= 0;` – Marek Möhling Nov 15 '16 at 23:13
  • `var chromeWebstore = (typeof window.chrome === 'object')? window.chrome.webstore : false;` – Marek Möhling Nov 15 '16 at 23:13
  • `var isChrome = !!window.chrome && !!chromeWebstore;` – Marek Möhling Nov 15 '16 at 23:14
  • 1
    I don't know how to insert line breaks in comments so I used several comments. btw., I've no Mac at home so I used macincloud.com for Safari testing. Very slow RDP connection to a virtual Mac but nifty anyway, 24h trial for 99c. – Marek Möhling Nov 15 '16 at 23:17
  • 2
    In Chrome it says "true" also for Blink. – alejnavab Dec 16 '16 at 05:25
  • 13
    But has this been tested on the **mobile versions** of those browsers as well as the **desktop versions** too? And truthfully, there are different mobile versions and different desktop versions per platform. So really, firefox has 3 binaries for Windows, Linux, Mac OS, and 2 binaries for Android and iOS. – DrZ214 Dec 23 '16 at 03:53
  • I am particularly trying to detect if the browser is Chrome or Firefox, and it seems to work great in Windows, Debian and MacOS for both browsers. In Android, it fails detecting Chrome, and in iPhone it fails for both of them. – adripanico Jan 11 '17 at 16:25
  • 1
    Thank you. Though, just tested on Chrome 55.0.2883.87 m, and it didn't work. – dnns Jan 31 '17 at 07:30
  • I'd like to check for chrome and this is definitely not working on latest chrome mobile .55 version :/ – Manuel Feb 04 '17 at 13:51
  • A general question though, why `!!document.documentMode`? Instead this is good without this `!!`. – N00b Pr0grammer Apr 19 '17 at 03:24
  • Mozilla added the [`runtime.getBrowserInfo()`](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/runtime/getBrowserInfo) WebExtension-API to get information about the browser in which an add-on is running. – johnp May 03 '17 at 13:17
  • It does not work with desktop version of Safari/603.2.4, anyone knows a solution? – LeOpArD Aug 02 '17 at 23:27
  • @LeOpArD add `/constructor/i.test(function HTMLElementConstructor() {}) || ` to the beginning of the safari test – buggedcom Sep 04 '17 at 11:28
  • 5
    The current `isSafari` does not work under ` – Mikko Ohtamaa Sep 14 '17 at 19:24
  • 1
    ReactJS Addendum: Since React is strongly-typed, this will cause compile-time errors for lack of definition in var's opr and safari. – HoldOffHunger Oct 26 '17 at 20:55
  • 2
    Note: When Chrome is run headless, there is no `window.chrome` object. – Alexander O'Mara Oct 27 '17 at 04:00
  • 4
    I get this error in safari `'safari' is not defined` – Badrush Nov 28 '17 at 05:54
  • Thanks for the ans. Worked for Desktop but not working in Android phone especially for Chrome. tell me if any solution there,, thanks again... –  Jan 19 '18 at 16:07
  • 4
    "It's trivial to spoof this value" -- Why is this being acknowledged at all? ANY form of browser detection *can* be spoofed. That doesn't matter at all; browser detection is largely a form of convenience to let people know of browser UI hints, known issues, etc., and user agents are a perfectly valid way to do that. This answer feels like a terrible mixed misunderstanding of feature detection vs user agent sniffing, and I'm really not sure why it's so popular. Nothing you've said is technically incorrect, but this is an incredibly unhelpful answer. – Katana314 Mar 13 '18 at 16:31
  • Detecting mobile browser: https://stackoverflow.com/questions/11381673/detecting-a-mobile-browser?rq=1 – S. Mayol Jun 07 '18 at 16:33
  • 2
    FYI `!!window.chrome && !!window.chrome.webstore;` returns `false` when Chrome is in headless mode. – Ally Jun 22 '18 at 04:59
  • Firefox `typeof InstallTrigger` is returning `undefined` for me in Firefox v25. I am using it in the debug console – Katie Jun 26 '18 at 22:54
  • Chrome v.64 will report back "Safari". – HoldOffHunger Sep 14 '18 at 17:57
  • 35
    window.chrome.webstore is deprecated starting from Chrome ver. 71: https://blog.chromium.org/2018/06/improving-extension-transparency-for.html – st_bk Oct 29 '18 at 06:48
  • 1
    !!window.chrome.webstore return false from chrome on android. – ali-myousefi Nov 13 '18 at 13:05
  • 3
    Chrome test (due to v71 obsolescence) can be fixed by `!!window.chrome && !isOpera`. – LB2 Dec 06 '18 at 00:47
  • As `chrome` and others are non-standard `window` properties it would be safer to use `window.hasOwnProperty('chrome')`. In other hand I am personally not a big fan of double negation. It is confusing when reading code. – David Dec 06 '18 at 10:23
  • I think you get less credit so thank you for coming up with a great solution. The usage of navigator.userAgent is rampant and i feel that your direction should be implemented natively. – NishM Dec 07 '18 at 19:26
  • 2
    Turns out `!!window.chrome && !isOpera` doesn't work as it matches for Edge. – LB2 Dec 10 '18 at 23:58
  • `!!window.navigator.plugins.namedItem('Chrome PDF Plugin')` – xdumaine Dec 13 '18 at 22:01
  • Its browser version dependent and doen't work in Chrome 71(tested). My code broke and it took lot of time to figure out. – raj Dec 19 '18 at 06:39
  • isChrome: false with Chrome 71 win7 – user3112634 Jan 03 '19 at 11:17
  • Can confirm on chrome. Does no work on Chrome 71 & 72. – aldoblack Jan 31 '19 at 15:14
  • var isChrome = !!window.chrome && !!window.Browser && window.Browser.name === 'chrome'; This appropriately identifies Chrome, but excludes Edge. Haven't tested with Opera. – Matt L Jan 31 '19 at 21:37
  • FYI Edge will be switching to the Chromium engine: https://www.theverge.com/2018/12/4/18125238/microsoft-chrome-browser-windows-10-edge-chromium – RyanNerd Feb 14 '19 at 20:24
  • it's false for all on chrome on ios – Reza Mar 13 '19 at 18:58
  • 3
    Took some time to figure out, so it might help some: `!!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime)` will fail when you open local domains or IPs! Chrome seems to invalidate the runtime when you browse to a local page. – eyecatchUp Mar 17 '19 at 21:19
  • 2
    Adding to @eyecatchUp, it seems that the chrome test works on https pages, but not http pages (without ssl). – murrayju Mar 20 '19 at 17:02
  • 2
    This seems to work better: `var isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.csi)` It at least works when the URL is not SSL and reports correctly on Edge. I'm not sure about Safari. – Ryan Shillington Mar 25 '19 at 20:35
  • As of right now, my chrome Version 74.0.3729.169 says `isChrome: true` and `isBlink: true` So seems like there is an issue here. – Stender May 28 '19 at 10:38
  • Why used: `false || !!document.documentMode` if it is equivalent to `!!document.documentMode`? Am I missing something? – vrintle Jun 02 '19 at 03:52
  • isChrome being true through Opera. Not a problem as Opera behaviour is too similar to Chrome but is still a missmatch. – Carlos López Marí Jul 01 '19 at 10:21
  • 3
    "because it's trivial to spoof this value." so what? If a browser is pretending to be something else, then why should the site care? – UKMonkey Aug 30 '19 at 19:38
  • @UKMonkey, have you found any lightweight solution to find a browser using userAgent? – Kiura Sep 12 '19 at 07:14
  • @Kiura not sure what exactly you mean, but the answer from Nimesh seems to be what you're looking for? – UKMonkey Sep 12 '19 at 15:35
  • @UKMonkey, yes, It is what I am looking for. Although I needed more browsers (like Yandex browser, Vivaldi, etc..). So finally I found a library that does what I need, in case other people are interested the library is called bowser – Kiura Sep 13 '19 at 12:58
  • use document['documentMode'] instead of document.documentMode, if you want to get rid of the error/warning message – Chethan Oct 15 '19 at 00:28
  • 4
    Seems pretty ridiculous to me that we have to go through all this to find out which browser is being used. I would think it would make sense for the browser vendors to agree on a standard javascript variable they can all send down, some crazy name like 'browserName'! – dmikester1 Dec 27 '19 at 16:30
  • Isn’t the Edge Chromium detection of just the substring “Edg” going to match on the old “Edge” (Trident based)? – scunliffe Jan 15 '20 at 17:57
  • Anyone has code to also detect Safari 11, 12 and 13? – Tiago Sousa Feb 19 '20 at 11:45
  • 2
    Chrome 80 and 81 are not detected with this. And not Safari on iOS (no idea where it has its version tag). – ygoe Apr 17 '20 at 19:25
  • This has failed to detect Firefox 78. – BReddy Jul 09 '20 at 01:05
  • isEdgeChromium is false for Edge Version 83.0.478.61 (Official build) (64-bit). Otherwise this works for the latest Safari, Firefox, and Chrome on Windows 10 and OSX Catalina. – Sideways S Jul 10 '20 at 23:47
  • 3
    Safari detection is no longer working as of Safari 14 Beta 2 on macOS 10.15.6 Catalina. – Ray Shan Aug 09 '20 at 07:05
  • 2
    I'm running Edge Chromium, but it says false for it. Everything is false. – Shaun Roselt Aug 20 '20 at 09:23
  • 4
    After reading all the comments I will never use duck typing to detect which browser is being used ever again. Using the userAgent string is not without it's problems but still seems like the best option and is still the preferred method by Google. – PHP Guru Nov 01 '20 at 07:37
  • 2
    Unfortunately not working under iOS 12.4.9 ipad Air in all three browsers: Safari, Chrome, Firefox – igolkotek Dec 06 '20 at 15:23
  • Is it intended, that on EdgeChromium and on Opera also isChrome == true? Besides that, it is kind a cool hack! :) – PjotrC Feb 11 '21 at 20:43
  • 1
    Please do not do that. It creates issues down the line for browser implementers and web developpers. When using non standard API for detecting a browser, basically we solidify the existence of this API and makes it part of the Web platform. The more people rely on it, the more the browser implementer will be unable to remove it one day because removing it will break websites. – karlcow Mar 08 '21 at 02:10
  • 2
    @dmikester1—one reason vendors do not want to standardise *navigator.useragent* is because they do not want their users to see "*Your browser is not supported, please download a supported browser from …*" like in the Netscape vs IE days. – RobG Mar 30 '21 at 23:27
  • please update it, because it's doesn't work in Edge Chromium, `(!!window.chrome.webstore || !!window.chrome.runtime)` always return false – Tamsamani Apr 27 '21 at 12:01
  • 2
    Chrome 71+ returns false. This answer needs to be updated... – greensin May 24 '21 at 09:17
  • 1
    isChrome: true on edge browser – dilipkumar katre May 31 '21 at 13:23
  • Doesn't work in modules it seems, well it's pretty damn stupid that this sort of approach is what one would have to resort to. It's brittle & can change at any time. Well, seeing as its javascript pretty much explains most of it. – Ylisar Sep 17 '21 at 13:48
  • 4
    it's not working anymore – joantoh Oct 08 '21 at 03:43
  • 3
    As of 2022, Firefox detection with InstallTrigger is going to break because it's going away around Firefox 103 or so. – Tanriol Jun 29 '22 at 13:02
  • I was trying to use this in a browser extension background script, but got an error that `'window' is not defined` which is understandable because it's a background script and doesn't have a window. Is there any solution to that? – Gangula Sep 19 '22 at 18:40
  • 1
    This is ever-obsolete. Instead use https://www.npmjs.com/package/detect-browser – Abel Wenning Oct 25 '22 at 17:37
  • 1
    This solution no longer works in modern browsers, as mentioned above. – RPaladin Dec 06 '22 at 18:07
  • 2
    This doesn't work for me. I get all "false" n MS Edge Version 108.0.1462.46. Your answer is extremely overrated with 1900+ upvotes. @Nimesh's answer below has only 184 upvotes and it works! – Apostolos Dec 10 '22 at 18:57
  • 2
    For Firefox version 112+ the check for `InstallTrigger` does not work anymore. `typeof mozInnerScreenX !== 'undefined'` might be an alternative. – Marcus Krahl Mar 21 '23 at 11:45
197

You can try following way to check Browser version.

    <!DOCTYPE html>
    <html>
    <body>
    <p>What is the name(s) of your browser?</p>
    <button onclick="myFunction()">Try it</button>
    <p id="demo"></p>
    <script>
    
    function myFunction() { 
     if((navigator.userAgent.indexOf("Opera") || navigator.userAgent.indexOf('OPR')) != -1 ) 
    {
        alert('Opera');
    }
    else if(navigator.userAgent.indexOf("Edg") != -1 )
    {
        alert('Edge');
    }
    else if(navigator.userAgent.indexOf("Chrome") != -1 )
    {
        alert('Chrome');
    }
    else if(navigator.userAgent.indexOf("Safari") != -1)
    {
        alert('Safari');
    }
    else if(navigator.userAgent.indexOf("Firefox") != -1 ) 
    {
         alert('Firefox');
    }
    else if((navigator.userAgent.indexOf("MSIE") != -1 ) || (!!document.documentMode == true )) //IF IE > 10
    {
      alert('IE'); 
    }  
    else 
    {
       alert('unknown');
    }
    }
    </script>
    
    </body>
    </html>

And if you need to know only IE Browser version then you can follow below code. This code works well for version IE6 to IE11

<!DOCTYPE html>
<html>
<body>

<p>Click on Try button to check IE Browser version.</p>

<button onclick="getInternetExplorerVersion()">Try it</button>

<p id="demo"></p>

<script>
function getInternetExplorerVersion() {
   var ua = window.navigator.userAgent;
        var msie = ua.indexOf("MSIE ");
        var rv = -1;

        if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))      // If Internet Explorer, return version number
        {               

            if (isNaN(parseInt(ua.substring(msie + 5, ua.indexOf(".", msie))))) {
                //For IE 11 >
                if (navigator.appName == 'Netscape') {
                    var ua = navigator.userAgent;
                    var re = new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})");
                    if (re.exec(ua) != null) {
                        rv = parseFloat(RegExp.$1);
                        alert(rv);
                    }
                }
                else {
                    alert('otherbrowser');
                }
            }
            else {
                //For < IE11
                alert(parseInt(ua.substring(msie + 5, ua.indexOf(".", msie))));
            }
            return false;
        }}
</script>

</body>
</html>
John Henckel
  • 10,274
  • 3
  • 79
  • 79
Nimesh
  • 3,342
  • 1
  • 28
  • 35
  • 4
    Why would one write so many lines of code? userAgent is ambiguous. – igauravsehrawat Oct 15 '15 at 07:00
  • 7
    What about Microsoft Edge? – user6031759 Jun 15 '16 at 23:25
  • doesn't work. Using Chrome 51 and user agent includes Safari string: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36 – Ricardo stands with Ukraine Jun 28 '16 at 10:29
  • 4
    the answer above checks for chrome before checking for safari. because safari will not have `chrome` keyword in the useragent. example of safari useragent - `mozilla/5.0 (macintosh; intel mac os x 10_11_5) applewebkit/601.6.17 (khtml, like gecko) version/9.1.1 safari/601.6.17` – Golak Sarangi Aug 17 '16 at 04:07
  • 27
    Stackoverflow uses this method – vityavv Sep 07 '16 at 14:02
  • Work smoothly on Chrome 55, Firefox 50 and IE 11, but not on Edge 38.14393.0.0 (shows "Chrome"). Thank you. – dnns Jan 31 '17 at 07:38
  • Edge has safari in it, need to check edge prior to safari – Andrew Aug 21 '17 at 17:37
  • and what we should write for chrome in ipad? –  Oct 26 '17 at 09:10
  • 7
    When testing this in Opera (latest version), this returns 'Chrome' for me. To fix this, I changed the Opera if statement to: `if(navigator.userAgent.indexOf("Opera") != -1 || navigator.userAgent.indexOf('OPR') != -1 )` – Kyle Vassella Dec 05 '17 at 23:05
  • At least use a switch block. – Joshua Jan 21 '18 at 01:55
  • 3
    For some reason my `navigator.userAgent` in chrome includes Safari: `"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"` but my firefox does not: `"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:25.0) Gecko/20100101 Firefox/25.0"` – Katie Jun 26 '18 at 22:59
  • I've heard `navigator.userAgent` is unreliable because of spoofing... – Elijah Mock Jan 30 '20 at 03:10
  • 2
    Which is expected and desired: if someone sets their UA to a different browser, they're doing that to get the content that would get served for that browser. User agent spoofing is literally why you want a browser detection solution based on userAgent instead of using duck typing, as you're generating different content for different browsers (as opposed to trying to implement progressive enhancement based on JS support, which should use duck typing because you'd need feature detection). – Mike 'Pomax' Kamermans Nov 18 '21 at 21:37
  • This is my userAgent string in Chrome!! ```'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36'``` This method doesn't work since it contains Safari and Mozilla too. – Hyuga Hinata Feb 23 '22 at 17:10
  • Yes! This works! You should get the most upvotes, not the first answer, which got 1900 upvotes and it doesn't work. – Apostolos Dec 10 '22 at 19:01
  • it doesn't handle brave browser – GorvGoyl Jan 13 '23 at 06:46
  • @GorvGoyl Brave will never work because they intentionally hide it from the user agent. Check https://github.com/brave/browser-laptop/blob/master/CHANGELOG.md#090 – alexandernst Jan 15 '23 at 13:38
  • 1
    @alexandernst there's a way https://stackoverflow.com/questions/36523448/how-do-i-tell-if-a-user-is-using-brave-as-their-browser – GorvGoyl Jan 16 '23 at 08:22
  • This detects Chrome on IOS as Safari! Take care – strix25 May 24 '23 at 12:05
79

Here are several prominent libraries that handle browser detection as of Dec 2019.

Bowser by lancedikson - 4,065★s - Last updated Oct 2, 2019 - 4.8KB

var result = bowser.getParser(window.navigator.userAgent);
console.log(result);
document.write("You are using " + result.parsedResult.browser.name +
               " v" + result.parsedResult.browser.version + 
               " on " + result.parsedResult.os.name);
<script src="https://unpkg.com/bowser@2.7.0/es5.js"></script>

*supports Edge based on Chromium


Platform.js by bestiejs - 2,550★s - Last updated Apr 14, 2019 - 5.9KB

console.log(platform);
document.write("You are using " + platform.name +
               " v" + platform.version + 
               " on " + platform.os);
<script src="https://cdnjs.cloudflare.com/ajax/libs/platform/1.3.5/platform.min.js"></script>

jQuery Browser by gabceb - 504★s - Last updated Nov 23, 2015 - 1.3KB

console.log($.browser)
document.write("You are using " + $.browser.name +
               " v" + $.browser.versionNumber + 
               " on " + $.browser.platform);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-browser/0.1.0/jquery.browser.min.js"></script>

Detect.js (Archived) by darcyclarke - 522★s - Last updated Oct 26, 2015 - 2.9KB

var result = detect.parse(navigator.userAgent);
console.log(result);
document.write("You are using " + result.browser.family +
               " v" + result.browser.version + 
               " on " + result.os.family);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Detect.js/2.2.2/detect.min.js"></script>

Browser Detect (Archived) by QuirksMode - Last updated Nov 14, 2013 - 884B

console.log(BrowserDetect)
document.write("You are using " + BrowserDetect.browser +
               " v" + BrowserDetect.version + 
               " on " + BrowserDetect.OS);
<script src="https://kylemit.github.io/libraries/libraries/BrowserDetect.js"></script>

Notable Mentions:

  • WhichBrowser - 1,355★s - Last updated Oct 2, 2018
  • Modernizr - 23,397★s - Last updated Jan 12, 2019 - To feed a fed horse, feature detection should drive any canIuse style questions. Browser detection is really just for providing customized images, download files, or instructions for individual browsers.

Further Reading

KyleMit
  • 30,350
  • 66
  • 462
  • 664
70

I know it may be overkill to use a lib for that, but just to enrich the thread, you could check is.js way of doing this:

is.firefox();
is.ie(6);
is.not.safari();
Rafael Eyng
  • 4,720
  • 2
  • 33
  • 34
  • 14
    Just worth noting that under the hood it's primarily doing User-Agent detection. Supplemented with vendor detection / some feature detection in places. – TygerKrash Oct 20 '15 at 09:50
  • 1
    @TygerKrash sure, you are absolutely right. That is actually what I meant with my answer: open the source code of `is.js` and check how they do it. – Rafael Eyng Apr 17 '16 at 16:26
  • 4
    jQuery used to include similar properties: $.browser.msie... Were removed from version 1.9 http://api.jquery.com/jquery.browser/ – Ricardo stands with Ukraine Jun 29 '16 at 09:08
  • @RafaelEyng: I think the issue with it doing User-Agent detection is that this method is unreliable. – HoldOffHunger Oct 26 '17 at 20:30
  • 1
    This is definitely the most robust approach when you assume that the UA string hasn't been modified. It also properly detects OS (android, win, mac, linux); device type (desktop, tablet, mobile). It can also test for version of browser. – kashiraja Feb 17 '19 at 07:23
  • is.js Bug: is.Chrome() returns false on the Google Chrome of all iOS Devices. MacOS on Chrome works. – akcasoy Aug 23 '19 at 06:38
50

In case anyone finds this useful, I've made Rob W's answer into a function that returns the browser string rather than having multiple variables floating about. Since the browser also can't really change without loading all over again, I've made it cache the result to prevent it from needing to work it out the next time the function is called.

/**
 * Gets the browser name or returns an empty string if unknown. 
 * This function also caches the result to provide for any 
 * future calls this function has.
 *
 * @returns {string}
 */
var browser = function() {
    // Return cached result if avalible, else get result then cache it.
    if (browser.prototype._cachedResult)
        return browser.prototype._cachedResult;

    // Opera 8.0+
    var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;

    // Firefox 1.0+
    var isFirefox = typeof InstallTrigger !== 'undefined';

    // Safari 3.0+ "[object HTMLElementConstructor]" 
    var isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || safari.pushNotification);

    // Internet Explorer 6-11
    var isIE = /*@cc_on!@*/false || !!document.documentMode;

    // Edge 20+
    var isEdge = !isIE && !!window.StyleMedia;

    // Chrome 1+
    var isChrome = !!window.chrome && !!window.chrome.webstore;

    // Blink engine detection
    var isBlink = (isChrome || isOpera) && !!window.CSS;

    return browser.prototype._cachedResult =
        isOpera ? 'Opera' :
        isFirefox ? 'Firefox' :
        isSafari ? 'Safari' :
        isChrome ? 'Chrome' :
        isIE ? 'IE' :
        isEdge ? 'Edge' :
        isBlink ? 'Blink' :
        "Don't know";
};

console.log(browser());
HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Will Squire
  • 6,127
  • 7
  • 45
  • 57
50

Short variant (update 10 july 2020 mobile browser detection fix)

var browser = (function() {
    var test = function(regexp) {return regexp.test(window.navigator.userAgent)}
    switch (true) {
        case test(/edg/i): return "Microsoft Edge";
        case test(/trident/i): return "Microsoft Internet Explorer";
        case test(/firefox|fxios/i): return "Mozilla Firefox";
        case test(/opr\//i): return "Opera";
        case test(/ucbrowser/i): return "UC Browser";
        case test(/samsungbrowser/i): return "Samsung Browser";
        case test(/chrome|chromium|crios/i): return "Google Chrome";
        case test(/safari/i): return "Apple Safari";
        default: return "Other";
    }
})();
console.log(browser)

Typescript version:

export enum BROWSER_ENUM {
  EDGE ,
  INTERNET_EXPLORER ,
  FIRE_FOX ,
  OPERA ,
  UC_BROWSER ,
  SAMSUNG_BROWSER ,
  CHROME ,
  SAFARI ,
  UNKNOWN ,
}

const testUserAgent = (regexp: RegExp): boolean => regexp.test(window.navigator.userAgent);

function detectBrowser(): BROWSER_ENUM {
  switch (true) {
    case testUserAgent(/edg/i): return BROWSER_ENUM.EDGE;
    case testUserAgent(/trident/i): return BROWSER_ENUM.INTERNET_EXPLORER;
    case testUserAgent(/firefox|fxios/i): return BROWSER_ENUM.FIRE_FOX;
    case testUserAgent(/opr\//i): return BROWSER_ENUM.OPERA;
    case testUserAgent(/ucbrowser/i): return BROWSER_ENUM.UC_BROWSER;
    case testUserAgent(/samsungbrowser/i): return BROWSER_ENUM.SAMSUNG_BROWSER;
    case testUserAgent(/chrome|chromium|crios/i): return BROWSER_ENUM.CHROME;
    case testUserAgent(/safari/i): return BROWSER_ENUM.SAFARI;
    default: return BROWSER_ENUM.UNKNOWN;
  }
}

export const BROWSER: BROWSER_ENUM = detectBrowser();

export const IS_FIREFOX = BROWSER === BROWSER_ENUM.FIRE_FOX;

Functional algorithm, just for fun:

 var BROWSER =  new Array(
     ["Microsoft Edge", /edg/i],
     ["Microsoft Internet Explorer", /trident/i],
     ["Mozilla Firefox", /firefox|fxios/i],
     ["Opera", /opr\//i],
     ["UC Browser", /ucbrowser/i],
     ["Samsung Browser", /samsungbrowser/i],
     ["Google Chrome", /chrome|chromium|crios/i],
     ["Apple Safari", /safari/i],
     ["Unknown", /.+/i],
 ).find(([, value]) => value.test(window.navigator.userAgent)).shift();
Alex Nikulin
  • 8,194
  • 4
  • 35
  • 37
  • If you dislikes me, please explain why. – Alex Nikulin Mar 23 '18 at 11:16
  • 5
    this will show 'safari' while browsing with 'chrome' on ios – Reza Mar 13 '19 at 19:06
  • 2
    This method worked with Chrome and Firefox on desktop and Safari on iOS. It fails with Chrome and Firefox on iOS. – BReddy Jul 09 '20 at 01:09
  • @BReddy retest this please, I haven't any apple device:) – Alex Nikulin Jul 09 '20 at 11:42
  • I tested this with Firefox (78.0.1 on Win10), Chrome (83.0 on Win10), Edge (83.0 on Win10 - Chromium base), Firefox(27 on iOS), and Chrome (83.0 on iOS) successfully. This logic still reported Safari (on iOS 13.5.1) still reported as 'chrome'. Could this be because Chromium is derived from WebKit base? – BReddy Jul 09 '20 at 16:24
  • @BReddy yes all webkits are similar, but have some different features.But browsers can have different useragents on ios. For example firefox and chrome on ios have fxios and crios strings. Retest it please) – Alex Nikulin Jul 10 '20 at 05:04
  • It does work on both Chrome and Safari on macOs. @BReddy: Order does matter here, hence the Safari check needs to be after Chrome. – pompalini Aug 17 '20 at 19:56
  • this works for me since I'm targeting Chrome, Edge, Firefox (later Safari) only. But is it currently reliable for all browsers? – Gangula Sep 19 '22 at 12:51
  • 1
    @Gangula it currently reliable for all browsers that you see in a code)Microsoft Edge,Microsoft Internet Explorer,Opera,Firefox,Uc,samsung,chrome,safari – Alex Nikulin Oct 03 '22 at 17:14
14

No idea if it is useful to anyone but here is a variant that would make TypeScript happy:

export function getBrowser() {

 // Opera 8.0+
    if ((!!window["opr"] && !!["opr"]["addons"]) || !!window["opera"] || navigator.userAgent.indexOf(' OPR/') >= 0) {
        return 'opera';
    }

    // Firefox 1.0+
    if (typeof window["InstallTrigger"] !== 'undefined') {
        return 'firefox';
    }

    // Safari 3.0+ "[object HTMLElementConstructor]" 
    if (/constructor/i.test(window["HTMLElement"]) || (function(p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof window["safari"] !== 'undefined' && window["safari"].pushNotification))) {
        return 'safari';
    }

    // Internet Explorer 6-11
    if (/*@cc_on!@*/false || !!document["documentMode"]) {
        return 'ie';
    }

    // Edge 20+
    if (!(/*@cc_on!@*/false || !!document["documentMode"]) && !!window["StyleMedia"]) {
        return 'edge';
    }

    // Chrome 1+
    if (!!window["chrome"] && !!window["chrome"].webstore) {
        return 'chrome';
    }

    // Blink engine detection
    if (((!!window["chrome"] && !!window["chrome"].webstore) || ((!!window["opr"] && !!["opr"]["addons"]) || !!window["opera"] || navigator.userAgent.indexOf(' OPR/') >= 0)) && !!window["CSS"]) {
        return 'blink';
    }
}
Emma
  • 27,428
  • 11
  • 44
  • 69
Tony Smith
  • 869
  • 1
  • 11
  • 25
  • 1
    Why do you have some ifs with "false" as a condition? – CodeMonkey Oct 28 '19 at 11:45
  • @YonatanNir I think it's meant to detect conditional compilation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Microsoft_Extensions/at-cc-on – Lucas Azevedo Mar 05 '20 at 12:13
  • Typescript say the same with this: Argument of type '{ new (): HTMLElement; prototype: HTMLElement; }' is not assignable to parameter of type 'string' – Jorge Monroy Sep 09 '21 at 21:40
13

Thank you, everybody. I tested the code snippets here on the recent browsers: Chrome 55, Firefox 50, IE 11 and Edge 38, and I came up with the following combination that worked for me for all of them. I'm sure it can be improved, but it's a quick solution for whoever needs:

var browser_name = '';
isIE = /*@cc_on!@*/false || !!document.documentMode;
isEdge = !isIE && !!window.StyleMedia;
if(navigator.userAgent.indexOf("Chrome") != -1 && !isEdge)
{
    browser_name = 'chrome';
}
else if(navigator.userAgent.indexOf("Safari") != -1 && !isEdge)
{
    browser_name = 'safari';
}
else if(navigator.userAgent.indexOf("Firefox") != -1 ) 
{
    browser_name = 'firefox';
}
else if((navigator.userAgent.indexOf("MSIE") != -1 ) || (!!document.documentMode == true )) //IF IE > 10
{
    browser_name = 'ie';
}
else if(isEdge)
{
    browser_name = 'edge';
}
else 
{
   browser_name = 'other-browser';
}
$('html').addClass(browser_name);

It adds a CSS class to the HTML, with the name of the browser.

dnns
  • 326
  • 4
  • 10
12

Here's a 2016 adjusted version of Rob's answer, including Microsoft Edge and detection of Blink:

(edit: I updated Rob's answer above with this information.)

// Opera 8.0+ (UA detection to detect Blink/v8-powered Opera)
isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
// Firefox 1.0+
isFirefox = typeof InstallTrigger !== 'undefined';
// Safari 3.0+
isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || safari.pushNotification);
// Internet Explorer 6-11
isIE = /*@cc_on!@*/false || !!document.documentMode;
// Edge 20+
isEdge = !isIE && !!window.StyleMedia;
// Chrome 1+
isChrome = !!window.chrome && !!window.chrome.webstore;
// Blink engine detection
isBlink = (isChrome || isOpera) && !!window.CSS;

/* Results: */
console.log("isOpera", isOpera);
console.log("isFirefox", isFirefox);
console.log("isSafari", isSafari);
console.log("isIE", isIE);
console.log("isEdge", isEdge);
console.log("isChrome", isChrome);
console.log("isBlink", isBlink);

The beauty of this approach is that it relies on browser engine properties, so it covers even derivative browsers, such as Yandex or Vivaldi, which are practically compatible with the major browsers whose engines they use. The exception is Opera, which relies on user agent sniffing, but today (i.e. ver. 15 and up) even Opera is itself only a shell for Blink.

pilau
  • 6,635
  • 4
  • 56
  • 69
  • The `!!window.MSAssertion;` test doesn't work for me in the Edge beta via Remote Desktop. It returns false. – NoR Jan 20 '16 at 16:45
  • @NoR What version of Edge are you using? It matters – pilau Jan 20 '16 at 16:59
  • The VM Version: 20150801 --- Edge Version: 20.10240.16384.0 – NoR Jan 20 '16 at 17:21
  • 1
    @NoR Oh you're using the VM... The `MSAssertion` trick is adjusted to version 25. But since many devs rely on the VMs, I'll try to adjust it this older version. Good call. Thanks. – pilau Jan 20 '16 at 17:42
  • 1
    @NoR Updated - should be futureproof. The `StyleMedia` (capitalized) object is specific to IE and Edge and doesn't seem to be going anywhere. – pilau Jan 20 '16 at 20:07
  • @IssacGable let's fix it - which version? – pilau Aug 13 '17 at 06:43
  • @pilau Safai Version 10.1.2 (12603.3.8) – Issac Gable Aug 14 '17 at 16:06
  • 1
    I have also found [UAParser](https://github.com/faisalman/ua-parser-js) a js plugin that still maintained and has be highly accurate and easy to use. – Issac Gable Aug 14 '17 at 16:08
  • Property `window.chrome.webstore` was removed in Chrome 71, so this approach is no longer working. – Bedla Dec 19 '18 at 10:35
11

You can use try and catch to use the different browser error messages. IE and edge were mixed up, but I used the duck typing from Rob W (based on this project here: https://www.khanacademy.org/computer-programming/i-have-opera/2395080328).

var getBrowser = function() {        
    try {
        var e;
        var f = e.width;
    } catch(e) {
        var err = e.toString();

        if(err.indexOf("not an object") !== -1) {
            return "safari";
        } else if(err.indexOf("Cannot read") !== -1) {
            return "chrome";
        } else if(err.indexOf("e is undefined") !== -1) {
            return "firefox";
        } else if(err.indexOf("Unable to get property 'width' of undefined or null reference") !== -1) {
            if(!(false || !!document.documentMode) && !!window.StyleMedia) {
                return "edge";
            } else {
                return "IE";
            }
        } else if(err.indexOf("cannot convert e into object") !== -1) {
            return "opera";
        } else {
            return undefined;
        }
    }
};
Mason Jones
  • 151
  • 2
  • 7
  • 1
    That's a great idea: you don't need neither "window", nor "navigator" objects! – Vadim Dec 13 '17 at 15:42
  • My suggestion is to get rid document and window completely. See IE chunk: return "firefox"; } else if(err.search("[object Error]") !== -1 && e.message != null && e.description != null){ return "IE"; } else if(err.search("cannot convert e into object") !== -1){ return "opera"; – Vadim Dec 13 '17 at 16:07
  • How does that differentiate between IE and edge? – Mason Jones Dec 18 '17 at 18:40
  • Strange, I can't reproduce err.search("[object Error]") anymore. Anyway, for me firefox vs chrome vs some thing else is enough. I use it in a PAC file where window and document objects are not available. – Vadim Dec 21 '17 at 12:05
  • Just figured out the cause. It looks like that for funning a PAC file Windows 7 does not use IE11, which is installed at my machine, but rather IE7-like engine (probably from the Windows host). So err.toString() there gives "[object Error]" while inside the IE11 it gives "Unable to get property..." string as in your code. So, the code above should fail with the IE7. – Vadim Dec 21 '17 at 12:19
  • Running Chrome 67 and Opera 54 (OS X), they both return the same error string :( – brasofilo Aug 02 '18 at 01:04
7

If you need to know what is the numeric version of some particular browser you can use the following snippet. Currently it will tell you the version of Chrome/Chromium/Firefox:

var match = $window.navigator.userAgent.match(/(?:Chrom(?:e|ium)|Firefox)\/([0-9]+)\./);
var ver = match ? parseInt(match[1], 10) : 0;
HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Valera Tumash
  • 628
  • 7
  • 16
7

Detecting Browsers on Desktop and Mobile : Edge, Opera, Chrome, Safari, Firefox, IE

I did some changes in @nimesh code now it is working for Edge also, and Opera issue fixed:

function getBrowserName() {

    if ( navigator.userAgent.indexOf("Edge") > -1 && navigator.appVersion.indexOf('Edge') > -1 ) {
        return 'Edge';
    }
    else if( navigator.userAgent.indexOf("Opera") != -1 || navigator.userAgent.indexOf('OPR') != -1 )
    {
        return 'Opera';
    }
    else if( navigator.userAgent.indexOf("Chrome") != -1 )
    {
        return 'Chrome';
    }
    else if( navigator.userAgent.indexOf("Safari") != -1)
    {
        return 'Safari';
    }
    else if( navigator.userAgent.indexOf("Firefox") != -1 ) 
    {
        return 'Firefox';
    }
    else if( ( navigator.userAgent.indexOf("MSIE") != -1 ) || (!!document.documentMode == true ) ) //IF IE > 10
    {
        return 'IE';
    }  
    else 
    {
        return 'unknown';
    }
}

Thanks @nimesh user:2063564

Irshad Khan
  • 5,670
  • 2
  • 44
  • 39
7

Detecting Browser and Its version

This code snippet is based on the article from MDN. Where they gave a brief hint about various keywords that can be used to detect the browser name.

reference

The data shown in the image above is not sufficient for detecting all the browsers e.g. userAgent of Firefox will have Fxios as a keyword rather than Firefox.

A few changes are also done to detect browsers like Edge and UCBrowser

The code is currently tested for the following browsers by changing userAgent with the help of dev-tools (How to change userAgent):

  • FireFox
  • Chrome
  • IE
  • Edge
  • Opera
  • Safari
  • UCBrowser

getBrowser = () => {
    const userAgent = navigator.userAgent;
    let browser = "unkown";
    // Detect browser name
    browser = (/ucbrowser/i).test(userAgent) ? 'UCBrowser' : browser;
    browser = (/edg/i).test(userAgent) ? 'Edge' : browser;
    browser = (/googlebot/i).test(userAgent) ? 'GoogleBot' : browser;
    browser = (/chromium/i).test(userAgent) ? 'Chromium' : browser;
    browser = (/firefox|fxios/i).test(userAgent) && !(/seamonkey/i).test(userAgent) ? 'Firefox' : browser;
    browser = (/; msie|trident/i).test(userAgent) && !(/ucbrowser/i).test(userAgent) ? 'IE' : browser;
    browser = (/chrome|crios/i).test(userAgent) && !(/opr|opera|chromium|edg|ucbrowser|googlebot/i).test(userAgent) ? 'Chrome' : browser;;
    browser = (/safari/i).test(userAgent) && !(/chromium|edg|ucbrowser|chrome|crios|opr|opera|fxios|firefox/i).test(userAgent) ? 'Safari' : browser;
    browser = (/opr|opera/i).test(userAgent) ? 'Opera' : browser;

    // detect browser version
    switch (browser) {
        case 'UCBrowser': return `${browser}/${browserVersion(userAgent,/(ucbrowser)\/([\d\.]+)/i)}`;
        case 'Edge': return `${browser}/${browserVersion(userAgent,/(edge|edga|edgios|edg)\/([\d\.]+)/i)}`;
        case 'GoogleBot': return `${browser}/${browserVersion(userAgent,/(googlebot)\/([\d\.]+)/i)}`;
        case 'Chromium': return `${browser}/${browserVersion(userAgent,/(chromium)\/([\d\.]+)/i)}`;
        case 'Firefox': return `${browser}/${browserVersion(userAgent,/(firefox|fxios)\/([\d\.]+)/i)}`;
        case 'Chrome': return `${browser}/${browserVersion(userAgent,/(chrome|crios)\/([\d\.]+)/i)}`;
        case 'Safari': return `${browser}/${browserVersion(userAgent,/(safari)\/([\d\.]+)/i)}`;
        case 'Opera': return `${browser}/${browserVersion(userAgent,/(opera|opr)\/([\d\.]+)/i)}`;
        case 'IE': const version = browserVersion(userAgent,/(trident)\/([\d\.]+)/i);
            // IE version is mapped using trident version 
            // IE/8.0 = Trident/4.0, IE/9.0 = Trident/5.0
            return version ? `${browser}/${parseFloat(version) + 4.0}` : `${browser}/7.0`;
        default: return `unknown/0.0.0.0`;
    }
}

browserVersion = (userAgent,regex) => {
    return userAgent.match(regex) ? userAgent.match(regex)[2] : null;
}

console.log(getBrowser());
Ankit
  • 604
  • 6
  • 13
6

There is also a less "hacky" method which works for all popular browsers. Google has included a browser-check in their Closure Library. In particular, have a look at goog.userAgent and goog.userAgent.product. In this way, you are also up to date if something changes in the way the browsers present themselves (given that you always run the latest version of the closure compiler.)

Albert
  • 163
  • 1
  • 7
  • Most of the answers here are not concerned with being "hacky" if they are the only reliable method. userAgent, as noted multiple times, is easily spoofed, and is therefore, unreliable. – HoldOffHunger Oct 26 '17 at 19:43
6

UAParser is one of the JavaScript Library to identify browser, engine, OS, CPU, and device type/model from userAgent string.

There's an CDN available. Here, I have included a example code to detect browser using UAParser.

<!doctype html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/ua-parser-js@0/dist/ua-parser.min.js"></script>
<script type="text/javascript">
    var parser = new UAParser();
    var result = parser.getResult();
    console.log(result.browser);     // {name: "Chromium", version: "15.0.874.106"}
</script>
</head>
<body>
</body>
</html>

Now you can use the value of result.browser to conditionally program your page.

Source Tutorial: How to detect browser, engine, OS, CPU, and device using JavaScript?

Luzan Baral
  • 3,678
  • 5
  • 37
  • 68
  • 4
    a [thousand](https://github.com/faisalman/ua-parser-js/blob/master/src/ua-parser.js) lines of code you call lightweight? – deathangel908 Jun 25 '18 at 15:44
4

You can use Detect-browser.js, JavaScript library that detects and prints an object of browser information including browser language/name, user agent, device type, user OS, referer, online/0ffline, user timezone, screen resolution, and cookie enabled.

Get it from here detect-browser.js

it will give you something like that:

enter image description here

Malki Mohamed
  • 1,578
  • 2
  • 23
  • 40
  • This is definitely the best solution, as all other approaches are not actively maintained in the ever-changing world of browsers. – Abel Wenning Oct 25 '22 at 17:40
4

Here is my customized solution.

        const inBrowser = typeof window !== 'undefined'
        const UA = inBrowser && window.navigator.userAgent.toLowerCase()
        const isIE =
          UA && /; msie|trident/i.test(UA) && !/ucbrowser/i.test(UA).test(UA)
        const isEdge = UA && /edg/i.test(UA)
        const isAndroid = UA && UA.indexOf('android') > 0
        const isIOS = UA && /iphone|ipad|ipod|ios/i.test(UA)
        const isChrome =
          UA &&
          /chrome|crios/i.test(UA) &&
          !/opr|opera|chromium|edg|ucbrowser|googlebot/i.test(UA)
        const isGoogleBot = UA && /googlebot/i.test(UA)
        const isChromium = UA && /chromium/i.test(UA)
        const isUcBrowser = UA && /ucbrowser/i.test(UA)
        const isSafari =
          UA &&
          /safari/i.test(UA) &&
          !/chromium|edg|ucbrowser|chrome|crios|opr|opera|fxios|firefox/i.test(UA)
        const isFirefox = UA && /firefox|fxios/i.test(UA) && !/seamonkey/i.test(UA)
        const isOpera = UA && /opr|opera/i.test(UA)
        const isMobile =
          /\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(UA) ||
          /\b(Android|Windows Phone|iPad|iPod)\b/i.test(UA)
        const isSamsung = UA && /samsungbrowser/i.test(UA)
        const isIPad = UA && /ipad/.test(UA)
        const isIPhone = UA && /iphone/.test(UA)
        const isIPod = UA && /ipod/.test(UA)
    
        console.log({
          UA,
          isAndroid,
          isChrome,
          isChromium,
          isEdge,
          isFirefox,
          isGoogleBot,
          isIE,
          isMobile,
          isIOS,
          isIPad,
          isIPhone,
          isIPod,
          isOpera,
          isSafari,
          isSamsung,
          isUcBrowser,
        }
      }
Henrique Van Klaveren
  • 1,502
  • 14
  • 24
3

Chrome & Edge introduced a new User-Agent Client Hints API for this:

navigator.userAgentData.brands.map(item => item.brand).includes('Google Chrome')

Firefox & Safari don't support it yet unfortunately.

Ollie Williams
  • 1,996
  • 3
  • 25
  • 41
2
var BrowserDetect = {
        init: function () {
            this.browser = this.searchString(this.dataBrowser) || "Other";
            this.version = this.searchVersion(navigator.userAgent) || this.searchVersion(navigator.appVersion) || "Unknown";
        },
        searchString: function (data) {
            for (var i = 0; i < data.length; i++) {
                var dataString = data[i].string;
                this.versionSearchString = data[i].subString;

                if (dataString.indexOf(data[i].subString) !== -1) {
                    return data[i].identity;
                }
            }
        },
        searchVersion: function (dataString) {
            var index = dataString.indexOf(this.versionSearchString);
            if (index === -1) {
                return;
            }

            var rv = dataString.indexOf("rv:");
            if (this.versionSearchString === "Trident" && rv !== -1) {
                return parseFloat(dataString.substring(rv + 3));
            } else {
                return parseFloat(dataString.substring(index + this.versionSearchString.length + 1));
            }
        },

        dataBrowser: [
            {string: navigator.userAgent, subString: "Edge", identity: "MS Edge"},
            {string: navigator.userAgent, subString: "MSIE", identity: "Explorer"},
            {string: navigator.userAgent, subString: "Trident", identity: "Explorer"},
            {string: navigator.userAgent, subString: "Firefox", identity: "Firefox"},
            {string: navigator.userAgent, subString: "Opera", identity: "Opera"},  
            {string: navigator.userAgent, subString: "OPR", identity: "Opera"},  

            {string: navigator.userAgent, subString: "Chrome", identity: "Chrome"}, 
            {string: navigator.userAgent, subString: "Safari", identity: "Safari"}       
        ]
    };

    BrowserDetect.init();


    var bv= BrowserDetect.browser;
    if( bv == "Chrome"){
        $("body").addClass("chrome");
    }
    else if(bv == "MS Edge"){
     $("body").addClass("edge");
    }
    else if(bv == "Explorer"){
     $("body").addClass("ie");
    }
    else if(bv == "Firefox"){
     $("body").addClass("Firefox");
    }


$(".relative").click(function(){
$(".oc").toggle('slide', { direction: 'left', mode: 'show' }, 500);
$(".oc1").css({
   'width' : '100%',
   'margin-left' : '0px',
   });
});
neel upadhyay
  • 344
  • 2
  • 10
1

To check for IE browser using following code.

console.log(/MSIE|Trident/.test(window.navigator.userAgent))

OR

var isIE = !!document.documentMode; 

console.log(isIE)

Thanks

Rahul Daksh
  • 212
  • 1
  • 7
1

This method is currently valid for detecting all browsers. I quoted the vue-element-admin template

 export function fnBrowserDetect() {
      var browserName = (function(agent) {
        switch (true) {
          case agent.indexOf('edge') > -1: return 'MS Edge'
          case agent.indexOf('edg/') > -1: return 'Edge (chromium based)'
          case agent.indexOf('opr') > -1 && !!window.opr: return 'Opera'
          case agent.indexOf('chrome') > -1 && !!window.chrome: return 'Chrome'
          case agent.indexOf('trident') > -1: return 'MS IE'
          case agent.indexOf('firefox') > -1: return 'Mozilla Firefox'
          case agent.indexOf('safari') > -1: return 'Safari'
          default: return 'other'
        }
      })(window.navigator.userAgent.toLowerCase())
      return browserName.toLowerCase()
    }
M.skr
  • 98
  • 2
  • 9
  • I have so many questions for this code... Why switch(true)?! – SimonC Jan 24 '23 at 14:20
  • @SimonC I'm thinking the reason behind `switch(true)` is to avoid writing a while loop of any kind My question though is what is `window.opr` or `window.chrome`?? They aren't properties of the window class from all that I've read. ref: https://developer.mozilla.org/en-US/docs/Web/API/Window – Carlo Nyte Jul 30 '23 at 16:42
  • 1
    @CarloNyte window.chrome seems to be a Chrome extension and not something defined in the standard. I would be slightly worried if Google did a Microsoft and defined itself as the standard - and got away with it – SimonC Jul 31 '23 at 08:22
0

This combines both Rob's original answer and Pilau's update for 2016

    var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
    // Opera 8.0+ (UA detection to detect Blink/v8-powered Opera)
var isFirefox = typeof InstallTrigger !== 'undefined';   // Firefox 1.0+
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
    // At least Safari 3+: "[object HTMLElementConstructor]"
var isChrome = !!window.chrome && !isOpera;              // Chrome 1+
var isIE = /*@cc_on!@*/false || !!document.documentMode;
// Edge 20+
var isEdge = !isIE && !!window.StyleMedia;
// Chrome 1+
var output = 'Detecting browsers by ducktyping:<hr>';
output += 'isFirefox: ' + isFirefox + '<br>';
output += 'isChrome: ' + isChrome + '<br>';
output += 'isSafari: ' + isSafari + '<br>';
output += 'isOpera: ' + isOpera + '<br>';
output += 'isIE: ' + isIE + '<br>';
output += 'isIE Edge: ' + isEdge + '<br>';
document.body.innerHTML = output;
Joe Borg
  • 65
  • 2
  • 12
  • Is there a point to telling the user what browser they're using? I imagine they'd already know this. – HoldOffHunger Oct 26 '17 at 19:56
  • 1
    @HoldOffHunger it's main intention was more to adapt the most compatible code to the active browser, rather than to inform the user which browser they're using. Unless the browser they're using is super outdated and has been excluded from backwars compatibility, in which it wouldn't hurt to let the user know they can benefit from a better experience should they switch to something more up to date – Joe Borg Nov 02 '17 at 06:16
0

Here you find out which browser is it running.

function isValidBrowser(navigator){

            var isChrome =  navigator.indexOf('chrome'),
            isFireFox= navigator.indexOf('firefox'),
            isIE = navigator.indexOf('trident') ,
            isValidChromeVer = parseInt(navigator.substring(isChrome+7, isChrome+8)) >= 4,
            isValidFireForVer = parseInt(navigator.substring(isFireFox+8, isFireFox+9)) >= 3,
            isValidIEVer = parseInt(navigator.substring(isIE+8, isIE+9)) >= 7;

            if((isChrome > -1 && isValidChromeVer){ console.log("Chrome Browser")}

            if(isFireFox > -1 && isValidFireForVer){ console.log("FireFox  Browser")}

            if(isIE > -1 && isValidIEVer)){ console.log("IE Browser")}


        }
Ajay Kumar
  • 4,864
  • 1
  • 41
  • 44
0

We can use below util methods

utils.isIE = function () {
        var ver = navigator.userAgent;
        return ver.indexOf("MSIE") !== -1 || ver.indexOf("Trident") !== -1; // need to check for Trident for IE11
    };

    utils.isIE32 = function () {
        return (utils.isIE() && navigator.appVersion.indexOf('Win64') === -1);
    };

    utils.isChrome = function () {
        return (window.chrome);
    };

    utils.isFF64 = function () {
        var agent = navigator.userAgent;
        return (agent.indexOf('Win64') >= 0 && agent.indexOf('Firefox') >= 0);
    };

    utils.isFirefox = function () {
        return (navigator.userAgent.toLowerCase().indexOf('firefox') > -1);
    };
NPE
  • 429
  • 2
  • 16
0
const isChrome = /Chrome/.test(navigator.userAgent)
const isFirefox = /Firefox/.test(navigator.userAgent)
Landaida
  • 134
  • 2
  • 8
  • 2
    Unfortunately, it's not a good answer. Edge has Chrome in his userAgent message. It's better to use !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime); – Przemo Apr 18 '20 at 13:49
  • your answer also fail for Opera browser – Landaida Oct 08 '20 at 16:41
0

You can detect it like:

if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) {
   alert('Firefox');
}
CodeWhisperer
  • 1,143
  • 2
  • 19
  • 39
0
import getAgent, { getAccurateAgent } from "@egjs/agent";

const agent = getAgent();
getAccurateAgent().then((accurate_agent)=>{
    console.log(agent,'accurate.');
})
console.log(agent);

https://github.com/naver/egjs-agent

JaeIL Ryu
  • 159
  • 10
0

var BrowserType;
(function (BrowserType) {
    BrowserType["OPERA"] = "Opera";
    BrowserType["OPERA2"] = "OPR";
    BrowserType["EDGE"] = "Edg";
    BrowserType["CHROME"] = "Chrome";
    BrowserType["SAFARI"] = "Safari";
    BrowserType["FIREFOX"] = "Firefox";
    BrowserType["UNKNOWN"] = "unknown";
})(BrowserType || (BrowserType = {}));
const detectBrowser = () => {
    return Object.values(BrowserType).find((browser) => navigator.userAgent.indexOf(browser) != -1);
};
console.log(detectBrowser());
-1

Simple:

var OSName="Unknown OS";
if (navigator.appVersion.indexOf("Win")!=-1) OSName="Windows";
if (navigator.appVersion.indexOf("Mac")!=-1) OSName="MacOS";
if (navigator.appVersion.indexOf("X11")!=-1) OSName="UNIX";
if (navigator.appVersion.indexOf("Linux")!=-1) OSName="Linux";
if (navigator.appVersion.indexOf("Linux x86_64")!=-1) OSName="Ubuntu";

var nVer = navigator.appVersion;
var nAgt = navigator.userAgent;
var browserName  = navigator.appName;
var fullVersion  = ''+parseFloat(navigator.appVersion); 
var majorVersion = parseInt(navigator.appVersion,10);
var nameOffset,verOffset,ix;

// In Opera, the true version is after "Opera" or after "Version"
if ((verOffset=nAgt.indexOf("Opera"))!=-1) {
 browserName = "Opera";
 fullVersion = nAgt.substring(verOffset+6);
 if ((verOffset=nAgt.indexOf("Version"))!=-1) 
   fullVersion = nAgt.substring(verOffset+8);
}
// In MSIE, the true version is after "MSIE" in userAgent
else if ((verOffset=nAgt.indexOf("MSIE"))!=-1) {
 browserName = "Microsoft Internet Explorer";
 fullVersion = nAgt.substring(verOffset+5);
}
// In Chrome, the true version is after "Chrome" 
else if ((verOffset=nAgt.indexOf("Chrome"))!=-1) {
 browserName = "Chrome";
 fullVersion = nAgt.substring(verOffset+7);
}
// In Safari, the true version is after "Safari" or after "Version" 
else if ((verOffset=nAgt.indexOf("Safari"))!=-1) {
 browserName = "Safari";
 fullVersion = nAgt.substring(verOffset+7);
 if ((verOffset=nAgt.indexOf("Version"))!=-1) 
   fullVersion = nAgt.substring(verOffset+8);
}
// In Firefox, the true version is after "Firefox" 
else if ((verOffset=nAgt.indexOf("Firefox"))!=-1) {
 browserName = "Firefox";
 fullVersion = nAgt.substring(verOffset+8);
}
// In most other browsers, "name/version" is at the end of userAgent 
else if ( (nameOffset=nAgt.lastIndexOf(' ')+1) < 
          (verOffset=nAgt.lastIndexOf('/')) ) 
{
 browserName = nAgt.substring(nameOffset,verOffset);
 fullVersion = nAgt.substring(verOffset+1);
 if (browserName.toLowerCase()==browserName.toUpperCase()) {
  browserName = navigator.appName;
 }
}
// trim the fullVersion string at semicolon/space if present
if ((ix=fullVersion.indexOf(";"))!=-1)
   fullVersion=fullVersion.substring(0,ix);
if ((ix=fullVersion.indexOf(" "))!=-1)
   fullVersion=fullVersion.substring(0,ix);

majorVersion = parseInt(''+fullVersion,10);
if (isNaN(majorVersion)) {
 fullVersion  = ''+parseFloat(navigator.appVersion); 
 majorVersion = parseInt(navigator.appVersion,10);
}

document.write(''
 +'Hey! i see you\'re using '+browserName+'! <br>'
 +'The full version of it is '+fullVersion+'. <br>'
 +'Your major version is '+majorVersion+', <br>'
 +'And your "navigator.appName" is '+navigator.appName+'. <br>'
 +'Your "navigator.userAgent" is '+navigator.userAgent+'. <br>'
)

document.write('And, your OS is '+OSName+'. <br>');
Alon
  • 191
  • 2
  • 9
-3

Simple, single line of JavaScript code will give you the name of browser:

function GetBrowser()
{
    return  navigator ? navigator.userAgent.toLowerCase() : "other";
}
HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Nirav Mehta
  • 6,943
  • 9
  • 42
  • 51
  • 18
    The userAgent alone doesn't tell us enough. For example, my user agent is "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36", which mentions Mozilla, Chrome and Safari. Which browser type am I? – eremzeit Sep 11 '15 at 22:39
  • Sorry but I didn't get you for "Which browser type am I?" what you want to get? – Nirav Mehta Sep 12 '15 at 04:56
  • 1
    @NiravMehta What he meant is that `navigator.userAgent` tells you every browser possible you have.. So this is really not reliable, the only case it would work is if the user only has one browser. – Baldráni Mar 08 '16 at 09:41
  • 1
    this is not a reliable way to detect browser. Some useragents includes both chrome and safari, so there is not way to detect which one should we consider and last but, not the least, useragent can be modified by the web page. – Juvenik Jun 27 '17 at 05:40