Can you determine if Chrome is in incognito mode via a script?
Solution 1
The functionality of this answer is Chrome version dependant. The most recent comment was this works in v90
Yes. The FileSystem API is disabled in incognito mode. Check out https://jsfiddle.net/w49x9f1a/ when you are and aren't in incognito mode.
Sample code:
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"));
}
Solution 2
In Chrome 74 to 84.0.4147.135 you can determine this by estimating the available file system storage space
See the 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')
}
Solution 3
One way is to visit a unique URL and then check to see whether a link to that URL is treated as visited by CSS.
You can see an example of this in "Detecting Incognito" (Dead link).
Research paper by same author to replace Detecting Incognito link above
In main.html
add an iframe,
<iframe id='testFrame' name='testFrame' onload='setUniqueSource(this)' src='' style="width:0; height:0; visibility:hidden;"></iframe>
, and some JavaScript code:
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 = '';
}
Then in test.html
that are loaded into the 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>
NOTE: trying this from the filesystem can make Chrome cry about "Unsafe Javascript". It will, however, work serving from a webserver.
Solution 4
You can, in JavaScript, see JHurrah's answer. Except for not highlighting links, all incognito mode does is not save browse history and cookies. From google help page:
- Webpages that you open and files downloaded while you are incognito aren't recorded in your browsing and download histories.
- All new cookies are deleted after you close all incognito windows that you've opened.
As you can see the differences between normal browsing and incognito happen after you visit the webpage, hence there is nothing that browser communicates to the server when it's in this mode.
You can see what exactly your browser sends to the server using one of many HTTP request analysers, like this one here. Compare the headers between normal session and incognito and you will see no difference.
Solution 5
If you are developing an Extension then you can use the tabs API to determine if a window/tab incognito.
More information can be found here.
If you are just working with a webpage, it is not easy, and it is designed to be that way. However, I have noticed that all attempts to open a database (window.database) fail when in incongnito, this is because when in incognito no trace of data is allowed to be left on the users machine.
I haven't tested it but I suspect all calls to localStorage fail too.
Comments
-
RodeoClown about 2 years
Is it possible to determine if Google Chrome is in incognito mode via a script?
Edit: I actually meant is it possible via user-script, but the answers assume JavaScript is running on a web page. I've re-asked the question here in regards to user scripts.
-
Mohamed Mansour almost 14 yearsAnd you have to remember that the user must allow incognito mode for the extension manual. By default, everything is true.
-
RodeoClown almost 14 years@Mohamed: The user having to allow it would be me, so that won't be a problem :)
-
RodeoClown almost 14 yearsWait, I just realised I didn't make myself clear - I meant with a user script. I'll keep this question alive, as it has some useful answers (thanks), but I'll ask another question with extra clarification.
-
MaddTheSane almost 11 years
-
Pete Alvin about 8 years@aren Why not make it easy for script to determine if being viewed in incognito/private mode? The page is still executed in the browser sandbox and (theoretically) can't do anything to circumvent the privateness of the page visit, yet the programmer could add value by knowing it's incognito. Am I missing something?
-
JohnC almost 7 years@PeteAlvin Or the site could detract value by detecting incognito. Boston Globe's site won't display its articles in incognito, preventing the user from circumventing their free articles quota. In general, I prefer a site know less about me.
-
Maykonn almost 6 yearsExists a lib to detect browsing mode: github.com/Maykonn/js-detect-incognito-private-browsing-paywall
-
Anonymous about 5 yearsYes, but should you? (Hint: no you shouldn't)
-
RodeoClown about 5 yearsUnless you want to, in which case it's fine.
-
sudoqux almost 4 years"Chrome will likewise work to remedy any other current or future means of Incognito Mode detection." quote from Google blog - so any solution is likely to stop working, at some point in the future.
-
Joe Rutkowski about 2 years@TiagoRangeldeSousa I own the repo detectIncognito mentioned below. Have you tested that, and if so did it not work? Presently I am able to detect incognito on all modern browsers.
-
Tiago Rangel de Sousa about 2 yearsSorry, detectIncognito works! I have deleted my message
-
-
Igor Zevaka almost 14 yearsThat's pretty cool, i didn't realise that incognito mode doesn't highlight visited links. This requires user to click a link though.
-
LaSul almost 14 yearsNo it doesn't, the iframe "clicks" the link.
-
Timo Tijhof over 11 yearsThis doesn't actually work since most browsers don't expose :visited style information through javascript. The CSS interface will say as if the link has the non-visited color. This is a security measure that has been in WebKit- and Gecko browsers at least since 2010. This was to protect the user's history (e.g. one could try all possible URLs, and send the visited ones to a third party. This way one could get access to tokens in urls and what not).
-
oxygen over 11 yearsRecently, it disables all extensions except those extensions which were specifically marked by the user as incognito safe.
-
Tom Teman over 8 yearsThis is the least hack-ish way and should be at the top. Clean and elegant.
-
Denilson Sá Maia about 8 yearsOfficial Mozilla article explaining the privacy changes regarding
:visited
: hacks.mozilla.org/2010/03/… -
user2718671 about 7 yearsThis is brilliant! Thank you soo much! The only problem is that it's asynchronous and since I have a situation where I have to wait for that check it slows down the page load by a few miliseconds.
-
Alok about 7 years@user2718671 do the check once and then set a cookie. A few ms on the first page load should not be noticeable in the larger scheme of things.
-
user2718671 about 7 years@Alok Thanks for that information. But I think in my case it wouldn't help because the user can't use all functionalities on the page if incognito mode is enabled. After the check a notification about that is displayed that the user if he wants to use all functionalities he should leave incognito mode and refresh the page. So the check every time he enters the page makes sense.
-
Alok about 7 years@user2718671 Again, if a few ms on a single page is a concern, you are doing something wrong. The cost of establishing a connection to a website (DNS + TCP + TLS) should dwarf your ms hit on the filesystem API call.
-
user2718671 about 7 years@Alok: Well, in the end the detection didn't work in all browsers anyway. Please check out: stackoverflow.com/questions/2860879/… What I did was to check if local storage and cookies are available and made the site work with some more if and else conditions. That worked best for me and the users.
-
Alok about 7 years@user2718671 jsfiddle.net/w49x9f1a still works fine for me in latest Chrome on mac osx. weird...
-
user2718671 about 7 years@Alok: I think it fails for Safari's Incognito Mode on Iphone 7. Safari - the new Internet Explorer ;)
-
Alexandru R about 7 yearsthis is not working anymore (maybe it worked in the past)
-
Alexandru R about 7 yearsthis is not working anymore (maybe it worked in the past)
-
Alok about 7 years@AlexandruRada still works for me. Again, this is for Chrome on the desktop. It's not going to work with other browsers/envs.
-
aljgom about 7 yearsJust updated my chrome now and it still works. I see you posted the same above and then said you were mistaken, just pointing this out for future viewers (feel free to delete your comment, I will delete this one if you do).
-
Lucas Massuh over 6 yearsI tried at Chrome. It works, but the logic is backwards.
-
Jay over 6 yearsI had the same experience as Lucas, it seems to work if you reverse the
console.log.bind
statements (I used an anonymous function there to set a variable to true or false) -
mccambridge over 6 yearsThinking this is out of date. When I log out the fs instance, I get an instance of
webkitRequestFileSystem
in both contexts. -
Ryan about 6 yearsThis looks very interesting and is a form of Javascript that I'm unfamiliar with and seems unsupported by my Netbeans 8.2 IDE in Windows 10. But if I can get it to work, I'm also curious: could I replace
reject('Check incognito failed')
withresolve(false)
if I wantisIncognito
to be a boolean that is only ever true or false? Thanks. -
Ryan about 6 yearsI see
Syntax Error: await is a reserved word
, and I thinkawait
always needs to be within anasync
function. So I think this code doesn't work. -
aljgom about 6 years
reject
would raise an exception if it is called, and a value would not be returned, soisIncognito
would always betrue
orfalse
the way the code is written. However, you would also be able to use a 'resolve' there if you want a value returned. And it might depend on how the environment handles await in the global scope? It works on the chrome console in the global scope, but you could try wrapping everything in(async function() { 'everything here' })();
so it is run inside an async function -
aljgom about 6 yearsAlternatively, you could just save the promise to
isIncognito
instead of the result, and run it afterwards in an async function:let isIncognito = new Promise( ...etc
then somewhere else you'd have a function like(async function() { if( !(await isIncognito) ) {alert('not incognito') } })();
-
Maykonn almost 6 yearsExists a lib to detect browsing mode: github.com/Maykonn/js-detect-incognito-private-browsing-paywall
-
tmarois over 5 yearsDoes this fail any errors with older browsers or other browsers other than Chrome/Firefox? I want to be sure it doesnt cause errors in like IE etc
-
user2434435 over 5 yearsThis is for Chrome ONLY!! so.. do not use it for OTHER browsers
-
blueren about 5 yearsThis is going to go away soon thanks to these commits
-
Alok about 5 yearsSemi-related to the question,
navigator.serviceWorker
is undefined in Firefox' incognito mode. Might be worth poking at Chrome's serviceWorker API to see if any differences pop up. -
LWC almost 5 yearsFunny enough @Alok - last month Chrome tried to beat your script, but failed!
-
Muhammad Faizan Uddin almost 5 yearsTry running Chrome's incognito mode with
disable-web-security
flag and the FileSystem API will still work on it -
LWC almost 5 yearsMeanwhile, Chrome v75 came out and beat the script (if you run JSFiddle it'll look not private when it is). But it only beats the script if the user enables the aforementioned secret opt-it setting. I assume by v76 this setting will be enabled by default and render this script obsolete.
-
LWC almost 5 yearsChrome v76 came up and just beats the script by default, which means this answer is no longer valid. But I read somewhere there's a limit on how much file size Chrome gives access to in InCogntio mode. So you may try to adjust the script to use this in order to beat Chrome again.
-
Cruncher over 4 yearsThis is the right answer now. Either the accepted answer should be updated with this, or the accepted answer should change. Not to take away from the originally accepted answer as it was the correct solution at the time.
-
Cruncher over 4 yearsThis answer is invalidated in chrome 76+
-
Alok over 4 yearsCorrect, see mishravikas.com/articles/2019-07/….
-
Gitesh Purbia over 4 yearsfail in chrome v 77.0.3865.90
-
Jay Momaya about 4 years@AmirB if you get any solution please share. Thank You.
-
Amir H. Bagheri almost 4 yearsNot yet. I haven’t found one.
-
Amit over 3 yearsconst {usage, quota} = await navigator.storage.estimate(); if(quota < 120000000){//Incognito} else {// not Incognito} This thing is still working in latest chrome browser.
-
Pragati Dugar over 3 yearsThis solution is no longer valid in newer chrome versions. I verified in Version 84.0.4147.135 (Official Build) (64-bit).And this is no longer the case.
-
Alok over 3 yearstry stackoverflow.com/a/57438917/2217509 for more recent Chrome versions.
-
vanisk over 3 yearsIt seems to be ok for my machine which uses Chrome Version 87.0.4280.67 (Official Build) (x86_64), it evens work when I changed the size to
0
.fs(window.TEMPORARY, 0, ...
-
djdance over 3 yearsUnfortunately, this doesn't work now: for example, in newest MS's EDGE I have 224053418 bytes in so called Private mode. In Chrome I see 234549212 bytes in Incognito mode.
-
SRR almost 3 yearsYour fiddle works for me but testing on localhost in incognito tells me that I'm not in incognito
-
Ivan Kuckir almost 3 years@S.Ramjit This script has to be executed in a webpage, which is in an iframe
-
Matěj Štágl over 2 yearsworks with chrome 96. As noted by author the script needs to be loaded server-side