Phát hiện trình duyệt Safari


142

Làm cách nào để phát hiện trình duyệt Safari bằng JavaScript? Tôi đã thử mã bên dưới và nó phát hiện không chỉ Safari mà cả trình duyệt Chrome.

function IsSafari() {

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

}

1
Một số mã JS liên quan đến việc gửi tệp hoạt động ổn định cho Safari, cho Chrome hoạt động tốt.
Tomas

1
Bạn gần như chắc chắn sẽ kiểm tra xem có bất kỳ sự khác biệt nào trong các API không. Có các trình duyệt dựa trên WebKit khác ngoài Safari và Chrome.
Quentin

12
Có nhiều lý do người ta có thể muốn phát hiện trình duyệt. Ví dụ: khi viết bài này, một số khía cạnh nhất định của công cụ SVG, chẳng hạn như các bộ lọc bị hỏng trong Safari, nhưng hoạt động trong Chrome.
Paul Legato

Đôi khi, bạn không thể sửa lỗi vì bạn không thể sao chép nó (Tôi không có quyền truy cập vào Mac). Tôi đã khắc phục sự cố trên Midori (một số sự cố BlobBuilder / Blob cho sendAsBinary shim), nhưng khách hàng nói rằng vẫn có vấn đề với việc tải lên tệp, vì vậy điều tốt nhất tôi có thể nghĩ là chỉ cần xóa hỗ trợ Safari và sử dụng iframe cho nó (như đối với IE cũ)
llamerr

Câu trả lời:


110

Bạn có thể dễ dàng sử dụng chỉ mục của Chrome để lọc Chrome:

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

6
Không hoạt động. Hiện tại xuất ra chuỗi chrome UA trên iPhone và thậm chí nó không có từ "chrome" trong đó.
Paul Carlton

5
Chuỗi IE 11 UA trong Windows 10 cũng chứa Safari và Chrome
kết hợp vào

Blackberry cũng bao gồm "Safari."
Harry Pehkonen

18
@Flimm Có nhiều trường hợp sử dụng hợp pháp để phát hiện trình duyệt. Đừng suy đoán để biết ý định của người hỏi hoặc người trả lời. Mặc dù thật tuyệt khi bao gồm một mẹo hữu ích mà bạn có thể tin là có liên quan, nhưng nó không có nghĩa là một yêu cầu.
Ruben Martinez Jr.

1
Điều này không hoạt động trên các trình duyệt Android, bao gồm "safari" nhưng không "chrome": developers.whatismybrowser.com/useragents/explore/software_name/
Kẻ

156

Lưu ý: luôn cố gắng phát hiện hành vi cụ thể mà bạn đang cố gắng khắc phục, thay vì nhắm mục tiêu theoisSafari?

Như một phương sách cuối cùng, phát hiện Safari với regex này:

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

Nó sử dụng các giao diện tiêu cực và loại trừ Chrome, Edge và tất cả các trình duyệt Android có chứaSafari tên trong tác nhân người dùng của họ.


2
Điều này không hoạt động. Tôi vẫn đang đúng nếu tôi đang sử dụng Trình duyệt Chrome trên iPhone.
ayjay 23/2/2015

27
Đó là bởi vì tất cả các trình duyệt trên iOS chỉ là trình bao bọc cho Safari (ngoại trừ Opera Mini ở chế độ Mini ), bao gồm cả Chrome. Điều này không nhất thiết có nghĩa là tất cả chúng sẽ khớp với thử nghiệm này vì chuỗi userAgent tùy thuộc vào trình bao bọc. Bạn có thể muốn phát hiện Chrome riêng trên iOS .
fregante

Anh bạn này làm việc cho tôi !!! Cảm ơn rất nhiều .. navigator.userAgent đã trả về các giá trị như "5.0 (Windows NT 6.1) AppleWebKit / 537.36 (KHTML, như Gecko) Chrome / 39.0.2171.99 Safari / 537.36" cho cả Chrome trong Windows và Safari trong mac.
KaustubhSV

2
Đã sửa bây giờ. Bạn chắc chắn đúng, vấn đề với rất nhiều trình duyệt là chúng bao gồm các tên khác để cố gắng không bị bỏ sót. Giống như Edge bao gồm cả Chrome và Safari trong UA của nó. Kiểm tra tác nhân người dùng là xấu vì lý do này: trình duyệt thay đổi và kiểm tra cần phải được cập nhật. Thật không may, không có cách hoàn hảo để phát hiện trình duyệt, đó luôn là một phỏng đoán.
fregante

1
Chắc chắn là một ý tưởng tốt để sử dụng tính năng phát hiện tính năng, nhưng một số hành vi chỉ khó hoặc gần như không thể kiểm tra, ví dụ: liệu video trên thiết bị di động có tự động toàn màn hình hay không, điều gì đó chỉ xảy ra trên iPhone và iPod. Để kiểm tra nó, bạn cần tải một video và để người dùng phát nó.
fregante

91

Như những người khác đã lưu ý, phát hiện tính năng được ưu tiên hơn là kiểm tra một trình duyệt cụ thể. Một lý do là chuỗi tác nhân người dùng có thể bị thay đổi. Một lý do khác là chuỗi có thể thay đổi và phá vỡ mã của bạn trong các phiên bản mới hơn.

Nếu bạn vẫn muốn làm điều đó và thử nghiệm cho bất kỳ phiên bản Safari nào, tôi khuyên bạn nên sử dụng điều này

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

Điều này sẽ hoạt động với mọi phiên bản Safari trên tất cả các thiết bị: Mac, iPhone, iPod, iPad.

Biên tập

Để kiểm tra trong trình duyệt hiện tại của bạn: https://jsfiddle.net/j5hgcbm2/

Chỉnh sửa 2

Được cập nhật theo tài liệu Chrome để phát hiện Chrome trên iOS chính xác

Điều đáng chú ý là tất cả các Trình duyệt trên iOS chỉ là trình bao bọc cho Safari và sử dụng cùng một công cụ. Xem bình luận của bfred.it về câu trả lời của chính anh ấy trong chủ đề này.

Chỉnh sửa 3

Cập nhật theo tài liệu Firefox để phát hiện Firefox trên iOS chính xác


Cảm ơn vì nhận xét - Đã cập nhật để phát hiện Chrome trên iOS một cách chính xác
qingu

@qingu - Tôi không hiểu javascript này, tôi sẽ làm như thế nào - if (safaribrowser) {làm điều này} khác {làm điều đó} sử dụng cùng một mã với giá trị là 'var isSafari' cảm ơn
GAV

@GAV: isSafarinếu không sẽ có truetrong trình duyệt Safari false. Bạn chỉ có thể sử dụng đoạn mã trên và sau đó sử dụng đoạn mã của bạn gần như khi bạn đăng nó. if (isSafari) { do_this(); } else { do_that(); }.
qingu

2
Thật không may, có nhiều lý do hơn để cố gắng tìm ra trình duyệt hơn là chỉ phát hiện tính năng. Một trình duyệt có thể hỗ trợ một tính năng, nhưng bị lỗi (ví dụ: lỗi canvas trong IE10, nhưng tính năng tương tự hoạt động trong IE9). Ngoài ra Firefox hoạt động khác với các trình duyệt dựa trên webkit, chẳng hạn như cách nó phản ứng với chuyển động của chuột. Safari của Apple có các lỗi không tồn tại trong Chrome. Một số trình duyệt cũng hoạt động hiệu quả khi thực hiện một số tác vụ tính toán chuyên sâu hơn các trình duyệt khác.
DemiImp

2
@Andras Đối với Firefox, bạn có thể thêm && !navigator.userAgent.match('FxiOS')tương tự với kiểm tra Chrome - ref ( developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/iêu )
Petri Pellinen

58

Chỉ dùng:

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

15
Không chắc chắn tại sao điều này không cao hơn - điều này là hoàn hảo, ngắn và đơn giản. Tôi cần loại trừ safari máy tính để bàn vì thiếu getUserMedia.
Stephen Tetreault

3
Đây là cách hoàn hảo để xác định safari trên máy tính để bàn vì nó không hoạt động trên thiết bị di động
godblessstrawberry 16/03/18

Phiên bản Safari này hoạt động để làm gì? Dường như không hoạt động cho v5.1.7
ElliotSchmelliot

Nếu bạn chỉ quan tâm đến trình duyệt, và không di động so với máy tính để bàn, điều này hoạt động hoàn hảo.
Antuan

1
Điều này không hoạt động bên trong iPhone 11 Pro Max Simulator 13,5
Christian Valentin ngày

19

Mã này được sử dụng để chỉ phát hiện trình duyệt safari

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

4
mã này chỉ phát hiện ra một trình duyệt webkit không phải là chrome. Nhiều trình duyệt khác có ý tưởng tồi là đưa "safari" vào chuỗi tác nhân người dùng của họ. Ví dụ, 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), hoặc trình duyệt Android Cổ:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.34 Safari/534.24
rupps

phát hiện nền tảng quăng có lẽ có thể lọc ra các trường hợp tương thích cụ thể.
ljgww 11/05/2015

Tôi mới kiểm tra một nửa tá trình duyệt iOS của bên thứ ba, tất cả đều giả mạo Tác nhân người dùng Safari rất chính xác.
Trận đấu Mitch

Vì vậy, điều này sẽ chỉ phát hiện Chrome. Chưa hết, tôi mới phát hiện ra Chrome 44 không còn Chrome trong UA nữa mà thay vào đó là 'CriOS' :(
Mitch Match

Chúng ta nên luôn luôn cố gắng thực hiện phát hiện tính năng và sử dụng phát hiện trình duyệt như là phương sách cuối cùng, vì sau này có nhiều khả năng phá vỡ và chặn người dùng hợp pháp. Bất kỳ câu trả lời nào không đề cập đến phát hiện tính năng nào đều nhận được thông báo từ tôi.
Flimm

12

Vì userAgent cho chrome và safari gần giống nhau nên việc xem nhà cung cấp trình duyệt có thể dễ dàng hơn

Safari

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

Trình duyệt Chrome

navigator.vendor ==  "Google Inc."

FireFox (tại sao nó trống?)

navigator.vendor ==  ""

IE (tại sao nó không được xác định?)

navigator.vendor ==  undefined

1
Tôi đang tìm kiếm thứ gì đó để vô hiệu hóa các thông báo cảnh báo trong safari tại nơi làm việc trên nhiều máy tính khác nhau (máy tính để bàn mac, ipad, v.v.) và điều này đã hoạt động hoàn hảo.
dylnmc

Nhưng nhà cung cấp cho Chrome trên iOS cũng sẽ là "Apple Computer, Inc.". Xin lỗi ...
Piotr Kowalski

@PiotrKowalski - bạn đã đi với giải pháp nào?
tylerlindell

@tylerlindell Xem câu trả lời của tôi ở cuối trang này với từ "phiên bản".
Piotr Kowalski

7

Chỉ có Safari bạch Chrome:

Sau khi thử các mã khác, tôi không tìm thấy mã nào hoạt động với các phiên bản Safari mới và cũ.

Cuối cùng, tôi đã làm mã này hoạt động rất tốt cho tôi:

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

Tôi quan sát thấy rằng chỉ có một từ phân biệt Safari - "Phiên bản". Vì vậy, regex này sẽ hoạt động hoàn hảo:

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

5

Tôi không biết tại sao OP muốn phát hiện Safari, nhưng trong trường hợp hiếm hoi bạn cần trình duyệt đánh hơi ngày nay, việc phát hiện công cụ kết xuất quan trọng hơn tên của trình duyệt. Ví dụ: trên iOS, tất cả các trình duyệt đều sử dụng công cụ Safari / Webkit, do đó, việc lấy "chrome" hoặc "firefox" làm tên trình duyệt là vô nghĩa nếu trình kết xuất bên dưới thực tế là Safari / Webkit. Tôi chưa thử nghiệm mã này với các trình duyệt cũ nhưng nó hoạt động với mọi thứ khá gần đây trên Android, iOS, OS X, Windows và 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>

Làm rõ:

  • Tất cả các trình duyệt trong iOS sẽ được báo cáo là "safari / webkit"
  • Tất cả các trình duyệt trong Android nhưng Firefox sẽ được báo cáo là "chrome / flash"
  • Chrome, Opera, Blisk, Vivaldi, v.v ... đều sẽ được báo cáo là "chrome / flash" trong Windows, OS X hoặc Linux

4

Tôi dùng cái này

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

Câu trả lời đơn giản nhất:

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

2
Nó hoạt động, mặc dù có thể được thực hiện đơn giản hơn mà không cần navigator.vendor.toLowerCase().indexOf('apple') > -1
regrec

5
Thậm chí đơn giản ... if (navigator.vendor.match(/apple/i)) { ... }.
Brad

Điều này không làm việc cho ios 13.3.1 trên firefox vì nó cho thấy Apple Computer, inc
nuttynibbles

1
@nuttynibble: Đây có lẽ là những gì bạn muốn bởi vì mọi trình duyệt trên iOS là một Safari được ngụy trang.
wortwart

3

Đối với các bản ghi, cách an toàn nhất mà tôi đã tìm thấy là triển khai phần Safari của mã phát hiện trình duyệt từ câu trả lời này :

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

Tất nhiên, cách tốt nhất để xử lý các vấn đề cụ thể của trình duyệt là luôn luôn phát hiện tính năng, nếu có thể. Tuy nhiên, sử dụng một đoạn mã như đoạn trên vẫn tốt hơn so với phát hiện chuỗi tác nhân.


1
Điều này không hoạt động với phiên bản safari / 13.1 Mobile / 15E148 Safari / 604.1 trên iPhone OS 13_4_1.
mindo

2

Tôi biết câu hỏi này đã cũ, nhưng tôi đã nghĩ đến việc đăng câu trả lời vì dù sao nó cũng có thể giúp được ai đó. Các giải pháp trên đã thất bại trong một số trường hợp cạnh, vì vậy chúng tôi phải triển khai nó theo cách xử lý riêng các nền tảng iOS, Desktop và các nền tảng khác.

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 sửa đổi cho câu trả lời ở trên

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

1

"Vấn đề" độc đáo này là dấu hiệu 100% cho thấy trình duyệt là Safari (tin hay không).

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

Điều này có nghĩa là bộ mô tả đối tượng cookie được đặt thành false trên Safari trong khi trên tất cả các thứ khác là đúng, điều này thực sự khiến tôi đau đầu với dự án khác. Chúc mừng mã hóa!


Có vẻ không còn đúng nữa. Ngoài ra sự cố trên Firefox "Object.getOwnPropertyDescriptor (...) không xác định"
Offirmo 20/03/19

0

Có lẽ điều này hoạt động:

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

EDIT: KHÔNG LÀM VIỆC lâu hơn


Chính xác thì điều này đang làm gì, vì trả về -1 trên tất cả các trình duyệt?
Petroff

@Petroff nó không còn hoạt động trong safari mới hơn. Cảm ơn đã chỉ ra điều đó.
Thợ mộc Harshal

2
Hãy xóa câu trả lời.
Flimm

0

Tôi tạo một hàm trả về kiểu boolean:

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

-2

Tác nhân người dùng đánh hơi là thực sự khó khăn và không đáng tin cậy. Chúng tôi đã cố gắng phát hiện Safari trên iOS với câu trả lời giống như câu trả lời của @ qingu ở trên, nó đã hoạt động khá tốt cho Safari, Chrome và Firefox. Nhưng nó đã phát hiện sai Opera và Edge là Safari.

Vì vậy, chúng tôi đã phát hiện ra tính năng, vì có vẻ như ngày nay, serviceWorkerchỉ được hỗ trợ trong Safari và không có trong bất kỳ trình duyệt nào khác trên iOS. Như đã nêu trong https://jakearchibald.github.io/isserviceworkerready/

Hỗ trợ không bao gồm các phiên bản iOS của trình duyệt bên thứ ba trên nền tảng đó (xem hỗ trợ Safari).

Vì vậy, chúng tôi đã làm một cái gì đó như

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

Lưu ý : Không được thử nghiệm trên Safari trên MacOS.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.