Detectar el navegador Safari

142

¿Cómo detectar el navegador Safari usando JavaScript? He probado el código a continuación y detecta no solo Safari sino también el navegador Chrome.

function IsSafari() {

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

}
Tomás
fuente
1
Algunos de los códigos JS relacionados con el envío de archivos funcionan de manera deferente para Safari, para Chrome funciona bien.
Tomás
1
Seguramente deberías probar cualquier diferencia en las API que existan. Hay otros navegadores basados ​​en WebKit más allá de Safari y Chrome.
Quentin
12
Hay muchas razones por las que uno podría desear detectar el navegador. Por ejemplo, al momento de escribir esto, ciertos aspectos del motor SVG, como los filtros, están rotos en Safari, pero funcionan en Chrome.
Paul Legato
A veces, simplemente no puede corregir el error porque no puede reproducirlo (no tengo acceso a Mac). Solucioné un problema en Midori (algún problema de BlobBuilder / Blob para sendAsbinary shim), pero el cliente dice que todavía hay un problema con la carga de archivos, por lo que lo mejor que puedo pensar es simplemente eliminar el soporte de Safari y usar iframes para ello (en cuanto a antiguo IE)
llamerr

Respuestas:

110

Puede usar fácilmente el índice de Chrome para filtrar Chrome:

var ua = navigator.userAgent.toLowerCase(); 
if (ua.indexOf('safari') != -1) { 
  if (ua.indexOf('chrome') > -1) {
    alert("1") // Chrome
  } else {
    alert("2") // Safari
  }
}
david
fuente
66
No funciona Actualmente emite una cadena UA cromada en el iPhone y ni siquiera tiene la palabra "cromo".
Paul Carlton
55
La cadena de IE 11 UA en Windows 10 también contiene Safari y Chrome
Cuixiping
Blackberry también incluye "Safari".
Harry Pehkonen
18
@Flimm Hay muchos casos de uso legítimo para la detección del navegador. No presumas conocer la intención del autor de la pregunta o del que responde. Si bien es excelente incluir un consejo útil que pueda considerar relevante, de ninguna manera es un requisito.
Ruben Martinez Jr.
1
Esto no funciona en los navegadores de Android, que incluye "safari" pero no "chrome": developers.whatismybrowser.com/useragents/explore/software_name/…
Eric Andrew Lewis
156

Nota: siempre trate de detectar el comportamiento específico que está tratando de corregir, en lugar de apuntarlo conisSafari?

Como último recurso, detecta Safari con esta expresión regular:

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

Utiliza búsquedas negativas y excluye Chrome, Edge y todos los navegadores de Android que incluyen el Safarinombre en su agente de usuario.

fregante
fuente
2
Esto no funciona Todavía me estoy cumpliendo si estoy usando Chrome Browser en un iPhone.
ayjay
27
Esto se debe a que todos los navegadores en iOS son solo envoltorios para Safari (con la excepción de Opera Mini en modo Mini ), incluido Chrome. Esto no significa necesariamente que todos coincidan con esta prueba, ya que la cadena userAgent depende del reiniciador. Es posible que desee detectar Chrome en iOS por separado.
fregante
¡Amigo, esto funcionó para mí! Muchas gracias .. navigator.userAgent estaba devolviendo valores como "5.0 (Windows NT 6.1) AppleWebKit / 537.36 (KHTML, como Gecko) Chrome / 39.0.2171.99 Safari / 537.36" para Chrome en Windows y Safari en mac.
KaustubhSV
2
Corregido ahora. Definitivamente tiene razón, el problema con muchos navegadores es que incluyen otros nombres para tratar de no quedarse fuera. Like Edge incluye Chrome y Safari en su UA. Las verificaciones de agente de usuario son malas por este motivo: los navegadores cambian y las verificaciones deben actualizarse. Desafortunadamente no hay una manera perfecta de detectar un navegador, siempre es una suposición.
fregante
1
Definitivamente es una buena idea usar la detección de funciones, pero algunos comportamientos son difíciles o casi imposibles de probar, por ejemplo, si los videos en dispositivos móviles pasan automáticamente a pantalla completa, algo que solo ocurre en el iPhone y el iPod. Para probarlo, debe cargar un video y hacer que el usuario lo reproduzca.
fregante 11/11/2015
91

Como otras personas ya han notado, la detección de características es preferible a la verificación de un navegador específico. Una razón es que la cadena del agente de usuario puede modificarse. Otra razón es que la cadena puede cambiar y romper su código en versiones más nuevas.

Si todavía quieres hacerlo y probar cualquier versión de Safari, te sugiero que uses esto

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

Esto funcionará con cualquier versión de Safari en todos los dispositivos: Mac, iPhone, iPod, iPad.

Editar

Para probar en su navegador actual: https://jsfiddle.net/j5hgcbm2/

Editar 2

Actualizado de acuerdo con los documentos de Chrome para detectar Chrome en iOS correctamente

Vale la pena señalar que todos los navegadores en iOS son solo envoltorios para Safari y usan el mismo motor. Vea el comentario de bfred.it sobre su propia respuesta en este hilo.

Editar 3

Actualizado de acuerdo con los documentos de Firefox para detectar Firefox en iOS correctamente

qingu
fuente
Gracias por el comentario - Actualizado para detectar Chrome en iOS correctamente
qingu
@qingu: no entiendo este javascript, ¿cómo haría algo así? si (safaribrowser) {haga esto} más {haga eso} usando el mismo código, qué valor es 'var isSafari' gracias
GAV
@GAV: isSafariestará trueen un navegador Safari, de lo falsecontrario. Simplemente puede usar el fragmento anterior y luego usar el suyo casi como lo publicó. if (isSafari) { do_this(); } else { do_that(); }.
qingu
2
Desafortunadamente, hay más razones para tratar de descubrir el navegador que solo la detección de funciones. Un navegador puede admitir una función, pero puede tener errores (por ejemplo, error de lienzo en IE10, pero la misma función funciona en IE9). Además, Firefox se comporta de manera diferente a los navegadores basados ​​en webkit, como la forma en que responde al movimiento del mouse. Safari de Apple tiene errores de reflujo que no existen en Chrome. Algunos navegadores también son eficaces cuando realizan ciertas tareas computacionalmente intensivas que otras.
DemiImp
2
@Andras Para Firefox puede agregar algo && !navigator.userAgent.match('FxiOS')similar al cheque de Chrome - ref ( developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/… )
Petri Pellinen
60

Solo usa:

var isSafari = window.safari !== undefined;
if (isSafari) console.log("Safari, yeah!");
lukyer
fuente
15
No estoy seguro de por qué esto no está más arriba: es perfecto, corto y simple. Necesitaba descartar el safari de escritorio por falta de getUserMedia.
Stephen Tetreault
3
ésta es la manera perfecta para determinar safari de escritorio ya que esto es no funciona en el móvil
godblessstrawberry
¿Para qué versiones de Safari funciona esto? No parece funcionar para v5.1.7
ElliotSchmelliot
Si solo le interesan los navegadores, y no los dispositivos móviles frente al escritorio, esto funciona perfectamente.
Antuan
1
Esto no funcionó dentro del iPhone 11 Pro Max Simulator 13.5
Christian Valentin
19

Este código se usa para detectar solo el navegador safari

if (navigator.userAgent.search("Safari") >= 0 && navigator.userAgent.search("Chrome") < 0) 
{
   alert("Browser is Safari");          
}
wahid
fuente
44
Este código solo detecta si un navegador webkit no es Chrome. Muchos otros navegadores tienen la mala idea de incluir "safari" en su cadena de agente de usuario. Por ejemplo, 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)o Stock Stock browser:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.34 Safari/534.24
rompe el
la detección de plataforma de lanzamiento quizás pueda filtrar casos de compatibilidad específicos.
ljgww
Acabo de revisar media docena de navegadores iOS de terceros, todos ellos falsifican el Agente de Usuario de Safari muy exacto.
Mitch Match
Entonces esto solo detectará Chrome. Y, sin embargo, me acabo de enterar de que Chrome 44 ya no tiene Chrome en la UA, sino 'CriOS' :(
Mitch Match
Siempre debemos tratar de hacer la detección de funciones y usar la detección del navegador como último recurso, ya que es mucho más probable que este último rompa y bloquee a los usuarios legítimos. Cualquier respuesta que no mencione la detección de características está recibiendo un voto negativo de mi parte.
Flimm
12

Debido a que userAgent para Chrome y Safari son casi iguales, puede ser más fácil mirar al proveedor del navegador

Safari

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

Cromo

navigator.vendor ==  "Google Inc."

Firefox (¿por qué está vacío?)

navigator.vendor ==  ""

IE (¿por qué no está definido?)

navigator.vendor ==  undefined
tylerlindell
fuente
1
Estaba buscando algo para desactivar los mensajes de advertencia en safari en el trabajo en varias computadoras (computadoras de escritorio mac, ipads, etc.), y esto funcionó perfectamente.
dylnmc
Pero el proveedor de Chrome en iOS también será "Apple Computer, Inc.". Lo siento ...
Piotr Kowalski
@PiotrKowalski: ¿con qué solución fuiste?
tylerlindell
@tylerlindell Vea mi respuesta al final de esta página con la palabra "versión".
Piotr Kowalski
7

Solo Safari sin Chrome:

Después de probar otros códigos, no encontré ninguno que funcione con versiones nuevas y antiguas de Safari.

Finalmente, hice este código que me funciona muy bien:

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

Observé que solo una palabra distingue Safari - "Versión". Entonces esta expresión regular funcionará perfectamente:

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

No sé por qué el OP quería detectar Safari, pero en el raro caso de que necesite rastrear el navegador hoy en día es probablemente más importante detectar el motor de renderizado que el nombre del navegador. Por ejemplo, en iOS todos los navegadores utilizan el motor Safari / Webkit, por lo que no tiene sentido obtener "Chrome" o "Firefox" como nombre del navegador si el procesador subyacente es de hecho Safari / Webkit. No he probado este código con navegadores antiguos, pero funciona con todo lo bastante reciente en Android, iOS, OS X, Windows y 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>

Para aclarar:

  • Todos los navegadores bajo iOS serán reportados como "safari / webkit"
  • Todos los navegadores con Android, pero Firefox se informarán como "Chrome / Blink"
  • Chrome, Opera, Blisk, Vivaldi, etc. se informarán como "cromo / parpadeo" en Windows, OS X o Linux
Christopher Martin
fuente
4

yo uso esto

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

La respuesta más simple:

function isSafari() {
 if (navigator.vendor.match(/[Aa]+pple/g).length > 0 ) 
   return true; 
 return false;
}
SudarP
fuente
2
Funciona, aunque podría hacerse más simple sin regexp:navigator.vendor.toLowerCase().indexOf('apple') > -1
fviktor
55
Aún más simple ... if (navigator.vendor.match(/apple/i)) { ... }.
Brad
Esto no funciona para iOS 13.3.1 en Firefox, ya que muestra Apple Computer, Inc.
nuttynibbles
1
@nuttynibbles: Esto es probablemente lo que quieres porque cada navegador en iOS es un Safari disfrazado.
wortwart
3

Para los registros, la forma más segura que he encontrado es implementar la parte Safari del código de detección del navegador a partir de esta respuesta :

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

Por supuesto, la mejor manera de lidiar con problemas específicos del navegador es siempre mediante la detección de características, si es posible. Sin embargo, usar un código como el anterior es aún mejor que la detección de cadenas de agente.

Marcos Sandrini
fuente
1
Esto no funciona con Safari Version / 13.1 Mobile / 15E148 Safari / 604.1 en iPhone OS 13_4_1.
mindo
2

Sé que esta pregunta es antigua, pero pensé en publicar la respuesta de todos modos, ya que puede ayudar a alguien. Las soluciones anteriores fallaban en algunos casos extremos, por lo que tuvimos que implementarlo de una manera que maneje iOS, escritorio y otras plataformas por separado.

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;
}
S.S
fuente
1

Regex modificado para la respuesta anterior

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

Este "problema" único es 100% signo de que el navegador es Safari (lo creas o no).

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

Esto significa que el descriptor de objeto de cookie está establecido en falso en Safari, mientras que en el resto es cierto, lo que en realidad me está dando dolor de cabeza en el otro proyecto. ¡Feliz codificación!

zoxxx
fuente
Parece que ya no es verdad. También se bloquea en Firefox "Object.getOwnPropertyDescriptor (...) no está definido"
Offirmo
0

Quizás esto funciona:

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

EDITAR: NO TRABAJAR MÁS

Carpintero Harshal
fuente
¿Qué está haciendo esto exactamente, porque devuelve -1 en todos los navegadores?
Petroff
@Petroff ya no funciona en un nuevo safari. Gracias por mencionarlo.
Harshal Carpenter
2
Siéntase libre de eliminar la respuesta.
Flimm
0

Creo una función que devuelve el tipo booleano:

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

El rastreo de agentes de usuario es realmente complicado y poco confiable. Intentábamos detectar Safari en iOS con algo como la respuesta de @ qingu anterior, funcionó bastante bien para Safari, Chrome y Firefox. Pero detectó falsamente Opera y Edge como Safari.

Así que optamos por la detección de funciones, ya que parece que hoy en día serviceWorkersolo se admite en Safari y no en ningún otro navegador en iOS. Como se indica en https://jakearchibald.github.io/isserviceworkerready/

El soporte no incluye versiones de iOS de navegadores de terceros en esa plataforma (ver soporte de Safari).

Entonces hicimos algo como

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

Nota : No probado en Safari en MacOS.

AG
fuente