Detectar o navegador Safari

142

Como detectar o navegador Safari usando JavaScript? Eu tentei o código abaixo e ele detecta não apenas o Safari, mas também o navegador Chrome.

function IsSafari() {

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

}
Tomas
fonte
1
Alguns dos códigos JS relacionados ao envio de arquivos funcionam de maneira diferencial para o Safari, pois o Chrome funciona bem.
Tomas
1
Você quase certamente deve estar testando as diferenças nas APIs existentes. Existem outros navegadores baseados no WebKit além do Safari e Chrome.
Quentin
12
Há muitas razões pelas quais alguém pode querer detectar o navegador. Por exemplo, no momento da redação deste documento, certos aspectos do mecanismo SVG, como filtros, são quebrados no Safari, mas estão funcionando no Chrome.
Paul Legato
Às vezes você simplesmente não consegue consertar o bug porque não pode reproduzi-lo (não tenho acesso ao Mac). Corrigi o problema no Midori (algum problema do BlobBuilder / Blob para o sendAsBinary shim), mas o cliente diz que ainda há um problema com o upload do arquivo, então a melhor coisa que consigo pensar é em remover o suporte do Safari e usar iframes para ele (como antigo IE)
llamerr

Respostas:

110

Você pode facilmente usar o índice do Chrome para filtrar o Chrome:

var ua = navigator.userAgent.toLowerCase(); 
if (ua.indexOf('safari') != -1) { 
  if (ua.indexOf('chrome') > -1) {
    alert("1") // Chrome
  } else {
    alert("2") // Safari
  }
}
david
fonte
6
Não funciona Atualmente, está produzindo uma string UA cromada no iPhone e nem sequer tem a palavra "chrome".
Paul Carlton
5
Corda IE 11 UA no Windows 10 também contém Safari e Chrome
cuixiping
Blackberry também inclui "Safari".
Harry Pehkonen
18
@Flimm Existem muitos casos de uso legítimos para detecção do navegador. Não presuma conhecer a intenção do autor ou do responsável pela resposta. Embora seja ótimo incluir uma dica útil que você considere relevante, ela não é de forma alguma um requisito.
Ruben Martinez Jr.
1
Isso não funciona em navegadores Android, que inclui "safari", mas não "cromo": developers.whatismybrowser.com/useragents/explore/software_name/...
Eric Andrew Lewis
156

Nota: tente sempre detectar o comportamento específico que você está tentando corrigir, em vez de segmentá-lo comisSafari?

Como último recurso, detecte o Safari com este regex:

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

Ele usa pesquisas negativas e exclui Chrome, Edge e todos os navegadores Android que incluem o Safarinome em seu agente de usuário.

fregante
fonte
2
Isso não funciona. Ainda estou conseguindo se estiver usando o Navegador Chrome em um iPhone.
ayjay
27
Isso ocorre porque todos os navegadores no iOS são apenas invólucros para o Safari (com exceção do Opera Mini no modo Mini ), incluindo o Chrome. Isso não significa necessariamente que todos eles corresponderão a esse teste, pois a sequência userAgent depende do wrapper. Convém detectar o Chrome no iOS separadamente.
24515 fregante
Cara isso funcionou para mim !!! Muito obrigado .. navigator.userAgent estava retornando valores como "5.0 (Windows NT 6.1) AppleWebKit / 537.36 (KHTML, como Gecko) Chrome / 39.0.2171.99 Safari / 537.36" para Chrome no Windows e Safari no mac.
precisa
2
Corrigido agora. Você está definitivamente certo, o problema com muitos navegadores é que eles incluem outros nomes para tentar não ficar de fora. O Like Edge inclui o Chrome e o Safari nos seus UA. As verificações do agente do usuário são ruins por esse motivo: os navegadores mudam e as verificações precisam ser atualizadas. Infelizmente, não há uma maneira perfeita de detectar um navegador, é sempre um palpite.
Fregante 29/10
1
Definitivamente, é uma boa idéia usar a detecção de recursos, mas alguns comportamentos são difíceis ou quase impossíveis de testar, por exemplo, se os vídeos no celular ficam automaticamente em tela cheia, algo que só acontece no iPhone e no iPod. Para testá-lo, você precisa carregar um vídeo e fazer com que o usuário o reproduza.
fregante
91

Como outras pessoas já observaram, a detecção de recursos é preferível à verificação de um navegador específico. Uma razão é que a sequência do agente do usuário pode ser alterada. Outro motivo é que a string pode mudar e quebrar seu código em versões mais recentes.

Se você ainda quiser fazer o teste e testar qualquer versão do Safari, sugiro usar este

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

Isso funcionará com qualquer versão do Safari em todos os dispositivos: Mac, iPhone, iPod, iPad.

Editar

Para testar no seu navegador atual: https://jsfiddle.net/j5hgcbm2/

Editar 2

Atualizado de acordo com os documentos do Chrome para detectar o Chrome no iOS corretamente

Vale ressaltar que todos os navegadores no iOS são apenas invólucros para o Safari e usam o mesmo mecanismo. Veja o comentário do bfred.it sobre sua própria resposta neste tópico.

Editar 3

Atualizado de acordo com os documentos do Firefox para detectar corretamente o Firefox no iOS

qingu
fonte
Obrigado pelo comentário - Atualizado para detectar o Chrome no iOS corretamente
qingu 7/11/15
@qingu - Eu não entendo esse javascript, como eu faria algo assim - se (safaribrowser) {faça ​​isso} mais {faça ​​isso} usando o mesmo código que valor é 'var isSafari' thanks
GAV
@GAV: isSafariestará trueem um navegador Safari, falsecaso contrário. Você pode simplesmente usar o snippet acima e, em seguida, usar o seu quase como o publicou. if (isSafari) { do_this(); } else { do_that(); }.
qingu 9/02/16
2
Infelizmente, existem mais motivos para tentar descobrir o navegador do que apenas a detecção de recursos. Um navegador pode oferecer suporte a um recurso, mas com erros (por exemplo, bug de tela no IE10, mas o mesmo recurso funciona no IE9). O Firefox também se comporta de maneira diferente dos navegadores baseados em webkit, como a forma como responde ao movimento do mouse. O Safari da Apple possui bugs de refluxo que não existem no Chrome. Alguns navegadores também têm bom desempenho ao executar determinadas tarefas intensivas em termos de computação que outros.
DemiImp
2
@Andras para o Firefox que você pode adicionar && !navigator.userAgent.match('FxiOS')similar ao Chrome check - ref ( developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/... )
Petri Pellinen
60

Apenas use:

var isSafari = window.safari !== undefined;
if (isSafari) console.log("Safari, yeah!");
lukyer
fonte
15
Não sei por que isso não é mais alto - é perfeito, curto e simples. Eu precisava descartar o safari de desktop por falta de getUserMedia.
Stephen Tetreault
3
esta é a maneira perfeita para determinar safari área de trabalho como este é não funciona no celular
godblessstrawberry
Para quais versões do Safari isso funciona? Parece que não funciona para a
v5.1.7
Se você se preocupa apenas com navegadores, e não com dispositivos móveis e computadores, isso funciona perfeitamente.
Antuan
1
Isso não funcionou dentro do iPhone 11 Pro Max Simulator 13.5
Christian Valentin
19

Este código é usado para detectar apenas o navegador safari

if (navigator.userAgent.search("Safari") >= 0 && navigator.userAgent.search("Chrome") < 0) 
{
   alert("Browser is Safari");          
}
wahid
fonte
4
esse código detecta apenas se um navegador de webkit não é cromado. Muitos outros navegadores têm a péssima idéia de incluir "safari" na cadeia de caracteres do agente do usuário. Por exemplo, 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)Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.34 Safari/534.24
:,
talvez a detecção da plataforma de lançamento possa filtrar casos de compatibilidade específicos.
Ljgww
Acabei de verificar meia dúzia de navegadores iOS de terceiros, todos eles falsificam o exato Agente do Usuário Safari.
Mitch Match
Portanto, isso detectará apenas o Chrome. E, no entanto, acabei de descobrir que o Chrome 44 não tem mais o Chrome nos UA, mas o 'CriOS' :(
Mitch Match
Sempre devemos tentar detectar recursos e usar a detecção de navegador como último recurso, pois é muito mais provável que este último interrompa e bloqueie usuários legítimos. Qualquer resposta que não mencione a detecção de recursos está recebendo um voto negativo de mim.
Flimm
12

Como o userAgent para chrome e safari é quase o mesmo, pode ser mais fácil procurar o fornecedor do navegador

Safári

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

cromada

navigator.vendor ==  "Google Inc."

FireFox (por que está vazio?)

navigator.vendor ==  ""

IE (por que é indefinido?)

navigator.vendor ==  undefined
tylerlindell
fonte
1
Eu estava procurando algo para desativar as mensagens de aviso no safari no trabalho em vários computadores (desktops mac, ipads etc.), e isso funcionou perfeitamente.
dylnmc
Mas o fornecedor do Chrome no iOS também será "Apple Computer, Inc.". Desculpe ...
Piotr Kowalski
@PiotrKowalski - com qual solução você foi?
precisa saber é o seguinte
@tylerlindell Veja minha resposta na parte inferior desta página com a palavra "versão".
Piotr Kowalski
7

Somente Safari sem o Chrome:

Depois de tentar outros códigos, não encontrei nenhum que funcionasse com versões novas e antigas do Safari.

Finalmente, eu fiz esse código que está funcionando muito bem para mim:

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
fonte
5

Eu observei que apenas uma palavra distingue o Safari - "Versão". Portanto, esse regex funcionará perfeitamente:

/.*Version.*Safari.*/.test(navigator.userAgent)
Piotr Kowalski
fonte
5

Não sei por que o OP queria detectar o Safari, mas, no caso raro, você precisa farejar o navegador hoje em dia, é provavelmente mais importante detectar o mecanismo de renderização do que o nome do navegador. Por exemplo, no iOS, todos os navegadores usam o mecanismo Safari / Webkit, portanto, é inútil obter "chrome" ou "firefox" como nome do navegador se o renderizador subjacente for de fato o Safari / Webkit. Não testei esse código com navegadores antigos, mas funciona com tudo relativamente recente no Android, iOS, OS X, Windows e 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>

Esclarecer:

  • Todos os navegadores no iOS serão relatados como "safari / webkit"
  • Todos os navegadores no Android, exceto o Firefox, serão relatados como "chrome / blink"
  • Chrome, Opera, Blisk, Vivaldi etc. serão todos relatados como "chrome / blink" no Windows, OS X ou Linux
Christopher Martin
fonte
4

Eu uso isso

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
fonte
4

Resposta mais simples:

function isSafari() {
 if (navigator.vendor.match(/[Aa]+pple/g).length > 0 ) 
   return true; 
 return false;
}
SudarP
fonte
2
Ele funciona, embora poderia ser feito mais simples, sem regexp:navigator.vendor.toLowerCase().indexOf('apple') > -1
fviktor
5
Ainda mais simples ... if (navigator.vendor.match(/apple/i)) { ... }.
Brad
Isso não funciona para o iOS 13.3.1 no firefox, pois mostra a Apple Computer, inc
nuttynibbles
1
@nuttynibbles: Provavelmente é isso que você deseja, pois todo navegador no iOS é um Safari disfarçado.
wortwart 14/07
3

Para os registros, a maneira mais segura que encontrei é implementar a parte do Safari do código de detecção de navegador com esta resposta :

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

Obviamente, a melhor maneira de lidar com problemas específicos do navegador é sempre a detecção de recursos, se possível. Usar um pedaço de código como o acima é, no entanto, ainda melhor que a detecção de cadeias de agentes.

Marcos Sandrini
fonte
1
Isso não funciona com o safari Versão / 13.1 Mobile / 15E148 Safari / 604.1 no iPhone OS 13_4_1.
mindo 24/04
2

Sei que essa pergunta é antiga, mas pensei em postar a resposta de qualquer maneira, pois isso pode ajudar alguém. As soluções acima estavam falhando em alguns casos extremos, então tivemos que implementá-lo de uma maneira que lidasse com iOS, Desktop e outras plataformas separadamente.

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
fonte
1

Regex modificado para a resposta acima

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

Esse "problema" único é 100% sinal de que o navegador é Safari (acredite ou não).

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

Isso significa que o descritor de objeto de cookie é definido como false no Safari, enquanto o outro é verdadeiro, o que realmente está me causando dor de cabeça no outro projeto. Feliz codificação!

zoxxx
fonte
Parece não ser mais verdade. Também falha no Firefox "Object.getOwnPropertyDescriptor (...) é indefinido"
Offirmo 20/03/19
0

Talvez isso funcione:

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

EDIT: NÃO FUNCIONA MAIS

Harshal Carpenter
fonte
O que exatamente isso está fazendo, porque retorna -1 em todos os navegadores?
precisa
@ Petoff não está mais trabalhando no safari mais recente. Obrigado por apontar isso.
Harshal Carpenter #
2
Sinta-se livre para excluir a resposta.
Flimm
0

Eu crio uma função que retorna o tipo booleano:

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

Farejar o agente do usuário é realmente complicado e não confiável. Estávamos tentando detectar o Safari no iOS com algo como a resposta do @ qingu acima, funcionou muito bem no Safari, Chrome e Firefox. Mas detectou falsamente o Opera e o Edge como Safari.

Por isso, optamos pela detecção de recursos, como parece hoje, serviceWorkersó é suportada no Safari e não em qualquer outro navegador no iOS. Conforme declarado em https://jakearchibald.github.io/isserviceworkerready/

O suporte não inclui versões iOS de navegadores de terceiros nessa plataforma (consulte o suporte ao Safari).

Então fizemos algo como

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

Nota : Não testado no Safari no MacOS.

AG
fonte