21

I know there are a thousand questions on Stack Overflow about detecting the browser with JavaScript. My question is how can you detect the browser without window.navigator (which includes navigator.userAgent)?

First, to clarify, I don't need to know the rendering engine, this isn't for adaptive layout, and don't panic: I'm already doing feature detection. If why I'm asking about detecting the browser is important, please comment and I'll be happy to splice in the explanation, but it will probably make the question egregiously long.

Next, let me describe why my question is not a duplicate of:

  • Browser detection in Javascript? because of 19 answers, 12 of them use navigator.userAgent specifically (including jQuery.browser which used userAgent, and is now gone anyway), 4 use navigator.appName (which gives "Netscape" in Chrome...), 1 side-steps the question by recommending feature detection, which is different from browser detection (I am already using feature detection, but to know the extent to which I can use them, I need browser detection), and 2 aren't really answers or are IE-specific. (Although this non-answer is actually very explanatory about why my question here is relevant: I'm trying to avoid hitting pain points on certain browsers that would crash the tab!) Since my question is asking for an answer (even a hack?) without using window.navigator, it is not a duplicate of that question.

  • Check if the user is using IE because of 11 answers, 10 use navigator.userAgent and 1 of them uses an IE trick to detect IE only, which is not sufficient to answer my question (though it may be potentially be a small part of a helpful solution posted here)?

  • In Javascript, how do I determine if my current browser is Firefox on a computer vs everything else? because of 11 answers, 8 use navigator.userAgent, 2 recommend feature detection (again, not my question), and 1 isn't even an answer, really.

  • How to detect chrome and safari browser (webkit) because of 8 answers, 6 of them use navigator.userAgent, and 2 are webkit-specific. Unfortunately, WebKit is not necessarily tied to just Safari, and I need to know the browser, not the rendering engine.

Hopefully that is crystal clear.

I know there are other ways to do this, but I don't know the ins-and-outs of each browser well enough. Are there objects or variables that are consistently or reliably exposed to JavaScript in certain browsers, maybe? I know that some experimental APIs are vendor-prefixed, but that doesn't seem like a good idea for use in a commercial product, although I'm willing to stoop that low if needed. Any other possibilities?

Community
  • 1
  • 1
Matt
  • 22,721
  • 17
  • 71
  • 112
  • 5
    This is a duplicate of a million other more specific questions such as http://stackoverflow.com/questions/12625876/how-to-detect-chrome-and-safari-browser-webkit and http://stackoverflow.com/questions/2324944/in-javascript-how-do-i-determine-if-my-current-browser-is-firefox-on-a-computer and http://stackoverflow.com/questions/19999388/jquery-check-if-user-is-using-ie and http://stackoverflow.com/questions/2400935/browser-detection-in-javascript – user229044 Nov 23 '14 at 00:12
  • @meager All those solutions check the User Agent string or do feature detection. Both are not options with my question. – Matt Nov 23 '14 at 00:13
  • 7
    @meager Did you even read my question? In what ways OTHER than the user-agent can the browser type bet detected? Please re-open the question. – Matt Nov 23 '14 at 00:15
  • 3
    All of those questions have non-UA answers. – user229044 Nov 23 '14 at 00:17
  • The http://stackoverflow.com/questions/2400935/browser-detection-in-javascript answers specifically are pretty much what you are looking for. – D.Shawley Nov 23 '14 at 00:18
  • 4
    ... window.navigator effectively counts as a user-agent string -- I'm trying to avoid that here. – Matt Nov 23 '14 at 00:18
  • 2
    So why not just run some sample JavaScript to, you know, actually estimate performance rather than just providing a predefined estimate. Your proposed approach will probably not stand the test of time. That says nothing of the differences between browser versions you would be ignoring as well: Firefox ESR releases, Chrome Stable/Canary, browsers you don't account for like Midori and script engines that aren't browsers at all like nodejs/V8. – Goyuix Nov 23 '14 at 05:19
  • @Goyuix That's not the question. The backstory is somewhat complicated. Stop trying to solve the wrong problem, and let's open this up to sharing intelligence: how does one detect the browser without using User Agent or window.navigator? Show me the duplicate question. – Matt Nov 23 '14 at 06:58
  • the reason that people continually try to flag this as duplicate to the hundreds of other questions on this site regarding browser detection is because there is no standard by which browser manufacturers must abide, and so you will always be limited to methods which attempt to "Guess", based on whatever information the browser manufacturer wants to supply or not. There **is not** a way around the fact that this is not compulsory information from the browser manufacturers. – Claies Nov 24 '14 at 01:22
  • @AndrewCounts Even if that's true, the claim of "duplicate question" doesn't follow from that reasoning. Duplicate question means that the question already has answers in another question. So far, no such questions have surfaced. – Matt Nov 24 '14 at 01:26
  • @AndrewCounts As for finding a solution, I'm not opposed to guessing, since I know that there must be some objects or values exposed in some browsers but not others. Even if the answer relies on some hacks, that's okay, as I'm still investigating this myself too, and may just end up using some "guessing" logic. But it would be nice to have a brief explanation rather than me just flying blind with what I can see from the console's autocomplete, or some incomplete docs, ya know? – Matt Nov 24 '14 at 01:27
  • If you read the Living Document on HTML Standard at https://html.spec.whatwg.org/multipage/webappapis.html#dom-navigator-useragent, they are very clear. User Agent is optional, browsers don't have to honor it, and in fact are encouraged to provide as little info as possible. If you want a reliable way to detect browsers that doesn't use the user-agent, it would take a change in the HTML standard. – Claies Nov 24 '14 at 01:29
  • @AndrewCounts I understand that I'll have to tolerate less than ideal. I'm more than willing to accept the *most* reliable answer instead. – Matt Nov 24 '14 at 01:33
  • I wish you lots of luck with your research, and I understand how frustrating it is. I'm just not sure that this is going to be the right community for finding the kind of hacks you are looking for, hiding from the HTML standards docs. – Claies Nov 24 '14 at 01:36
  • Safari: `var a; for (var i in window) if (i.toLowerCase().indexOf('webkit') != -1) a = true; return a && !window.chrome` (assuming no other browsers besides chrome and safari are webkit) – bjb568 Dec 16 '14 at 02:18
  • I don't need to know why you need to detect the browser (there are lots of use cases), but I would want to know *why you want to avoid `window.navigator`*? – Bergi Dec 16 '14 at 02:45
  • @Bergi In part, because IE is going to start pretending to be all the other browsers, rendering it effectively useless: http://msdn.microsoft.com/en-us/library/ie/hh869301(v=vs.85).aspx – Matt Dec 16 '14 at 16:16

2 Answers2

8

A thought:

  • IE uses ActiveX (still does up to IE11, legacy), You can fairly easy deduce the fact that the user is using IE from looking at activeX availability, however if the security settings are on, you need to fall back on, guess what, other feature detection.
  • Chrome and Firefox both support the use of extensions, maybe detecting these extensions will help
  • Chrome has the window['chrome']['webstore'] object available in the global scope.
  • You can sort through the window object with Object.keys and look for vendor specific names like 'moz' or 'ms' or 'o'.

If you combine moz, ms and chrome-object you can sniff out the three largest browsers.

On a side note, feature detection is still the best option, not for the OP, but for the "I'm-just-getting-into-programming-and-I-like-to-know-how-I-sniff-out-a-browser-programmers" out there.

Mouser
  • 13,132
  • 3
  • 28
  • 54
  • 2
    Yes! These are the kind of hacks I'm looking for! Thank you. I will experiment with these ideas. – Matt Dec 16 '14 at 16:22
6

First off, just to be clear no inbound HTTP request is guaranteed to be accurate in saying who they are. In fact this is how some hackers operate by faking out the User-Agent field of the HTTP header. Most browser providers; however, do a good job of identifying who they are by saying so in the User-agent field of the inbound HTTP request header. The only problem working at the Javascript layer is that it is one layer too high for seeing the headers. However there are tricks and here's one of them :

var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
alert(headers);

I found this after thinking about the problem a bit and knowing the Network side pretty well... You can read more about this here: Accessing the web page's HTTP Headers in JavaScript, in fact this question could be considered a duplicate of that answer, however, not everyone knows the HTTP layer. The code above is pretending to be a legitimate inbound request, and opens the document.location using a "Get", but it sends nothing. Without knowing the browser internals I am guessing that it is the DOM itself that is returning the already known header information. Just parse the User-Agent portion of he response and you are all set.

Community
  • 1
  • 1
JWP
  • 6,672
  • 3
  • 50
  • 74
  • 2
    You're right, User-Agent is not a reliable way to detect the browser; it's one reason why I want to avoid it. (See http://msdn.microsoft.com/en-us/library/ie/hh869301(v=vs.85).aspx) Props for a really clever solution though -- I'd have never thought of that! – Matt Dec 16 '14 at 16:19
  • Thanks for posting the link I had seen the "Edge" stuff but had no idea what it was (until now). Good luck in your hunt for a solution. – JWP Dec 16 '14 at 16:35