检测Safari浏览器


142

如何使用JavaScript检测Safari浏览器?我在下面尝试过代码,它不仅可以检测Safari,还可以检测Chrome浏览器。

function IsSafari() {

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

}

1
与文件提交相关的一些JS代码可以在Safari上正常运行,对于Chrome可以正常运行。
托马斯

1
几乎可以肯定,您应该测试API是否存在差异。除了Safari和Chrome,还有其他基于WebKit的浏览器。
昆汀

12
人们可能希望检测到浏览器的原因有很多。例如,撰写本文时,SVG引擎的某些方面(例如过滤器)在Safari中已损坏,但在Chrome中有效。
Paul Legato 2012年

有时您只是无法修复错误,因为您无法复制它(我无法使用Mac)。我修复了Midori的问题(sendAsBinary shim的一些BlobBuilder / Blob问题),但是客户端说文件上传仍然存在问题,所以我能想到的最好的事情就是删除Safari支持并为此使用iframe(如旧版IE)
llamerr

Answers:


110

您可以轻松地使用Chrome的索引来过滤掉Chrome:

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

6
不起作用 当前在iPhone上输出chrome UA字符串,甚至没有单词“ chrome”。
Paul Carlton

5
Windows 10中的IE 11 UA字符串还包含Safari和Chrome
cuixiping 2015年

黑莓手机还包括“ Safari”。
哈里·佩科宁

18
@Flimm有许多用于浏览器检测的合法用例。不要以为知道询问者或应答者的意图。包含您可能认为有用的有用提示虽然很棒,但这绝不是必需的。
鲁宾·马丁内斯(Ruben Martinez)

1
这确实对Android的浏览器不工作,其中包括“野生动物园”,而不是“铬”:developers.whatismybrowser.com/useragents/explore/software_name/...
埃里克·安德鲁·刘易斯

156

注意:请始终尝试检测要修复的特定行为,而不要使用isSafari?

作为最后的手段,使用此正则表达式检测Safari:

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

它使用否定性环顾,并且不包括Chrome,Edge和所有Safari在其用户代理中包含该名称的Android浏览器。


2
这行不通。如果我在iPhone上使用Chrome浏览器,我仍然会理解。
ayjay 2015年

27
这是因为iOS上的所有浏览器都只是Safari的包装(Chrome浏览器除外)(在Mini模式下为Opera Mini )。这并不一定意味着他们将所有自的userAgent字符串到包装符合这个测试。您可能要分别在iOS检测Chrome
fregante

杜德这对我有用!!!感谢吨。navigator.userAgent对于Windows中的Chrome和Mac中的Safari都返回了诸如“ 5.0(Windows NT 6.1)AppleWebKit / 537.36(KHTML,如Gecko)Chrome / 39.0.2171.99 Safari / 537.36”之类的值。
KaustubhSV

2
立即修复。您肯定是对的,许多浏览器的问题在于它们包含其他名称,以免被遗漏。Like Edge在其UA中同时包含Chrome和Safari。由于以下原因,用户代理检查不正确:浏览器发生变化,并且需要更新检查。不幸的是,没有完美的方法来检测浏览器,这总是一个猜测。
fregante

1
使用功能检测绝对是个好主意,但有些行为很难或几乎无法测试,例如,移动视频是否自动全屏显示,而这种情况仅发生在iPhone和iPod上。要对其进行测试,您需要加载视频并让用户播放。
fregante 2015年

91

正如其他人已经指出的那样,相比于检查特定的浏览器,功能检测更为可取。原因之一是可以更改用户代理字符串。另一个原因是该字符串可能会更改,并在较新的版本中破坏您的代码。

如果您仍然想要这样做并测试任何Safari版本,建议您使用

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

此功能适用于所有设备上的任何版本的Safari:Mac,iPhone,iPod,iPad。

编辑

要在当前浏览器中进行测试:https : //jsfiddle.net/j5hgcbm2/

编辑2

已根据Chrome文档更新,以正确检测iOS上的Chrome

值得注意的是,iOS上的所有浏览器都只是Safari的包装器,并且使用相同的引擎。请参阅bfred.it在此线程中对自己答案的评论。

编辑3

根据Firefox文档进行了更新,以正确检测iOS上的Firefox


感谢您的评论-更新后可以在iOS上正确检测Chrome
qingu 2015年

@qingu-我听不懂这个javascript,我该怎么做-if(safaribrowser){这样做} else {这样做}使用相同的代码,值是'var isSafari'谢谢
GAV

@GAV:isSafari否则将true在Safari浏览器中false。您可以简单地使用上面的代码段,然后几乎在发布时使用您的代码段。if (isSafari) { do_this(); } else { do_that(); }
qingu

2
不幸的是,尝试找出浏览器的更多原因不仅仅是功能检测。浏览器可以支持某项功能,但会出现问题(例如:IE10中的canvas错误,但IE9中可以使用相同的功能)。Firefox的行为也不同于基于Webkit的浏览器,例如它对鼠标移动的响应方式。苹果的Safari浏览器具有Chrome中不存在的重排错误。与某些浏览器相比,某些浏览器在执行某些计算密集型任务时也表现出色。
DemiImp '16

2
@Andras对于Firefox,您可以添加&& !navigator.userAgent.match('FxiOS')类似于Chrome的检查功能
-ref

59

只需使用:

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

15
不知道为什么这不是更高的-这是完美,简短和简单的方法。我需要排除缺少Safari浏览器的情况getUserMedia
Stephen Tetreault,

3
这是确定台式设备浏览器的理想方法,因为这在移动设备上不起作用
godblessstrawberry

此功能适用于什么版本的Safari?似乎不适用于v5.1.7
ElliotSchmelliot

如果您只在乎浏览器,而不在乎移动与台式机,则此方法非常适用。
安端

1
这在iPhone 11 Pro Max Simulator 13.5中不起作用
Christian Valentin

19

此代码仅用于检测野生动物园浏览器

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

4
此代码仅检测Webkit浏览器不是chrome。许多其他浏览器的坏主意是在用户代理字符串中包含“ safari”。例如Opera Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36 OPR/24.0.1558.51 (Edition Next),或Stock Android浏览器:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.34 Safari/534.24
rupps 2015年

抛掷平台检测也许可以过滤掉特定的兼容性情况。
ljgww 2015年

我刚刚检查了六个第三方iOS浏览器,它们都欺骗了非常精确的Safari User-Agent。
米奇比赛

因此,这只会检测到Chrome。但是,我刚刚发现Chrome 44不再在UA中具有Chrome,而是用“ CriOS”代替:(
Mitch Match

我们应该始终尝试进行特征检测,并把浏览器检测作为最后的手段,因为后者更有可能破坏并阻止合法用户。任何根本不涉及功能检测的答案都对我不利。
Flimm

12

由于chrome和safari的userAgent几乎相同,因此可以更轻松地了解浏览器的供应商

苹果浏览器

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

navigator.vendor ==  "Google Inc."

FireFox(为什么它为空?)

navigator.vendor ==  ""

IE(为什么未定义?)

navigator.vendor ==  undefined

1
我一直在寻找可以在各种计算机(Mac台式机,ipad等)上工作的野生动物园中禁用警告消息的方法,并且此方法非常有效。
dylnmc

但是,iOS上的Chrome厂商也将是“ Apple Computer,Inc.”。抱歉...
Piotr Kowalski '18年

@PiotrKowalski-您选择了哪种解决方案?
tylerlindell

@tylerlindell请参阅本页底部带有“版本”字样的答案。
Piotr Kowalski '18

7

Safari淘汰的Chrome:

在尝试了其他代码之后,我没有发现任何适用于新旧版本的Safari的代码。

最后,我做了这段代码,对我来说效果很好:

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 = "Not is Safari!";
}
<body id="idbody">
</body>



5

我不知道为什么OP想要检测Safari,但在极少数情况下,如今您需要浏览器嗅探,检测渲染引擎可能比浏览器名称更重要。例如,在iOS上,所有浏览器都使用Safari / Webkit引擎,因此,如果底层渲染器实际上是Safari / Webkit,则将“ chrome”或“ firefox”作为浏览器名称毫无意义。我尚未在旧的浏览器上测试过此代码,但它可用于Android,iOS,OS X,Windows和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>

澄清:

  • iOS下的所有浏览器都将报告为“ safari / webkit”
  • Android(但Firefox)下的所有浏览器都将报告为“ chrome / blink”
  • 在Windows,OS X或Linux下,Chrome,Opera,Blisk,Vivaldi等将全部报告为“ chrome / blink”

4

我用这个

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

4

最简单的答案:

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

2
它可以工作,尽管不用regexp可以更简单:navigator.vendor.toLowerCase().indexOf('apple') > -1
fviktor

5
甚至更简单if (navigator.vendor.match(/apple/i)) { ... }
布拉德

这不适用于Firefox上的ios 13.3.1,因为它显示了Apple Computer,inc
nuttynibbles

1
@nuttynibbles:这可能是您想要的,因为iOS上的每个浏览器都是变相的Safari。
wortwart

3

对于记录,我找到的最安全的方法是从此答案中实现浏览器检测代码的Safari部分:

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

当然,处理浏览器特定问题的最佳方法始终是进行特征检测(如果可能的话)。但是,使用类似上面的代码仍然比代理字符串检测更好。


1
此功能不适用于iPhone OS 13_4_1上的Safari版本/13.1 Mobile / 15E148 Safari / 604.1。
mindo

2

我知道这个问题很旧,但我还是想发布答案,因为它可能会对某人有所帮助。上述解决方案在某些情况下是失败的,因此我们必须以分别处理iOS,桌面和其他平台的方式来实现它。

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


1

这个独特的“问题”是100%表示浏览器是Safari(信不信由你)。

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

这意味着cookie对象描述符在Safari上设置为false,而其他所有对象都为true,这实际上使我对另一个项目感到头疼。编码愉快!


似乎不再成立。在Firefox上也崩溃“ Object.getOwnPropertyDescriptor(...)未定义”
Offirmo

0

也许这可行:

Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor')

编辑:不再工作


这到底是做什么的,因为在所有浏览器上都返回-1?
彼得罗夫

@Petroff它不再适用于新的野生动物园。感谢您指出。
Harshal Carpenter

2
随时删除答案。
Flimm

0

我创建一个返回布尔类型的函数:

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

-2

用户代理嗅探确实是棘手且不可靠的。我们试图通过上面@qingu的回答来检测iOS上的Safari,它在Safari,Chrome和Firefox上确实表现良好。但是它错误地将Opera和Edge检测为Safari。

因此,我们进行了功能检测,直到今天为止,serviceWorker它仅在Safari中受支持,而在iOS上的任何其他浏览器中均不受支持。如https://jakearchibald.github.io/isserviceworkerready/中所述

支持不包括该平台上的第三方浏览器的iOS版本(请参阅Safari支持)。

所以我们做了类似的事情

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

注意:尚未在MacOS的Safari上进行测试。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.