Tomas
Tomas

Reputation: 18087

Detect Safari browser

How to detect Safari browser using JavaScript? I have tried code below and it detects not only Safari but also Chrome browser.

function IsSafari() {

  var is_safari = navigator.userAgent.toLowerCase().indexOf('safari/') > -1;
  return is_safari;

}

Upvotes: 262

Views: 366004

Answers (25)

stiweb
stiweb

Reputation: 41

This code is used to detect only safari browser

const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)

Upvotes: 0

Infigon
Infigon

Reputation: 662

Detect gesture change support, like this:

const isSafari = !!window.GestureEvent
document.write(isSafari ? "You are using Safari." : "You are not using Safari.")

Nice and simple; works for iOS and Android! If you need ES5 support, replace const with var.

Note that if people are using WKWebView for app development tailored to an Apple device, it may claim it is Safari, which is technically true, given that it uses Safari's web features in the background. Other solutions may be necessary, such as injecting additional code.

Upvotes: 15

leoledmag
leoledmag

Reputation: 136

Only Safari whitout Chrome:

After trying other's code I didn't find any that works with new and old versions of Safari.

Finally, I did this code that's working very well for me:

var ua = navigator.userAgent.toLowerCase(); 
var isSafari = false;
try {
  isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || safari.pushNotification);
}
catch(err) {}
isSafari = (isSafari || ((ua.indexOf('safari') != -1)&& (!(ua.indexOf('chrome')!= -1) && (ua.indexOf('version/')!= -1))));

//test
if (isSafari)
{
  //Code for Safari Browser (Desktop and Mobile)
  document.getElementById('idbody').innerHTML = "This is Safari!";
}
else
{
  document.getElementById('idbody').innerHTML = "This is not Safari!";
}
<body id="idbody"></body>

Upvotes: 7

Sheikh Wahaj
Sheikh Wahaj

Reputation: 141

2024 Version

  var ua = window.navigator.userAgent;
  var iOS = ua.match(/Macintosh/i) || ua.match(/iPad/i) || ua.match(/iPhone/i);
  var webkit = ua.match(/WebKit/i);
  var iOSSafari = iOS && webkit && !ua.match(/CriOS/i) && !ua.match(/EdgiOS/i) && !ua.match(/Chrome/i) && !ua.match(/Edg/i);

    if (iOSSafari) {
        //do stuff here
    }

Upvotes: 3

gael
gael

Reputation: 868

2023 edition

if(navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome')){
    // it's safari
    console.log('safari detected');
}

Upvotes: 3

lukyer
lukyer

Reputation: 7983

Just use:

var isSafari = window.safari !== undefined;
if (isSafari) console.log("Safari, yeah!");

Note this might not be reliable for mobile versions of Safari.

Upvotes: 132

Michael Rafailyk
Michael Rafailyk

Reputation: 462

Read many answers and posts and determined the most accurate solution. Tested in Safari, Chrome, Firefox & Opera (desktop and iOS versions). First we need to detect Apple vendor and then exclude Chrome, Firefox & Opera (for iOS).

let isSafari = navigator.vendor.match(/apple/i) &&
             !navigator.userAgent.match(/crios/i) &&
             !navigator.userAgent.match(/fxios/i) &&
             !navigator.userAgent.match(/Opera|OPT\//);

if (isSafari) {
  // Safari browser is used
} else {
  // Other browser is used
}

Upvotes: 23

user1201917
user1201917

Reputation: 1370

Based on @SudarP answer.

At Q3 2021 this solution will fail in either Firefox (Uncaught TypeError: navigator.vendor.match(...) is null) and Chrome (Uncaught TypeError: Cannot read properties of null (reading 'length'));

So here is a fixed and shorter solution:

function isSafari() {
  return (navigator.vendor.match(/apple/i) || "").length > 0
}

Upvotes: 1

David A. Gray
David A. Gray

Reputation: 1075

I tested the code posted by #Christopher Martin, and it reported my browser as Chrome, because it tests for that before testing for Edge, which would otherwise answer true to the test that is intended to identify Chrome. I amended his answer to correct that deficiency and two others, namely:

  1. The abbreviated user agent substring for Edge
  2. The very old string for MSIE

Converting the code into a function yields the following function and test script that reports via the debug console.

    <script type="text/javascript">
    function BasicBrowserSniffer ( )
    {
        if ( navigator.userAgent.match ( /edge\//i ) ) {
            return 'edge/edgehtml';
        }
        if ( navigator.userAgent.match ( /edg\//i ) ) {
            return 'edge/edgehtml';
        }
        else if ( navigator.vendor.match ( /google/i ) ) {
            return 'chrome/blink';
        }
        else if ( navigator.vendor.match ( /apple/i ) ) {
            return 'safari/webkit';
        }
        else if ( navigator.userAgent.match ( /firefox\//i ) ) {
            return 'firefox/gecko';
        }
        else if ( navigator.userAgent.match ( /trident\//i ) ) {
            return 'ie/trident';
        }
        else if ( navigator.userAgent.match ( /msie\//i ) ) {
            return 'ie/trident';
        }
        else
        {
            return navigator.userAgent + "\n" + navigator.vendor;
        }
    };  // BasicBrowserSniffer function

    console.info ( 'Entering function anonymous DocumentReady function' );
    console.info ( 'User Agent String   = ' + navigator.userAgent.toLowerCase ( ));
    console.info ( 'User Agent Vendor   = ' + var uav = navigator.vendor.toLowerCase ( );
    console.info ( 'BasicBrowserSniffer = ' + BasicBrowserSniffer ( ) );
    console.info ( 'Leaving function anonymous DocumentReady function' );
</script>

Upvotes: 1

Simone
Simone

Reputation: 21252

In my case I needed to target Safari on both iOS and macOS. This worked for me:

if (/apple/i.test(navigator.vendor)) {
  // It's Safari
}

Upvotes: 13

A.G.
A.G.

Reputation: 324

User agent sniffing is really tricky and unreliable. We were trying to detect Safari on iOS with something like @qingu's answer above, it did work pretty well for Safari, Chrome and Firefox. But it falsely detected Opera and Edge as Safari.

So we went with feature detection, as it looks like as of today, serviceWorker is only supported in Safari and not in any other browser on iOS. As stated in https://jakearchibald.github.io/isserviceworkerready/

Support does not include iOS versions of third-party browsers on that platform (see Safari support).

So we did something like

if ('serviceWorker' in navigator) {
    return 'Safari';
}
else {
    return 'Other Browser';
}

Note: Not tested on Safari on MacOS.

Upvotes: -4

Idan
Idan

Reputation: 4023

I create a function that return boolean type:

export const isSafari = () => navigator.userAgent.toLowerCase().indexOf('safari') !== -1

Upvotes: -1

SudarP
SudarP

Reputation: 936

Simplest answer:

function isSafari() {
 if (navigator.vendor.match(/[Aa]+pple/g).length > 0 ) 
   return true; 
 return false;
}

Upvotes: 5

Marcos Sandrini
Marcos Sandrini

Reputation: 450

For the records, the safest way I've found is to implement the Safari part of the browser-detection code from this answer:

const isSafari = window['safari'] && safari.pushNotification &&
    safari.pushNotification.toString() === '[object SafariRemoteNotification]';

Of course, the best way of dealing with browser-specific issues is always to do feature-detection, if at all possible. Using a piece of code like the above one is, though, still better than agent string detection.

Upvotes: 2

Christopher Martin
Christopher Martin

Reputation: 197

I don't know why the OP wanted to detect Safari, but in the rare case you need browser sniffing nowadays it's problably more important to detect the render engine than the name of the browser. For example on iOS all browsers use the Safari/Webkit engine, so it's pointless to get "chrome" or "firefox" as browser name if the underlying renderer is in fact Safari/Webkit. I haven't tested this code with old browsers but it works with everything fairly recent on Android, iOS, OS X, Windows and Linux.

<script>
    let browserName = "";

    if(navigator.vendor.match(/google/i)) {
        browserName = 'chrome/blink';
    }
    else if(navigator.vendor.match(/apple/i)) {
        browserName = 'safari/webkit';
    }
    else if(navigator.userAgent.match(/firefox\//i)) {
        browserName = 'firefox/gecko';
    }
    else if(navigator.userAgent.match(/edge\//i)) {
        browserName = 'edge/edgehtml';
    }
    else if(navigator.userAgent.match(/trident\//i)) {
        browserName = 'ie/trident';
    }
    else
    {
        browserName = navigator.userAgent + "\n" + navigator.vendor;
    }
    alert(browserName);
</script>

To clarify:

  • All browsers under iOS will be reported as "safari/webkit"
  • All browsers under Android but Firefox will be reported as "chrome/blink"
  • Chrome, Opera, Blisk, Vivaldi etc. will all be reported as "chrome/blink" under Windows, OS X or Linux

Upvotes: 13

qingu
qingu

Reputation: 2201

As other people have already noted, feature detection is preferred over checking for a specific browser. One reason is that the user agent string can be altered. Another reason is that the string may change and break your code in newer versions.

If you still want to do it and test for any Safari version, I'd suggest using this

var isSafari = navigator.vendor && navigator.vendor.indexOf('Apple') > -1 &&
               navigator.userAgent &&
               navigator.userAgent.indexOf('CriOS') == -1 &&
               navigator.userAgent.indexOf('FxiOS') == -1;

This will work with any version of Safari across all devices: Mac, iPhone, iPod, iPad.

Edit

To test in your current browser: https://jsfiddle.net/j5hgcbm2/

Edit 2

Updated according to Chrome docs to detect Chrome on iOS correctly

It's worth noting that all Browsers on iOS are just wrappers for Safari and use the same engine. See bfred.it's comment on his own answer in this thread.

Edit 3

Updated according to Firefox docs to detect Firefox on iOS correctly

Upvotes: 136

maxxx
maxxx

Reputation: 726

This unique "issue" is 100% sign that browser is Safari (believe it or not).

if (Object.getOwnPropertyDescriptor(Document.prototype, 'cookie').descriptor === false) {
   console.log('Hello Safari!');
}

This means that cookie object descriptor is set to false on Safari while on the all other is true, which is actually giving me a headache on the other project. Happy coding!

Upvotes: 1

Piotr Kowalski
Piotr Kowalski

Reputation: 338

I observed that only one word distinguishes Safari - "Version". So this regex will work perfect:

/.*Version.*Safari.*/.test(navigator.userAgent)

Upvotes: 6

H H
H H

Reputation: 376

I know this question is old, but I thought of posting the answer anyway as it may help someone. The above solutions were failing in some edge cases, so we had to implement it in a way that handles iOS, Desktop, and other platforms separately.

function isSafari() {
    var ua = window.navigator.userAgent;
    var iOS = !!ua.match(/iP(ad|od|hone)/i);
    var hasSafariInUa = !!ua.match(/Safari/i);
    var noOtherBrowsersInUa = !ua.match(/Chrome|CriOS|OPiOS|mercury|FxiOS|Firefox/i)
    var result = false;
    if(iOS) { //detecting Safari in IOS mobile browsers
        var webkit = !!ua.match(/WebKit/i);
        result = webkit && hasSafariInUa && noOtherBrowsersInUa
    } else if(window.safari !== undefined){ //detecting Safari in Desktop Browsers
        result = true;
    } else { // detecting Safari in other platforms
        result = hasSafariInUa && noOtherBrowsersInUa
    }
    return result;
}

Upvotes: 3

fregante
fregante

Reputation: 31678

Note: always try to detect the specific behavior you're trying to fix, instead of targeting it with isSafari?

As a last resort, detect Safari with this regex:

var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);

It uses negative look-arounds and it excludes Chrome, Edge, and all Android browsers that include the Safari name in their user agent.

Upvotes: 261

tylerlindell
tylerlindell

Reputation: 1563

Because userAgent for chrome and safari are nearly the same it can be easier to look at the vendor of the browser

Safari

navigator.vendor ==  "Apple Computer, Inc."

Chrome

navigator.vendor ==  "Google Inc."

FireFox (why is it empty?)

navigator.vendor ==  ""

IE (why is it undefined?)

navigator.vendor ==  undefined

Upvotes: 23

Yurii Sherbak
Yurii Sherbak

Reputation: 126

Modified regex for answer above

var isSafari = /^((?!chrome|android|crios|fxios).)*safari/i.test(navigator.userAgent);
  • crios - Chrome
  • fxios - Firefox

Upvotes: 4

lovepong
lovepong

Reputation: 625

I use this

function getBrowserName() {
    var name = "Unknown";
    if(navigator.userAgent.indexOf("MSIE")!=-1){
        name = "MSIE";
    }
    else if(navigator.userAgent.indexOf("Firefox")!=-1){
        name = "Firefox";
    }
    else if(navigator.userAgent.indexOf("Opera")!=-1){
        name = "Opera";
    }
    else if(navigator.userAgent.indexOf("Chrome") != -1){
        name = "Chrome";
    }
    else if(navigator.userAgent.indexOf("Safari")!=-1){
        name = "Safari";
    }
    return name;   
}

if( getBrowserName() == "Safari" ){
    alert("You are using Safari");
}else{
    alert("You are surfing on " + getBrowserName(name));
}

Upvotes: 5

david
david

Reputation: 4278

You can easily use index of Chrome to filter out Chrome:

var ua = navigator.userAgent.toLowerCase(); 
if (ua.indexOf('safari') != -1) { 
  if (ua.indexOf('chrome') > -1) {
    alert("1") // Chrome
  } else {
    alert("2") // Safari
  }
}

Upvotes: 127

wahid
wahid

Reputation: 1150

This code is used to detect only safari browser

if (navigator.userAgent.search("Safari") >= 0 && navigator.userAgent.search("Chrome") < 0) 
{
   alert("Browser is Safari");          
}

Upvotes: 27

Related Questions