Détecter le navigateur Safari

142

Comment détecter le navigateur Safari en utilisant JavaScript? J'ai essayé le code ci-dessous et il détecte non seulement Safari, mais aussi le navigateur Chrome.

function IsSafari() {

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

}
Tomas
la source
1
Certains codes JS liés à la soumission de fichiers fonctionnent de manière respectueuse pour Safari, car Chrome fonctionne correctement.
Tomas
1
Vous devriez presque certainement tester les différences entre les API. Il existe d'autres navigateurs basés sur WebKit au-delà de Safari et Chrome.
Quentin
12
Il existe de nombreuses raisons pour lesquelles on peut souhaiter détecter le navigateur. Par exemple, au moment d'écrire ces lignes, certains aspects du moteur SVG tels que les filtres sont cassés dans Safari, mais fonctionnent dans Chrome.
Paul Legato
Parfois, vous ne pouvez tout simplement pas corriger le bogue car vous ne pouvez pas le reproduire (je n'ai pas accès à Mac). J'ai résolu un problème sur Midori (un problème BlobBuilder / Blob pour le shim sendAsBinary), mais le client dit qu'il y a toujours un problème avec le téléchargement de fichiers, donc la meilleure chose à laquelle je puisse penser est simplement de supprimer le support Safari et d'utiliser des iframes pour cela (comme pour old IE)
llamerr

Réponses:

110

Vous pouvez facilement utiliser l'index de Chrome pour filtrer Chrome:

var ua = navigator.userAgent.toLowerCase(); 
if (ua.indexOf('safari') != -1) { 
  if (ua.indexOf('chrome') > -1) {
    alert("1") // Chrome
  } else {
    alert("2") // Safari
  }
}
David
la source
6
Ça ne marche pas. Sortie de la chaîne chrome UA sur iPhone et ne contient même pas le mot "chrome".
Paul Carlton
5
La chaîne IE 11 UA dans Windows 10 contient également Safari et Chrome
Cuixiping
Blackberry comprend également «Safari».
Harry Pehkonen
18
@Flimm Il existe de nombreux cas d'utilisation légitimes pour la détection de navigateur. Ne présumez pas connaître l'intention du demandeur ou du répondant. Bien qu'il soit bon d'inclure un conseil utile que vous pensez peut-être pertinent, ce n'est en aucun cas une exigence.
Ruben Martinez Jr.
1
Cela ne fonctionne pas sur les navigateurs Android, qui incluent "safari" mais pas "chrome": développeurs.whatismybrowser.com
Eric Andrew Lewis
156

Remarque: essayez toujours de détecter le comportement spécifique que vous essayez de corriger, au lieu de le cibler avecisSafari?

En dernier recours, détectez Safari avec cette regex:

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

Il utilise des regards négatifs et exclut Chrome, Edge et tous les navigateurs Android qui incluent le Safarinom dans leur agent utilisateur.

frégante
la source
2
Cela ne marche pas. Je deviens toujours vrai si j'utilise le navigateur Chrome sur un iPhone.
ayjay
27
En effet, tous les navigateurs sur iOS ne sont que des wrappers pour Safari (à l'exception d'Opera Mini en mode Mini ), y compris Chrome. Cela ne signifie pas nécessairement qu'ils correspondent tous à ce test puisque la chaîne userAgent appartient au wrapper. Vous souhaiterez peut-être détecter Chrome sur iOS séparément.
fregante
Mec, cela a fonctionné pour moi !!! Merci beaucoup .. navigator.userAgent renvoyait des valeurs telles que "5.0 (Windows NT 6.1) AppleWebKit / 537.36 (KHTML, comme Gecko) Chrome / 39.0.2171.99 Safari / 537.36" pour Chrome sous Windows et Safari sous mac.
KaustubhSV
2
Corrigé maintenant. Vous avez certainement raison, le problème avec beaucoup de navigateurs est qu'ils incluent d'autres noms pour essayer de ne pas être en reste. Comme Edge inclut à la fois Chrome et Safari dans son UA. Les vérifications des agents utilisateurs sont mauvaises pour cette raison: les navigateurs changent et les vérifications doivent être mises à jour. Malheureusement, il n'y a pas de moyen parfait de détecter un navigateur, c'est toujours une supposition.
fregante
1
C'est certainement une bonne idée d'utiliser la détection des fonctionnalités, mais certains comportements sont simplement difficiles ou presque impossibles à tester, par exemple si les vidéos sur mobile passent automatiquement en plein écran, ce qui ne se produit que sur l'iPhone et l'iPod. Pour le tester, vous devez charger une vidéo et demander à l'utilisateur de la lire.
fregante
91

Comme d'autres personnes l'ont déjà noté, la détection des fonctionnalités est préférable à la recherche d'un navigateur spécifique. L'une des raisons est que la chaîne de l'agent utilisateur peut être modifiée. Une autre raison est que la chaîne peut changer et casser votre code dans les versions plus récentes.

Si vous voulez toujours le faire et tester n'importe quelle version de Safari, je vous suggère d'utiliser ceci

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

Cela fonctionnera avec n'importe quelle version de Safari sur tous les appareils: Mac, iPhone, iPod, iPad.

Éditer

Pour tester dans votre navigateur actuel: https://jsfiddle.net/j5hgcbm2/

Modifier 2

Mise à jour selon les documents Chrome pour détecter correctement Chrome sur iOS

Il convient de noter que tous les navigateurs sur iOS ne sont que des wrappers pour Safari et utilisent le même moteur. Voir le commentaire de bfred.it sur sa propre réponse dans ce fil.

Modifier 3

Mise à jour selon la documentation de Firefox pour détecter correctement Firefox sur iOS

qingu
la source
Merci pour le commentaire - Mise à jour pour détecter correctement Chrome sur iOS
qingu
@qingu - Je ne comprends pas ce javascript, comment pourrais-je faire quelque chose comme - if (safaribrowser) {do this} else {do ​​that} en utilisant le même code quelle valeur est 'var isSafari' merci
GAV
@GAV: isSafarisera truedans un navigateur Safari, falsesinon. Vous pouvez simplement utiliser l'extrait ci-dessus, puis utiliser le vôtre presque comme vous l'avez publié. if (isSafari) { do_this(); } else { do_that(); }.
qingu
2
Malheureusement, il y a plus de raisons d'essayer de comprendre le navigateur que la simple détection de fonctionnalités. Un navigateur peut prendre en charge une fonctionnalité, mais être bogué (ex: bogue de canevas dans IE10, mais la même fonctionnalité fonctionne dans IE9). Firefox se comporte également différemment des navigateurs basés sur des kits Web, comme par exemple la façon dont il réagit aux mouvements de la souris. Safari d'Apple a des bogues de redistribution qui n'existent pas dans Chrome. Certains navigateurs sont également plus performants lors de l'exécution de certaines tâches intensives en calcul que d'autres.
DemiImp
2
@Andras Pour Firefox, vous pouvez ajouter && !navigator.userAgent.match('FxiOS')une vérification similaire à Chrome - réf ( developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/… )
Petri Pellinen
60

Utilisez simplement:

var isSafari = window.safari !== undefined;
if (isSafari) console.log("Safari, yeah!");
Lukyer
la source
15
Je ne sais pas pourquoi ce n'est pas plus haut - est-ce parfait, court et simple. J'avais besoin d'exclure le safari de bureau faute de getUserMedia.
Stephen Tetreault
3
c'est un moyen idéal pour déterminer le safari de bureau car cela ne fonctionne pas sur mobile
godblessstrawberry
Pour quelles versions de Safari cela fonctionne-t-il? Ne semble pas fonctionner pour la v5.1.7
ElliotSchmelliot
Si vous ne vous souciez que des navigateurs, et non du mobile par rapport au bureau, cela fonctionne parfaitement.
Antuan
1
Cela n'a pas fonctionné dans l'iPhone 11 Pro Max Simulator 13.5
Christian Valentin
19

Ce code est utilisé pour détecter uniquement le navigateur Safari

if (navigator.userAgent.search("Safari") >= 0 && navigator.userAgent.search("Chrome") < 0) 
{
   alert("Browser is Safari");          
}
wahid
la source
4
ce code détecte uniquement si un navigateur Webkit n'est pas chrome. Beaucoup d'autres navigateurs ont la mauvaise idée d'inclure "safari" dans leur chaîne d'agent utilisateur. Par exemple, 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
:,
lancer la détection de plate-forme peut peut-être filtrer des cas de compatibilité spécifiques.
ljgww
Je viens de vérifier une demi-douzaine de navigateurs iOS tiers, ils usurpent tous le très exact Safari User-Agent.
Mitch Match
Donc, cela ne détectera que Chrome. Et pourtant, je viens de découvrir que Chrome 44 n'a plus Chrome dans l'UA, mais 'CriOS' à la place :(
Mitch Match
Nous devrions toujours essayer de faire la détection des fonctionnalités et utiliser la détection du navigateur en dernier recours, car cette dernière est beaucoup plus susceptible de casser et de bloquer les utilisateurs légitimes. Toute réponse qui ne mentionne pas du tout la détection de fonctionnalités reçoit un vote contre moi.
Flimm
12

Étant donné que userAgent pour chrome et safari sont presque les mêmes, il peut être plus facile de regarder le fournisseur du navigateur.

Safari

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

Chrome

navigator.vendor ==  "Google Inc."

FireFox (pourquoi est-il vide?)

navigator.vendor ==  ""

IE (pourquoi est-il indéfini?)

navigator.vendor ==  undefined
Tylerlindell
la source
1
Je cherchais quelque chose pour désactiver les messages d'avertissement en safari au travail sur divers ordinateurs (ordinateurs de bureau Mac, iPad, etc.), et cela a parfaitement fonctionné.
dylnmc
Mais le fournisseur de Chrome sur iOS sera également "Apple Computer, Inc.". Désolé ...
Piotr Kowalski
@PiotrKowalski - quelle solution avez-vous choisie?
tylerlindell
@tylerlindell Voir ma réponse au bas de cette page avec le mot "version".
Piotr Kowalski
7

Uniquement Safari sans Chrome:

Après avoir essayé d'autres codes, je n'en ai trouvé aucun qui fonctionne avec les nouvelles et anciennes versions de Safari.

Enfin, j'ai fait ce code qui fonctionne très bien pour moi:

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
la source
5

J'ai observé qu'un seul mot distingue Safari - "Version". Donc, cette regex fonctionnera parfaitement:

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

Je ne sais pas pourquoi l'OP voulait détecter Safari, mais dans les rares cas où vous avez besoin de renifler le navigateur, il est probablement plus important de détecter le moteur de rendu que le nom du navigateur. Par exemple sur iOS, tous les navigateurs utilisent le moteur Safari / Webkit, il est donc inutile d'avoir "chrome" ou "firefox" comme nom de navigateur si le moteur de rendu sous-jacent est en fait Safari / Webkit. Je n'ai pas testé ce code avec d'anciens navigateurs mais il fonctionne avec tout ce qui est assez récent sur Android, iOS, OS X, Windows et 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>

Clarifier:

  • Tous les navigateurs sous iOS seront signalés comme "safari / webkit"
  • Tous les navigateurs sous Android sauf Firefox seront signalés comme "chrome / clignotement"
  • Chrome, Opera, Blisk, Vivaldi etc. seront tous signalés comme "chrome / blink" sous Windows, OS X ou Linux
Christophe Martin
la source
4

Je l'utilise

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
la source
4

Réponse la plus simple:

function isSafari() {
 if (navigator.vendor.match(/[Aa]+pple/g).length > 0 ) 
   return true; 
 return false;
}
SudarP
la source
2
Cela fonctionne, bien que cela puisse être fait plus simple sans expression navigator.vendor.toLowerCase().indexOf('apple') > -1
régulière
5
Encore plus simple ... if (navigator.vendor.match(/apple/i)) { ... }.
Brad
Cela ne fonctionne pas pour iOS 13.3.1 sur Firefox comme il le montre Apple Computer, Inc
Nuttynibbles
1
@nuttynibbles: C'est probablement ce que vous voulez car chaque navigateur sur iOS est un Safari déguisé.
wortwart le
3

Pour mémoire, le moyen le plus sûr que j'ai trouvé est d'implémenter la partie Safari du code de détection du navigateur à partir de cette réponse :

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

Bien sûr, la meilleure façon de traiter les problèmes spécifiques au navigateur est toujours de faire la détection des fonctionnalités, si possible. Cependant, utiliser un morceau de code comme celui ci-dessus est toujours meilleur que la détection de chaîne d'agent.

Marcos Sandrini
la source
1
Cela ne fonctionne pas avec la version safari / 13.1 Mobile / 15E148 Safari / 604.1 sur iPhone OS 13_4_1.
mindo le
2

Je sais que cette question est ancienne, mais j'ai quand même pensé à poster la réponse car cela pourrait aider quelqu'un. Les solutions ci-dessus échouaient dans certains cas extrêmes, nous avons donc dû les implémenter de manière à gérer séparément iOS, Desktop et d'autres plates-formes.

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
la source
1

Modification de l'expression régulière pour la réponse ci-dessus

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

Ce «problème» unique est à 100% le signe que le navigateur est Safari (croyez-le ou non).

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

Cela signifie que le descripteur d'objet cookie est défini sur false sur Safari tandis que sur tous les autres est vrai, ce qui me donne en fait un mal de tête sur l'autre projet. Bon codage!

zoxxx
la source
Cela ne semble plus vrai. Se bloque également sur Firefox "Object.getOwnPropertyDescriptor (...) is undefined"
Offirmo
0

Peut-être que cela fonctionne:

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

EDIT: NE FONCTIONNE PLUS

Charpentier dur
la source
Qu'est-ce que cela fait exactement, car retourne -1 sur tous les navigateurs?
Petroff
@Petroff il ne fonctionne plus dans le nouveau safari. Merci de l'avoir signalé.
Harshal Carpenter
2
N'hésitez pas à supprimer la réponse.
Flimm
0

Je crée une fonction qui renvoie le type booléen:

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

Le reniflement d'agent utilisateur est vraiment délicat et peu fiable. Nous essayions de détecter Safari sur iOS avec quelque chose comme la réponse de @ qingu ci-dessus, cela fonctionnait plutôt bien pour Safari, Chrome et Firefox. Mais il a faussement détecté Opera et Edge comme Safari.

Nous avons donc opté pour la détection des fonctionnalités, car elle ressemble à ce jour, serviceWorkern'est prise en charge que dans Safari et dans aucun autre navigateur sur iOS. Comme indiqué dans https://jakearchibald.github.io/isserviceworkerready/

La prise en charge n'inclut pas les versions iOS de navigateurs tiers sur cette plate-forme (voir Prise en charge de Safari).

Alors nous avons fait quelque chose comme

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

Remarque : non testé sur Safari sous MacOS.

AG
la source