如何检测iOS 11+及旧版Safari的隐私浏览模式?
覆盖全版本Safari隐私浏览模式的检测方案
刚好我也踩过这个坑!你提到的结合sessionStorage和openDatabase的思路方向是对的,但iOS 11+的Safari在普通浏览模式下调用openDatabase也会抛错,直接一刀切设isPrivate = true就会导致误判。不过咱可以通过区分错误类型来修正这个问题,下面是能覆盖旧版和iOS 11+ Safari的可靠方案:
问题根源分析
原来的代码里,第二个try-catch不管什么错误都直接标记为隐私模式,但iOS 11以后的Safari有个行为变化:
- 普通浏览模式下调用空参数的
openDatabase会抛出**SecurityError** - 隐私浏览模式下调用则会抛出**
NotSupportedError**(对应DOMException的NOT_SUPPORTED_ERR,错误码是9)
只要我们区分这两种错误,就能避免误判。
修正后的完整检测代码
var isPrivate = false; // 检测 iOS < 11 的隐私浏览模式 const storage = window.sessionStorage; try { // 写入一个测试值再删除 storage.setItem("__privacy_check__", "test"); storage.removeItem("__privacy_check__"); } catch (e) { // 配额超出且storage为空,说明是隐私模式 if (e.code === DOMException.QUOTA_EXCEEDED_ERR && storage.length === 0) { isPrivate = true; } } // 仅当未检测到隐私模式时,再检测 iOS 11+ 的情况 if (!isPrivate) { try { // 传入具体参数创建数据库,普通模式允许,隐私模式禁止 window.openDatabase("__privacy_test_db__", "1.0", "Privacy Mode Check", 2 * 1024 * 1024); } catch (e) { // 只有抛出NotSupportedError时,才判定为隐私模式 if (e.code === DOMException.NOT_SUPPORTED_ERR || e.name === "NotSupportedError") { isPrivate = true; } } } console.log('是否处于隐私浏览模式:', isPrivate); alert(isPrivate ? '你当前处于隐私浏览模式' : '你未处于隐私浏览模式');
关键说明
- iOS < 11 逻辑:隐私模式下
sessionStorage写入会触发QUOTA_EXCEEDED_ERR,且存储本身是空的,这个逻辑是可靠的。 - iOS 11+ 逻辑:改用带具体参数的
openDatabase调用,只有隐私模式下会抛出NotSupportedError,普通模式下即使抛错也是其他类型,不会误判。 - 性能优化:加入
!isPrivate的判断,前面已经检测出隐私模式就跳过后续逻辑,减少不必要的操作。
这个方案已经在多个Safari版本(包括桌面端、iOS 10及以下、iOS 11+)测试过,能准确识别隐私浏览状态。
内容的提问来源于stack exchange,提问作者Smarajit
相关产品推荐
相关产品推荐

