Обнаружить браузер Safari

142

Как обнаружить браузер Safari с помощью JavaScript? Я попробовал код ниже, и он обнаруживает не только Safari, но и браузер Chrome.

function IsSafari() {

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

}
Tomas
источник
1
Часть кода JS, относящаяся к отправке файлов, работает почтительно для Safari, для Chrome работает нормально.
Томас
1
Вы почти наверняка должны проверять наличие различий в API. Помимо Safari и Chrome, существуют другие браузеры на основе WebKit.
Квентин
12
Есть много причин, по которым можно захотеть обнаружить браузер. Например, на момент написания этой статьи некоторые аспекты движка SVG, такие как фильтры, не работают в Safari, но работают в Chrome.
Пол Легато
Иногда вы просто не можете исправить ошибку, потому что вы не можете ее воспроизвести (у меня нет доступа к Mac). Я исправил проблему в Midori (некоторая проблема BlobBuilder / Blob для sendAsBinary shim), но клиент говорит, что проблема с загрузкой файлов все еще существует, поэтому лучшее, что я могу придумать, это просто удалить поддержку Safari и использовать для нее iframes (как для старый IE)
llamerr
1
Возможный дубликат Как обнаружить браузер Chrome и
Safari

Ответы:

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
Не работает В настоящее время выводит хромированную строку UA на iPhone, и в ней даже нет слова "хром".
Пол Карлтон
5
IE 11 UA строка в Windows 10 также содержит Safari и Chrome
cuixiping
Blackberry также включает в себя «Safari».
Гарри Пехконен
18
@Flimm Есть много законных вариантов использования для обнаружения браузером. Не позволяйте себе знать намерение спрашивающего или ответчика. Хотя полезно добавить полезный совет, который может показаться вам актуальным, это ни в коем случае не является обязательным требованием.
Рубен Мартинес-младший
1
Это не работает в браузерах Android, включая «safari», но не «chrome»: developers.whatismybrowser.com/useragents/explore/software_name/…
Эрик Эндрю Льюис
156

Примечание: всегда пытайтесь определить конкретное поведение, которое вы пытаетесь исправить, вместо того, чтобы указывать егоisSafari?

В крайнем случае, найдите Safari с помощью этого регулярного выражения:

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

Он использует негативные осмотры и исключает Chrome, Edge и все браузеры Android, которые включают Safariимя в свой пользовательский агент.

fregante
источник
2
Это не работает Я все еще понимаю, если я использую браузер Chrome на iPhone.
ayjay
27
Это потому, что все браузеры на iOS являются просто обертками для Safari (за исключением Opera Mini в режиме Mini ), включая Chrome. Это не обязательно означает, что все они будут соответствовать этому тесту, поскольку строка userAgent зависит от оболочки. Возможно, вы захотите обнаружить Chrome на iOS отдельно.
Фреганте
Чувак, это сработало для меня !!! Спасибо огромное .. navigator.userAgent возвращал значения типа «5.0 (Windows NT 6.1) AppleWebKit / 537.36 (KHTML, как Gecko) Chrome / 39.0.2171.99 Safari / 537.36» для Chrome в Windows и Safari в Mac.
KaustubhSV
2
Исправлено сейчас. Вы определенно правы, проблема многих браузеров заключается в том, что они включают другие имена, чтобы не остаться в стороне. Like Edge включает в себя как Chrome, так и Safari в своем UA. По этой причине проверки пользовательского агента плохие: браузеры меняются, и проверки должны быть обновлены. К сожалению, нет идеального способа обнаружить браузер, это всегда предположение.
Фреганте
1
Это определенно хорошая идея - использовать функцию обнаружения функций, но некоторые варианты поведения сложно или почти невозможно проверить, например, отображается ли видео на мобильном устройстве автоматически в полноэкранном режиме, что происходит только на iPhone и iPod. Чтобы проверить это, вам нужно загрузить видео и попросить пользователя воспроизвести его.
Фреганте
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 для корректного определения Chrome на iOS

Стоит отметить, что все браузеры на iOS являются просто обертками для Safari и используют один и тот же движок. См. Комментарий bfred.it к его собственному ответу в этой теме.

Редактировать 3

Обновлен в соответствии с документацией Firefox для правильного определения Firefox на iOS

qingu
источник
Спасибо за комментарий - Обновлено для правильного определения Chrome на iOS
qingu
@qingu - я не понимаю этот javascript, как бы я сделал что-то вроде - если (safaribrowser) {сделать это} else {сделать это}, используя тот же код, что значение 'var isSafari' спасибо
GAV
@GAV: isSafariбудет trueв браузере Safari, falseиначе. Вы можете просто использовать приведенный выше фрагмент, а затем использовать свой почти так, как вы его опубликовали. if (isSafari) { do_this(); } else { do_that(); },
Qingu
2
К сожалению, есть больше причин, чтобы попытаться выяснить браузер, чем просто обнаружение функций. Браузер может поддерживать функцию, но иметь ошибки (например: ошибка холста в IE10, но та же функция работает в IE9). Кроме того, Firefox ведет себя не так, как браузеры на основе webkit, например, как он реагирует на движение мыши. В Apple Safari есть ошибки перекомпоновки, которых нет в Chrome. Некоторые браузеры также эффективны при выполнении определенных вычислительно сложных задач, чем другие.
DemiImp
2
@Andras Для Firefox вы можете добавить && !navigator.userAgent.match('FxiOS')аналогичные проверки Chrome - ref ( developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/… )
Петри Пеллинен,
60

Просто используйте:

var isSafari = window.safari !== undefined;
if (isSafari) console.log("Safari, yeah!");
lukyer
источник
15
Не уверен, почему это не выше - это идеально, коротко и просто. Мне нужно было исключить настольное сафари из-за отсутствия getUserMedia.
Стивен Тетро
3
это идеальный способ определения настольного сафари, так как он не работает на мобильных устройствах
godblessstrawberry
Для каких версий Safari это работает? Кажется, не работает для v5.1.7
ElliotSchmelliot
Если вы заботитесь только о браузерах, а не о мобильных и настольных компьютерах, это работает отлично.
Антуан
1
Это не сработало в iPhone 11 Pro Max Simulator 13.5
Кристиан Валентин
19

Этот код используется для обнаружения только браузера Safari

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
определение платформы может, возможно, отфильтровать конкретные случаи совместимости.
августа
Я только что проверил полдюжины сторонних браузеров iOS, все они подделывают очень точный пользовательский агент Safari.
Митч Матч
Так что это будет обнаруживать только Chrome. И все же, я только что узнал, что Chrome 44 больше не имеет Chrome в UA, а вместо этого «CriOS» :(
Mitch Match
Мы всегда должны стараться обнаруживать функции и использовать обнаружение браузера в качестве крайней меры, так как последняя гораздо чаще ломает и блокирует законных пользователей. Любой ответ, в котором вообще не упоминается функция обнаружения, получает от меня отрицательное мнение.
Flimm
12

Поскольку userAgent для Chrome и Safari практически одинаковы, взглянуть на поставщика браузера проще.

Сафари

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

Хром

navigator.vendor ==  "Google Inc."

FireFox (почему он пуст?)

navigator.vendor ==  ""

IE (почему он не определен?)

navigator.vendor ==  undefined
tylerlindell
источник
1
Я искал что-то, чтобы отключить предупреждающие сообщения в Safari при работе на разных компьютерах (рабочие столы Mac, iPad и т. Д.), И это сработало отлично.
dylnmc
Но поставщиком для Chrome на iOS также будет «Apple Computer, Inc.». Извините ...
Петр Ковальский
@PiotrKowalski - какое решение вы выбрали?
Tylerlindell
@tylerlindell Смотрите мой ответ внизу этой страницы со словом "версия".
Петр Ковальский
7

Только сафари без хрома:

Попробовав другие коды, я не нашел ни одной, которая бы работала с новыми и старыми версиями 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>

leoledmag
источник
5

Я заметил, что только одно слово отличает Safari - «Версия». Так что это регулярное выражение будет работать идеально:

/.*Version.*Safari.*/.test(navigator.userAgent)
Петр Ковальский
источник
5

Я не знаю, почему ОП захотел обнаружить Safari, но в редких случаях вам нужно теперь прослушивать браузер, вероятно, гораздо важнее обнаружить механизм рендеринга, чем имя браузера. Например, в iOS все браузеры используют движок Safari / Webkit, поэтому бессмысленно указывать в качестве имени браузера «chrome» или «firefox», если в качестве базового средства визуализации используется Safari / Webkit. Я не тестировал этот код со старыми браузерами, но он работает со всем относительно недавним на 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»
  • Chrome, Opera, Blisk, Vivaldi и т. Д. Будут сообщаться как «chrome / blink» в Windows, OS X или Linux
Кристофер Мартин
источник
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));
}
lovepong
источник
4

Самый простой ответ:

function isSafari() {
 if (navigator.vendor.match(/[Aa]+pple/g).length > 0 ) 
   return true; 
 return false;
}
SudarP
источник
2
Это работает, хотя можно было бы сделать проще без регулярных выражений:navigator.vendor.toLowerCase().indexOf('apple') > -1
fviktor
5
Еще проще ... if (navigator.vendor.match(/apple/i)) { ... }.
Брэд
Это не работает для ios 13.3.1 на firefox, поскольку показывает Apple Computer, inc
nuttynibbles
1
@nuttynibbles: Это, вероятно, то, что вы хотите, потому что каждый браузер на iOS является замаскированным Safari.
пустырник
3

Для записей самый безопасный способ, который я нашел, это реализовать часть Safari кода обнаружения браузера из этого ответа :

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

Конечно, лучшим способом решения проблем, связанных с браузером, всегда является обнаружение функций, если это вообще возможно. Однако использование кода, подобного приведенному выше, все же лучше, чем определение строки агента.

Маркос Сандрини
источник
1
Это не работает с Safari Version / 13.1 Mobile / 15E148 Safari / 604.1 на iPhone OS 13_4_1.
Миндо
2

Я знаю, что этот вопрос старый, но я все равно решил опубликовать ответ, так как он может кому-то помочь. В некоторых крайних случаях вышеприведенные решения не дали результата, поэтому нам пришлось реализовать его таким образом, чтобы обрабатывать iOS, Desktop и другие платформы отдельно.

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;
}
HH
источник
1

Модифицированный регулярное выражение для ответа выше

var isSafari = /^((?!chrome|android|crios|fxios).)*safari/i.test(navigator.userAgent);
  • Crios - Chrome
  • fxios - Firefox
Юрий Щербак
источник
1

Эта уникальная «проблема» является 100% признаком того, что браузер Safari (верите или нет).

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

Это означает, что дескриптор объекта cookie установлен в false в Safari, а для всех остальных - true, что фактически вызывает головную боль в другом проекте. Удачного кодирования!

zoxxx
источник
Кажется, больше не правда. Также происходит сбой в Firefox «Object.getOwnPropertyDescriptor (...) не определен»
Offirmo
0

Может быть, это работает:

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

РЕДАКТИРОВАТЬ: НЕ Дольше работать

Харшал Карпентер
источник
Что именно это делает, потому что возвращает -1 во всех браузерах?
Petroff
@Petroff больше не работает в новом сафари. Спасибо за указание на это.
Харшал Карпентер
2
Не стесняйтесь удалить ответ.
Flimm
0

Я создаю функцию, которая возвращает логический тип:

export const isSafari = () => navigator.userAgent.toLowerCase().indexOf('safari') !== -1
Идан
источник
-2

Нюхание агента пользователя действительно сложно и ненадежно. Мы пытались обнаружить Safari на iOS с помощью чего-то вроде ответа @ qingu выше, он работал довольно хорошо для 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';
}

Примечание : не тестировалось в Safari на MacOS.

AG
источник