Rileva il browser Safari


142

Come rilevare il browser Safari utilizzando JavaScript? Ho provato il codice qui sotto e rileva non solo Safari ma anche il browser Chrome.

function IsSafari() {

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

}

1
Alcuni dei codici JS relativi all'invio di file funzionano in modo deferente per Safari, per Chrome funziona bene.
Tomas,

1
Dovresti quasi certamente provare per qualsiasi differenza nelle API ci siano. Esistono altri browser basati su WebKit oltre a Safari e Chrome.
Quentin,

12
Ci sono molte ragioni per cui si potrebbe desiderare di rilevare il browser. Ad esempio, al momento della stesura di questo articolo alcuni aspetti del motore SVG come i filtri sono rotti in Safari, ma funzionano in Chrome.
Paul Legato,

A volte non riesci a correggere il bug perché non riesci a riprodurlo (non ho accesso al Mac). Ho risolto il problema su Midori (alcuni problemi di BlobBuilder / Blob per sendAsBinary shim), ma il client dice che c'è ancora un problema con il caricamento dei file, quindi la cosa migliore che posso pensare è solo rimuovere il supporto Safari e usare iframe per esso (come per vecchio IE)
llamerr,

Risposte:


110

Puoi facilmente utilizzare l'indice di Chrome per filtrare Chrome:

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

6
Non funziona Attualmente sta trasmettendo una stringa UA cromata su iPhone e non contiene nemmeno la parola "chrome".
Paul Carlton,

5
La stringa IE 11 UA in Windows 10 contiene anche Safari e Chrome
cui

Blackberry include anche "Safari".
Harry Pehkonen,

18
@Flimm Esistono molti casi d'uso legittimi per il rilevamento del browser. Non presumere di conoscere l'intenzione del richiedente o del risponditore. Sebbene sia fantastico includere un suggerimento utile che potresti ritenere pertinente, non è assolutamente un requisito.
Ruben Martinez Jr.

1
Questo non funziona sui browser Android, che include "safari" ma non "chrome": developers.whatismybrowser.com/useragents/explore/software_name/…
Eric Andrew Lewis

156

Nota: cerca sempre di rilevare il comportamento specifico che stai tentando di correggere, anziché mirarloisSafari?

Come ultima risorsa, rileva Safari con questa regex:

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

Utilizza look-around negativi ed esclude Chrome, Edge e tutti i browser Android che includono il Safarinome nel loro user agent.


2
Questo non funziona Sto ancora diventando realtà se sto utilizzando Chrome Browser su un iPhone.
ajjay

27
Questo perché tutti i browser su iOS sono solo wrapper per Safari (ad eccezione di Opera Mini in modalità Mini ), incluso Chrome. Ciò non significa necessariamente che corrisponderanno tutti a questo test poiché la stringa userAgent dipende dal wrapper. Potresti voler rilevare Chrome su iOS separatamente.
fregante,

Amico, questo ha funzionato per me !!! Grazie mille .. navigator.userAgent stava restituendo valori come "5.0 (Windows NT 6.1) AppleWebKit / 537.36 (KHTML, come Gecko) Chrome / 39.0.2171.99 Safari / 537.36" sia per Chrome in Windows sia per Safari in mac.
KaustubhSV,

2
Riparato ora. Hai decisamente ragione, il problema con molti browser è che includono altri nomi per cercare di non essere esclusi. Like Edge include sia Chrome che Safari nei suoi UA. I controlli dell'agente utente sono errati per questo motivo: i browser cambiano e i controlli devono essere aggiornati. Purtroppo non esiste un modo perfetto per rilevare un browser, è sempre un'ipotesi.
fregante,

1
Sicuramente una buona idea utilizzare il rilevamento delle funzionalità, ma alcuni comportamenti sono semplicemente difficili o quasi impossibili da testare, ad esempio se i video sul cellulare passano automaticamente a schermo intero, cosa che accade solo su iPhone e iPod. Per testarlo, devi caricare un video e far riprodurre l'utente.
fregante,

91

Come altri hanno già notato, è preferibile il rilevamento delle funzionalità rispetto al controllo di un browser specifico. Uno dei motivi è che la stringa dell'agente utente può essere modificata. Un altro motivo è che la stringa può cambiare e rompere il codice nelle versioni più recenti.

Se vuoi ancora farlo e testare qualsiasi versione di Safari, ti suggerisco di usarlo

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

Funzionerà con qualsiasi versione di Safari su tutti i dispositivi: Mac, iPhone, iPod, iPad.

modificare

Per testare nel tuo browser attuale: https://jsfiddle.net/j5hgcbm2/

Modifica 2

Aggiornato in base ai documenti Chrome per rilevare correttamente Chrome su iOS

Vale la pena notare che tutti i browser su iOS sono solo involucri per Safari e utilizzano lo stesso motore. Vedi il commento di bfred.it sulla sua risposta in questa discussione.

Modifica 3

Aggiornato secondo i documenti di Firefox per rilevare correttamente Firefox su iOS


Grazie per il commento - Aggiornato per rilevare correttamente Chrome su iOS
qingu

@qingu - Non capisco questo javascript, come farei qualcosa del genere - se (safaribrowser) {do this} else {do ​​that} utilizzando lo stesso codice, il valore è 'var isSafari' grazie
GAV

@GAV: isSafarisarà truein un browser Safari, falsealtrimenti. Puoi semplicemente utilizzare lo snippet di cui sopra e quindi utilizzare il tuo quasi come lo hai pubblicato. if (isSafari) { do_this(); } else { do_that(); }.
qingu,

2
Sfortunatamente ci sono più motivi per provare a capire il browser oltre al semplice rilevamento delle funzionalità. Un browser può supportare una funzione, ma essere corrotto (es: bug di tela in IE10, ma la stessa funzione funziona in IE9). Anche Firefox si comporta in modo diverso rispetto ai browser basati su webkit, ad esempio come risponde al movimento del mouse. Safari di Apple ha bug di riflusso che non esistono in Chrome. Alcuni browser sono anche performanti quando svolgono determinate attività a livello di elaborazione rispetto ad altri.
DemiImp,

2
@Andras Per Firefox puoi aggiungere qualcosa di && !navigator.userAgent.match('FxiOS')simile al controllo di Chrome - ref ( developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/… )
Petri Pellinen,

60

Usa solo:

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

15
Non sono sicuro del perché questo non sia più in alto - è perfetto, breve e semplice. Avevo bisogno di escludere Safari desktop per la mancanza di getUserMedia.
Stephen Tetreault,

3
questo è il modo perfetto per determinare il desktop safari in quanto non funziona su dispositivi mobili
godblessstrawberry

Per quali versioni di Safari funziona? Non sembra funzionare per v5.1.7
ElliotSchmelliot il

Se ti interessano solo i browser e non i dispositivi mobili rispetto al desktop, questo funziona perfettamente.
Antuan,

1
Questo non ha funzionato con iPhone 11 Pro Max Simulator 13.5
Christian Valentin l'

19

Questo codice viene utilizzato per rilevare solo il browser Safari

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

4
questo codice rileva solo se un browser webkit non è Chrome. Molti altri browser hanno la cattiva idea di includere "safari" nella stringa del loro user agent. Ad esempio, 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 browser Android Stock:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.34 Safari/534.24
rupps

il lancio della piattaforma di rilevamento può forse filtrare specifici casi di compatibilità.
ljgww,

Ho appena controllato una mezza dozzina di browser iOS di terze parti, tutti falsificano l'esatto User-Agent Safari.
Mitch Match,

Quindi questo rileverà solo Chrome. Eppure, ho appena scoperto che Chrome 44 non ha più Chrome negli Emirati Arabi Uniti, ma invece "CriOS" :(
Mitch Match,

Dovremmo sempre cercare di eseguire il rilevamento delle funzionalità e utilizzare il rilevamento del browser come ultima risorsa, poiché quest'ultima ha molte più probabilità di violare e bloccare gli utenti legittimi. Qualsiasi risposta che non menziona affatto il rilevamento di funzionalità sta ottenendo un mio voto negativo.
Flimm,

12

Poiché userAgent per Chrome e Safari è quasi lo stesso, può essere più semplice consultare il fornitore del browser

Safari

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

Cromo

navigator.vendor ==  "Google Inc."

FireFox (perché è vuoto?)

navigator.vendor ==  ""

IE (perché non è definito?)

navigator.vendor ==  undefined

1
Stavo cercando qualcosa per disabilitare i messaggi di avviso in Safari sul lavoro su vari computer (desktop Mac, iPad, ecc.), E questo ha funzionato perfettamente.
dylnmc,

Ma il fornitore di Chrome su iOS sarà anche "Apple Computer, Inc.". Mi dispiace ...
Piotr Kowalski

@PiotrKowalski - con quale soluzione hai scelto?
Tylerlindell,

@tylerlindell Vedi la mia risposta in fondo a questa pagina con la parola "versione".
Piotr Kowalski,

7

Solo Safari senza Chrome:

Dopo aver provato altri codici non ne ho trovato nessuno che funzioni con le nuove e vecchie versioni di Safari.

Infine, ho fatto questo codice che funziona molto bene per me:

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

Ho osservato che solo una parola distingue Safari - "Versione". Quindi questa regex funzionerà perfettamente:

/.*Version.*Safari.*/.test(navigator.userAgent)

5

Non so perché l'OP abbia voluto rilevare Safari, ma nel raro caso al giorno d'oggi è necessario annusare il browser, è probabilmente più importante rilevare il motore di rendering rispetto al nome del browser. Ad esempio, su iOS tutti i browser utilizzano il motore Safari / Webkit, quindi è inutile ottenere "chrome" o "firefox" come nome del browser se il renderer sottostante è in realtà Safari / Webkit. Non ho testato questo codice con i vecchi browser ma funziona con tutto ciò che è abbastanza recente su 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>

Chiarire:

  • Tutti i browser sotto iOS verranno segnalati come "safari / webkit"
  • Tutti i browser con Android ma Firefox verranno indicati come "chrome / blink"
  • Chrome, Opera, Blisk, Vivaldi ecc. Verranno riportati come "chrome / blink" in Windows, OS X o Linux

4

Io lo uso

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

Risposta più semplice:

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

2
Funziona, anche se potrebbe essere fatto più semplice senza regexp:navigator.vendor.toLowerCase().indexOf('apple') > -1
fviktor

5
Ancora più semplice ... if (navigator.vendor.match(/apple/i)) { ... }.
Brad

Questo non funziona per iOS 13.3.1 su Firefox in quanto mostra Apple Computer, inc
nuttynibbles

1
@nuttynibbles: questo è probabilmente quello che vuoi perché ogni browser su iOS è un Safari sotto mentite spoglie.
Wortwart,

3

Per la cronaca, il modo più sicuro che ho trovato è implementare la parte Safari del codice di rilevamento del browser da questa risposta :

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

Naturalmente, il modo migliore per affrontare i problemi specifici del browser è sempre quello di rilevare le funzionalità, se possibile. L'uso di un pezzo di codice come quello sopra è, tuttavia, ancora meglio del rilevamento di stringhe di agenti.


1
Questo non funziona con Safari Version / 13.1 Mobile / 15E148 Safari / 604.1 su iPhone OS 13_4_1.
mindo

2

So che questa domanda è vecchia, ma ho pensato di pubblicare la risposta in quanto potrebbe aiutare qualcuno. Le soluzioni di cui sopra non funzionavano in alcuni casi limite, quindi abbiamo dovuto implementarlo in un modo che gestisse iOS, desktop e altre piattaforme separatamente.

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

Regex modificato per la risposta sopra

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

1

Questo "problema" unico indica al 100% che il browser è Safari (che ci crediate o no).

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

Ciò significa che il descrittore di oggetti cookie è impostato su false su Safari, mentre sull'altro è vero, il che in realtà mi sta facendo venire il mal di testa sull'altro progetto. Buona programmazione!


Sembra non più vero. Si arresta anche in modo anomalo su Firefox "Object.getOwnPropertyDescriptor (...) non è definito"
Offirmo

0

Forse questo funziona:

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

MODIFICA: NON FUNZIONA PIÙ


Cosa fa esattamente questo, perché restituisce -1 su tutti i browser?
Petroff,

@Petroff non funziona più nel nuovo safari. Grazie per segnalarlo.
Harshal Carpenter il

2
Sentiti libero di cancellare la risposta.
Flimm,

0

Creo una funzione che restituisce il tipo booleano:

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

-2

Lo sniffing dell'agente utente è davvero complicato e inaffidabile. Stavamo provando a rilevare Safari su iOS con qualcosa come la risposta di @ qingu sopra, ha funzionato abbastanza bene per Safari, Chrome e Firefox. Ma ha erroneamente rilevato Opera e Edge come Safari.

Quindi siamo andati con il rilevamento delle funzionalità, come sembra oggi, serviceWorkerè supportato solo in Safari e non in nessun altro browser su iOS. Come affermato in https://jakearchibald.github.io/isserviceworkerready/

Il supporto non include le versioni iOS di browser di terze parti su quella piattaforma (vedi supporto Safari).

Quindi abbiamo fatto qualcosa di simile

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

Nota : non testato su Safari su MacOS.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.