124

Though both are Webkit based browsers, Safari urlencodes quotation marks in the URL while Chrome does not.

Therefore I need to distinguish between these two in JS.

jQuery's browser detection docs mark "safari" as deprecated.

Is there a better method or do I just stick with the deprecated value for now?

2
  • I don't know if sticking with it is such a good idea, I haven't checked this out in depth, although I just browsed to the $.browser docs on chrome and it flags $.browser.safari === true. eeek.
    – davin
    Commented May 5, 2011 at 15:03
  • 1
    possible duplicate of How to detect Safari, Chrome, IE, Firefox and Opera browser without user agent sniffing?.
    – Rob W
    Commented May 25, 2012 at 10:44

14 Answers 14

355

Using a mix of feature detection and Useragent string:

    var is_opera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
    var is_Edge = navigator.userAgent.indexOf("Edge") > -1;
    var is_chrome = !!window.chrome && !is_opera && !is_Edge;
    var is_explorer= typeof document !== 'undefined' && !!document.documentMode && !is_Edge;
    var is_firefox = typeof window.InstallTrigger !== 'undefined';
    var is_safari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);

Usage:
if (is_safari) alert('Safari');

Or for Safari only, use this :

if ( /^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {alert('Its Safari');}
13
  • 3
    With a ratio of 48 votes vs. 5 votes for a feature detection with side effects, apparently this is the recommended solution. :) Making it accepted answer.
    – AndreKR
    Commented Sep 5, 2013 at 16:08
  • 1
    As an example of just how fragile this sort of thing is, this code does not detect Internet Explorer 11 because the UA string has changed. See msdn.microsoft.com/en-us/library/ie/hh869301%28v=vs.85%29.aspx Commented Mar 19, 2014 at 10:16
  • 1
    Android webview will also say Safari and that's not correct
    – Curtis
    Commented Jun 16, 2014 at 23:39
  • 15
    Chrome/Windows will report as Safari: (Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36)
    – Blaise
    Commented Jul 20, 2014 at 20:00
  • 6
    is_explorer = (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0) to also support IE11 >>> stackoverflow.com/a/22242528/2049986 Commented Aug 20, 2014 at 12:01
79

The following identifies Safari 3.0+ and distinguishes it from Chrome:

isSafari = !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/)
1
  • 1
    This is the thing. TNX!
    – EugenSunic
    Commented Jun 21, 2016 at 17:32
10

unfortunately the above examples will also detect android's default browser as Safari, which it is not. I used navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1 && navigator.userAgent.indexOf('Android') == -1

7

For checking Safari I used this:

$.browser.safari = ($.browser.webkit && !(/chrome/.test(navigator.userAgent.toLowerCase())));
if ($.browser.safari) {
    alert('this is safari');
}

It works correctly.

0
3

Apparently the only reliable and accepted solution would be to do feature detection like this:

browser_treats_urls_like_safari_does = false;
var last_location_hash = location.hash;
location.hash = '"blah"';
if (location.hash == '#%22blah%22')
    browser_treats_urls_like_safari_does = true;
location.hash = last_location_hash;
2
  • 2
    Nice trick, but unfortunately it doesn't work. The equality (location.hash == '#%22blah%22') will not work because of the way location.hash treats the string. :/ Commented Oct 14, 2011 at 12:45
  • 1
    Feature detection is the way to go, but there's a better method which does not have any side effects. Your snippet may interfere with other scripts which rely on hash change events. I've marked the question as a duplicate of this. I've created and tested the method in Safari 3.0 - 5.1.3 (Mac and Windows). It's a one-liner :)
    – Rob W
    Commented May 25, 2012 at 10:42
2

The only way I found is check if navigator.userAgent contains iPhone or iPad word

if (navigator.userAgent.toLowerCase().match(/(ipad|iphone)/)) {
    //is safari
}
1

If you are checking the browser use $.browser. But if you are checking feature support (recommended) then use $.support.

You should NOT use $.browser to enable/disable features on the page. Reason being its not dependable and generally just not recommended.

If you need feature support then I recommend modernizr.

9
  • Teach a man to fish... "Is there a better method" - Yes, feature detection. Commented May 5, 2011 at 22:03
  • You mean something like location.hash = '"blah"'; if (location.hash == '#%22blah%22') alert('is Safari');?
    – AndreKR
    Commented May 6, 2011 at 12:26
  • @AndreKR Exactly, I'd make a function to specifically test for the feature you are checking for. Commented May 6, 2011 at 14:19
  • 2
    @Greg You aren't asking the browser.. you are testing the browser. Commented Jun 16, 2011 at 13:10
  • 12
    Feature detection is great, but what about when you want to stop a particular browser from using CSS Animations (for example), because it has a buggy implementation? It technically supports the feature, but we want to take a decision to disable it for that browser, because the experience is better without in that instance. Commented Jun 30, 2011 at 15:09
1
//Check if Safari
  function isSafari() {
      return /^((?!chrome).)*safari/i.test(navigator.userAgent);
  }
//Check if MAC
     if(navigator.userAgent.indexOf('Mac')>1){
        alert(isSafari());
     }

http://jsfiddle.net/s1o943gb/10/

1

This will determine whether the browser is Safari or not.

if(navigator.userAgent.indexOf('Safari') !=-1 && navigator.userAgent.indexOf('Chrome') == -1)
{
    alert(its safari);
}else {
    alert('its not safari');
}
1
  • Doesn't work, unfortunately. Tested on Chrome v66 and Safari. Commented Jan 23, 2018 at 20:14
1

I use to detect Apple browser engine, this simple JavaScript condition:

 navigator.vendor.startsWith('Apple')
1
  • 1
    This is the only perfectly working solution :) Commented Aug 30, 2021 at 9:38
0

A very useful way to fix this is to detect the browsers webkit version and check if it is at least the one we need, else do something else.

Using jQuery it goes like this:

"use strict";

$(document).ready(function() {
    var appVersion                  = navigator.appVersion;
    var webkitVersion_positionStart = appVersion.indexOf("AppleWebKit/") + 12;
    var webkitVersion_positionEnd   = webkitVersion_positionStart + 3;
    var webkitVersion               = appVersion.slice(webkitVersion_positionStart, webkitVersion_positionEnd);
	
    console.log(webkitVersion);

    if (webkitVersion < 537) {
        console.log("webkit outdated.");
    } else {
        console.log("webkit ok.");
    };
});

This provides a safe and permanent fix for dealing with problems with browser's different webkit implementations.

Happy coding!

0
    // Safari uses pre-calculated pixels, so use this feature to detect Safari
    var canva = document.createElement('canvas');
    var ctx = canva.getContext("2d");
    var img = ctx.getImageData(0, 0, 1, 1);
    var pix = img.data;     // byte array, rgba
    var isSafari = (pix[3] != 0);   // alpha in Safari is not zero
0
0

Generic FUNCTION

 var getBrowseActive = function (browserName) {
   return navigator.userAgent.indexOf(browserName) > -1;
 };
0

My best solution

function getBrowserInfo() {
  const ua = navigator.userAgent; let tem;
  let M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
  if (/trident/i.test(M[1])) {
    tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
    return { name: 'IE ', version: (tem[1] || '') };
  }
  if (M[1] === 'Chrome') {
    tem = ua.match(/\bOPR\/(\d+)/);
    if (tem != null) {
      return { name: 'Opera', version: tem[1] };
    }
  }
  M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
  tem = ua.match(/version\/(\d+)/i);
  if (tem != null) {
    M.splice(1, 1, tem[1]);
  }
  return {
    name: M[0],
    version: M[1],
  };
}

getBrowserInfo();
1
  • Welcome. Thanks for contributing. Code only responses are discouraged as low quality on SO. Please consider editing to add an explanation how/why this solves the OP's issue, and even additional supporting links to documentation. Note that most upvotes come from quality answers over time, as various users learn something from your post to apply to their own coding issues. More info is available in the SO help center(StackOverflow.com/help) Commented Dec 22, 2020 at 22:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.