31

I found the following code to detect a desktop browser. But the method also detects some mobile browsers. How can I detect only desktop browsers like Safari, IE, Firefox, Opera etc?

is_desktopBrowser : function() {
    var ua = navigator.userAgent.toLowerCase();

    var rwebkit = /(webkit)[ \/]([\w.]+)/;
    var ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/;
    var rmsie = /(msie) ([\w.]+)/;
    var rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/;

    var match = rwebkit.exec(ua) ||
            ropera.exec(ua) ||
            rmsie.exec(ua) ||
            ua.indexOf("compatible") < 0 && rmozilla.exec(ua) ||
            [];

    return { browser: match[1] || "", version: match[2] || "0" };
},
dgvid
  • 25,555
  • 5
  • 39
  • 56
fabian
  • 5,323
  • 10
  • 59
  • 90

10 Answers10

30

jQuery.browser can be helpful when trying to figure out which browser. jQuery.browser was removed in jQuery 1.9.

I believe it is based on navigator.UserAgent, however navigator.UserAgent can tell you the OS on its own if you want.

Try this:

var isMobile = navigator.userAgent.match(/(iPad)|(iPhone)|(iPod)|(android)|(webOS)/i)

source

Jeffrey C
  • 344
  • 3
  • 13
sky-dev
  • 6,070
  • 2
  • 32
  • 32
  • 8
    `jQuery.browser` is deprecated in jQuery. Can't use it anymore. – tim Apr 22 '13 at 21:10
  • @DaanHeskes There's good reason for this, browser UA detecting that jQuery.browser is doing is a bad idea because years from now everyone that is using FirefoxOS, Ubuntuphone, blackberry/blueberryphone, MSEdgeTablet10.5, supernewphone1.0, or whatever other devices are popular, will not be detected. If you want to do something on smaller screen mobile devices, by all means do so... without detecting each possible OS individually! https://developer.mozilla.org/en-US/docs/Web/API/Screen – NoBugs Feb 12 '17 at 08:57
18

I check for

('ontouchstart' in window)

since that will tell me if I'm on a touch capable device. Of course that also returns true for an ipad, which might not be considered a "mobile device", but then I just check window.width for layout purposes.

tim
  • 3,625
  • 4
  • 32
  • 38
  • 23
    This approach returns false positive for touch-enabled desktops such as Microsoft's Surface and numerous other notebooks with Windows 8. – Andrew Sklyarevsky Mar 09 '15 at 13:34
  • 1
    I tried the same in the latest Chrome and according to this, my desktop Chrome is a mobile, so it's a no. – Lajos Mészáros May 26 '16 at 08:23
  • 2
    @LajosMeszaros It returns `false` under desktop Chrome on Windows. – adi518 Feb 21 '18 at 00:14
  • 1
    ('ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0) for touch-enabled desktops such as Microsoft's Surface and numerous other notebooks with Windows 8 – Zvi Redler Jan 29 '20 at 09:42
12

I came up with this:

    var isTouchDevice = function() {  return 'ontouchstart' in window || 'onmsgesturechange' in window; };
    var isDesktop = window.screenX != 0 && !isTouchDevice() ? true : false;

It leverages two things we can hold on to. One, window.screenX will ALWAYS be 0 on any tablet / mobile device. You can't move windows on these devices, it is always full screen.

Two, isTouchDevice is a pretty reliable way to know if it's mobile (android / iphone tablet) or Windows Surfacey thing. It has a touch event. Combining the two gives us a high degree of certainty that it's a mobile or tablet. If you're not one of those, you must be desktop.

Yes, you might have a desktop that somehow reports itself as touch and has the browser maxxed to the upper left. In my case, I can let that go.

httpete
  • 2,389
  • 20
  • 29
  • 1
    You should have window.screenX === 0 in the isTouchDevice check, rather than the other way around. window.screenX can be 0 on a desktop. – hexalys Jun 19 '13 at 04:24
  • Not a reliable option imo. There are laptops with touch screens. – Mark Knol Nov 08 '13 at 11:56
  • Mark this is true. But in some cases, it is close enough given the brevity of the code. There are cases where the outcome, although not ideal - is still usable for most and the code is compact enough to warrant value. – httpete Aug 02 '14 at 02:02
  • 1
    I thought I would add some input here as well (although an old answer). Some tablets will allow you to move windows, such as the Surface Pro. Just keep this in mind when coding your next project. – David Aug 20 '14 at 09:54
  • It's true David, and this code could be tweaked a bit to add detection for surface as an outlier. Most touch devices have no window movement, thus the screenX is a pretty good call. Depends on the use case. – httpete Sep 17 '15 at 14:13
  • 3
    `window.screenX != 0 && !isTouchDevice() ? true : false;` You can write this shorter as `window.screenX != 0 && !isTouchDevice();` – Janneman96 Mar 24 '17 at 13:59
7

I have been investigating this for my ReView (Responsive Viewport) project. I use a combination of the following.

  • window.screenX

Most mobile browsers have the 'window' locked to the left hand side. So if this isn't zero, likely to be a desktop browser window.

  • window.devicePixelRatio and screen.width

If dpr is 1 and screen width is reported as large via screen.width, likely to be desktop.

  • window.orientation

It is rare to find a desktop monitor in portrait mode. However, this could happen.

More unlikely is multiple orientation changes while using your site/app. This implies a desktop user would be spinning their screen... very unlikely.

A combination of these with some common sense and you can achieve a pretty solid guess.

The project mentioned along with more info is at http://responsiveviewport.com

Hope that helps.

Edward
  • 281
  • 4
  • 7
3

You can go to http://detectmobilebrowsers.com and generate a JS script which will detect whether a browser is a mobile browser. Unless you are worried about Smart TVs or some other non mobile nor desktop appliances, you can use that script and assume that if the browser is NOT a mobile browser then it should be a desktop browser.

Here is an example solution using the regex-es generated by that site:

var ua = navigator.userAgent.toLowerCase();
var isDesktop = !(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(ua.substr(0,4)));
Enigo
  • 3,351
  • 5
  • 29
  • 51
Dj.
  • 39
  • 1
2

Even it's a bit overkill for your case, express-useragent is one of the best solution as it can be used on both server and browser. Your case:

Include js file in HTML

<script type="text/javascript" src="/path/to/express-useragent.js"></script>

Execute the plugin

var userAgent = new UserAgent().parse(navigator.userAgent);

Value of userAgent will be something like

{
  "isMobile":false,
  "isDesktop":true,
  "isBot":false,
  .....
  "browser":"Chrome",
  "version":"17.0.963.79",
  "os":"Windows 7",
  "platform":"Microsoft Windows",
  "source":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.79..."
}
haotang
  • 5,302
  • 32
  • 43
1

Simply include Modernizr js file it adds the classes called no-touch to all desktop browsers so you can easily target using these classes

Simon Arnold
  • 15,214
  • 6
  • 63
  • 84
Shiva
  • 19
  • 1
1

Actually, it is easy to detect mobile or tablet device, then with a simple result inversion we can understand that is desktop or not, for easy accessing I write a simple function:

const isDesktop = () => {
  const navigatorAgent =
    navigator.userAgent || navigator.vendor || window.opera;
  return !(
    /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series([46])0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(
      navigatorAgent
    ) ||
    /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br([ev])w|bumb|bw-([nu])|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do([cp])o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly([-_])|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-([mpt])|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c([- _agpst])|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac([ \-/])|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja([tv])a|jbro|jemu|jigs|kddi|keji|kgt([ /])|klon|kpt |kwc-|kyo([ck])|le(no|xi)|lg( g|\/([klu])|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t([- ov])|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30([02])|n50([025])|n7(0([01])|10)|ne(([cm])-|on|tf|wf|wg|wt)|nok([6i])|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan([adt])|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c([-01])|47|mc|nd|ri)|sgh-|shar|sie([-m])|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel([im])|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c([- ])|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(
      navigatorAgent.substr(0, 4)
    )
  );
};

Note: this function is based on ES6 and it should transpile, best case for ReactJS.

AmerllicA
  • 23,670
  • 12
  • 111
  • 138
1

The problem with your script is, that it's just trying to detect the browser with the UserAgent-string which is not quite accurate because everyone can fake his UserAgent.

For a pretty good read on browser detection, check out this link: http://www.quirksmode.org/js/detect.html

Neq
  • 66
  • 3
0

As I said here, IE10+ solution just using matchMedia:

const isMobile = () => window.matchMedia('(max-width: 700px)').matches

isMobile() returns a boolean

const isMobile = () => window.matchMedia('(max-width: 700px)').matches
document.addEventListener('DOMContentLoaded', () => {
  setInterval(() => document.querySelector('.result').textContent = isMobile() ? 'yes but you should try this code in a bigger screen' : 'no', 300)
}, false);
.result {
  color: green;
  font-weight: bold;
}
Am I on mobile screen? <span class="result">something went wrong :/</span>
<p>
<div>Click in full page to see the difference</div>
insign
  • 4,453
  • 35
  • 30