Detect Safari using jQuery

184,060

Solution 1

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');}

Solution 2

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

isSafari = !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/)

Solution 3

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

Solution 4

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.

Solution 5

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;
Share:
184,060
AndreKR
Author by

AndreKR

Updated on December 23, 2020

Comments

  • AndreKR
    AndreKR over 3 years

    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?

  • John Strickler
    John Strickler about 13 years
    Teach a man to fish... "Is there a better method" - Yes, feature detection.
  • AndreKR
    AndreKR about 13 years
    You mean something like location.hash = '"blah"'; if (location.hash == '#%22blah%22') alert('is Safari');?
  • John Strickler
    John Strickler about 13 years
    @AndreKR Exactly, I'd make a function to specifically test for the feature you are checking for.
  • Greg Flynn
    Greg Flynn about 13 years
    feature detection isn't reliable either since some browsers default to "yes I support X" when really they don't
  • John Strickler
    John Strickler about 13 years
    @Greg You aren't asking the browser.. you are testing the browser.
  • John Strickler
    John Strickler about 13 years
    $.browser is already depreciated and may be moved out of the jQuery core soon. api.jquery.com/jQuery.browser read the description, the jQuery team prefers you use feature detection too.
  • Greg Flynn
    Greg Flynn about 13 years
    @John yea, you're right, I was thinking of something else, sorry!
  • Phil Ricketts
    Phil Ricketts almost 13 years
    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.
  • Panos Kalatzantonakis
    Panos Kalatzantonakis over 12 years
    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. :/
  • Rob W
    Rob W about 12 years
    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 :)
  • Chris
    Chris about 11 years
    @Replete +1 Another example is File Drag and Drop support detection and wanting to include Safari 5 on Windows. Commonly suggested method of using Modernizr.draganddrop && !!window.FileReader will return false, but Safari 5 on Windows DOES support drag and drop.
  • AndreKR
    AndreKR almost 11 years
    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.
  • Ben Cottrell
    Ben Cottrell over 10 years
    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.as‌​px
  • Curtis
    Curtis about 10 years
    Android webview will also say Safari and that's not correct
  • Blaise
    Blaise almost 10 years
    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)
  • Jacob van Lingen
    Jacob van Lingen almost 10 years
    is_explorer = (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0) to also support IE11 >>> stackoverflow.com/a/22242528/2049986
  • ibsenv
    ibsenv over 9 years
    Thanks..but I am not able to detect opera, var is_Opera = navigator.userAgent.indexOf("Presto") > -1; is giving false. But is_chrome is giving true. (opera 28)
  • Panos Kalatzantonakis
    Panos Kalatzantonakis over 9 years
    @ibsenv please check it now, I've updated the code to detect the newest version of Opera (v28). Thank you.
  • ShibinRagh
    ShibinRagh about 8 years
    except safari ? if (!is_safari) - is this right? i think its including chrome too
  • EugenSunic
    EugenSunic about 8 years
    This is the thing. TNX!
  • James Grey
    James Grey almost 8 years
    It works incorrect. function isSafari() { var isSafari = false; if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) { isSafari = true; } } isSafari(); if(isSafari){ alert("foo & bar"); }
  • Keith C
    Keith C over 7 years
    -1 from me; Chrome on my Mac right now has a user agent of "Mozilla/5.0 (iPad; CPU OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1" i.e. "Chrome" is not present.
  • Abhi
    Abhi over 6 years
    @PanosKal.Will it detects safari in Ipad as well?
  • Jonathan Arbely
    Jonathan Arbely over 6 years
    Doesn't work, unfortunately. Tested on Chrome v66 and Safari.
  • Nigel Fds
    Nigel Fds about 5 years
    also Edge shows isChrome true now ... so need to add below : !!window.chrome && !IsOpera() && !IsEdge();
  • ortonomy
    ortonomy about 5 years
    this doesn't work -- navigator.userAgent has been available in Safari since Safari 11
  • SherylHohman
    SherylHohman over 3 years
    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)
  • Saurabh Chauhan
    Saurabh Chauhan almost 3 years
    This is the only perfectly working solution :)