你能通过脚本确定 Chrome 是否处于隐身模式吗?

是否可以通过脚本确定 Google Chrome 是否处于隐身模式?

编辑: 实际上我的意思是通过用户脚本是否可行,但是答案假设 JavaScript 是在网页上运行的。关于用户脚本,我重新提出了这个问题。

103573 次浏览

一种方法是访问一个唯一的 URL,然后检查指向该 URL 的链接是否被 CSS 视为访问过。

您可以在“隐姓埋名检测”(死亡链接)中看到这方面的一个例子。

同一作者的研究论文代替了上述隐名链接的检测

main.html中添加一个 iframe,

 <iframe id='testFrame' name='testFrame' onload='setUniqueSource(this)' src='' style="width:0; height:0; visibility:hidden;"></iframe>

以及一些 JavaScript 代码:

function checkResult() {
var a = frames[0].document.getElementById('test');
if (!a) return;


var color;
if (a.currentStyle) {
color = a.currentStyle.color;
} else {
color = frames[0].getComputedStyle(a, '').color;
}


var visited = (color == 'rgb(51, 102, 160)' || color == '#3366a0');
alert('mode is ' + (visited ? 'NOT Private' : 'Private'));
}


function setUniqueSource(frame) {
frame.src = "test.html?" + Math.random();
frame.onload = '';
}

然后在 test.html中加载到 iFrame 中:

<style>
a:link { color: #336699; }
a:visited { color: #3366A0; }
</style>
<script>
setTimeout(function() {
var a = document.createElement('a');
a.href = location;
a.id = 'test';
document.body.appendChild(a);
parent.checkResult();
}, 100);
</script>

注意: 从文件系统中尝试这个操作可能会让 Chrome 为“不安全的 Javascript”而哭泣 但是,将工作从一个网络服务器。

您可以在 JavaScript 中查看 JHurrah 的 回答。除了没有突出显示链接,所有的隐身模式都没有保存浏览历史记录和 cookie。来自 google 帮助页面:

  • 当你隐姓埋名时打开的网页和下载的文件 没有记录在你的浏览和 下载历史记录。
  • 关闭所有隐身窗口后,所有新 Cookie 将被删除 你打开的那个。

正如你所看到的,正常浏览和匿名浏览之间的区别发生在 之后你访问该网页,因此浏览器在这种模式下没有任何东西与服务器通信。

您可以使用许多 HTTP 请求分析器之一(如 这个)查看浏览器到底向服务器发送了什么。比较标题之间的正常会话和隐姓埋名,你会看到没有区别。

如果您正在开发一个扩展,那么您可以使用选项卡 API 来确定窗口/选项卡是否隐藏。

更多信息可以找到 给你

如果你只是在使用一个网页,这并不容易,而且它就是这样设计的。然而,我注意到所有尝试打开数据库(window.database)的尝试都会在隐身状态下失败,这是因为隐身状态下不允许在用户机器上留下任何数据痕迹。

我还没有测试它,但我怀疑所有调用本地存储也会失败。

这个答案的功能取决于 Chrome 的版本

是的。文件系统 API 在隐身模式下是禁用的。当您处于和不处于隐身模式时,请查看 https://jsfiddle.net/w49x9f1a/

示例代码:

    var fs = window.RequestFileSystem || window.webkitRequestFileSystem;
if (!fs) {
console.log("check failed?");
} else {
fs(window.TEMPORARY,
100,
console.log.bind(console, "not in incognito mode"),
console.log.bind(console, "incognito mode"));
}

基于 阿洛克的回答的快速函数(注意: 这是异步的)

更新 -不再工作

function ifIncognito(incog,func){
var fs = window.RequestFileSystem || window.webkitRequestFileSystem;
if (!fs)  console.log("checking incognito failed");
else {
if(incog) fs(window.TEMPORARY, 100, ()=>{}, func);
else      fs(window.TEMPORARY, 100, func, ()=>{});
}
}

用途:

ifIncognito(true,  ()=>{ alert('in incognito') });
// or
ifIncognito(false, ()=>{ alert('not in incognito') });

更新 这似乎不再工作了


这使用了一个等待异步代码设置标志的承诺,这样我们就可以在以后同步地使用它。

let isIncognito = await new Promise((resolve, reject)=>{
var fs = window.RequestFileSystem || window.webkitRequestFileSystem;
if (!fs) reject('Check incognito failed');
else fs(window.TEMPORARY, 100, ()=>resolve(false), ()=>resolve(true));
});

然后我们就可以

if(isIncognito) alert('in incognito');
else alert('not in incognito');

注意,要使用 await,您需要位于一个异步函数内部。如果不是,那么可以将所有代码封装在一个代码中

下面是用 ES6语法编写的建议答案,稍微整理一下。

const isIncognito = () => new Promise((resolve, reject) => {
const fs = window.RequestFileSystem || window.webkitRequestFileSystem;
    

if (!fs) {
reject('Cant determine whether browser is running in incognito mode!');
}


fs(window.TEMPORARY, 100, resolve.bind(null, false), resolve.bind(null, true));
});


// Usage
isIncognito()
.then(console.log)
.catch(console.error)

在 Chrome74到84.0.4147.135中,你可以通过 估计可用的文件系统存储空间来确定这一点

看看 Jsfiddle

if ('storage' in navigator && 'estimate' in navigator.storage) {
const {usage, quota} = await navigator.storage.estimate();
console.log(`Using ${usage} out of ${quota} bytes.`);


if(quota < 120000000){
console.log('Incognito')
} else {
console.log('Not Incognito')
}
} else {
console.log('Can not detect')
}

这在2021年5月起作用: https://jsfiddle.net/2b1dk8oa/

该脚本必须在一个网页中执行,该网页位于一个 iframe 中。

try{
var ls = localStorage;
alert("You are not in Incognito Mode.");
}
catch(e) {  alert("You are in Incognito Mode.");  }

对于那些寻找解决方案的人来说,下面是2021年10月各种浏览器中当前检测私人浏览模式的方法的简要概述:

  • Chromium: 与 Vinnie James 的回答类似,调用导航器.storage.Estith () ,获取配额属性并将其与 Performance.memy.jsHeapSizelimit 进行比较。如果配额属性小于 jsHeapSizelimit,则为匿名。如果 jsHeapSizelimit 未定义,请使用1073741824(1GiB)。

  • Safari for macOS: 在不存在的推送服务器上使用 Safari.pushNotification.requestPermission 并获取错误。如果“手势”没有出现在错误中,那么它处于私有模式。

  • Safari for iOS: 创建一个 iframe 并使用 iframe 上的 contentWindow.applicationCache 添加一个错误事件侦听器。如果出现错误,它将处于私有模式。

  • 在一个私有窗口中没有定义 Firefox: Navator.serviceWorker。

  • Internet Explorer: window.indexedDB 将不在 InPrivate 模式中定义。

您可以在 GitHub 上的 隐姓埋名脚本中看到这些方法的实现。

其他答案似乎不再有效,在最近的铬版本。

这个想法是找出存储估计,以确定是否标签是隐名或没有。隐名标签的存储空间更小。

在普通和匿名窗口中运行此代码,并记下配额大小。

const {quota} = await navigator.storage.estimate();
console.log(quota);

使用配额大小差异来实现隐身模式检测的逻辑。


Chrome v105的逻辑工作如下:

const { quota } = await navigator.storage.estimate();


if (quota.toString().length === 10) {
console.log("gotcha: this is incognito tab"); //quota = 1102885027
} else {
console.log("this is a normal tab"); //quota = 296630877388
}

另外,看看这个解决方案获得更广泛的支持(也包括其他浏览器) 探测隐身者

演示: https://detectincognito.com/