Can you determine if Chrome is in incognito mode via a script?

97,079

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.

Share:
97,079
RodeoClown
Author by

RodeoClown

I filled 'About Me' out purely to get a badge!

Updated on April 14, 2022

Comments

  • RodeoClown
    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
      Mohamed Mansour almost 14 years
      And you have to remember that the user must allow incognito mode for the extension manual. By default, everything is true.
    • RodeoClown
      RodeoClown almost 14 years
      @Mohamed: The user having to allow it would be me, so that won't be a problem :)
    • RodeoClown
      RodeoClown almost 14 years
      Wait, 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
      MaddTheSane almost 11 years
    • Pete Alvin
      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
      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
      Maykonn almost 6 years
    • Anonymous
      Anonymous about 5 years
      Yes, but should you? (Hint: no you shouldn't)
    • RodeoClown
      RodeoClown about 5 years
      Unless you want to, in which case it's fine.
    • sudoqux
      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
      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
      Tiago Rangel de Sousa about 2 years
      Sorry, detectIncognito works! I have deleted my message
  • Igor Zevaka
    Igor Zevaka almost 14 years
    That's pretty cool, i didn't realise that incognito mode doesn't highlight visited links. This requires user to click a link though.
  • LaSul
    LaSul almost 14 years
    No it doesn't, the iframe "clicks" the link.
  • Timo Tijhof
    Timo Tijhof over 11 years
    This 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
    oxygen over 11 years
    Recently, it disables all extensions except those extensions which were specifically marked by the user as incognito safe.
  • Tom Teman
    Tom Teman over 8 years
    This is the least hack-ish way and should be at the top. Clean and elegant.
  • Denilson Sá Maia
    Denilson Sá Maia about 8 years
    Official Mozilla article explaining the privacy changes regarding :visited: hacks.mozilla.org/2010/03/…
  • user2718671
    user2718671 about 7 years
    This 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
    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
    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
    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
    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
    Alok about 7 years
    @user2718671 jsfiddle.net/w49x9f1a still works fine for me in latest Chrome on mac osx. weird...
  • user2718671
    user2718671 about 7 years
    @Alok: I think it fails for Safari's Incognito Mode on Iphone 7. Safari - the new Internet Explorer ;)
  • Alexandru R
    Alexandru R about 7 years
    this is not working anymore (maybe it worked in the past)
  • Alexandru R
    Alexandru R about 7 years
    this is not working anymore (maybe it worked in the past)
  • Alok
    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
    aljgom about 7 years
    Just 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
    Lucas Massuh over 6 years
    I tried at Chrome. It works, but the logic is backwards.
  • Jay
    Jay over 6 years
    I 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
    mccambridge over 6 years
    Thinking this is out of date. When I log out the fs instance, I get an instance of webkitRequestFileSystem in both contexts.
  • Ryan
    Ryan about 6 years
    This 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') with resolve(false) if I want isIncognito to be a boolean that is only ever true or false? Thanks.
  • Ryan
    Ryan about 6 years
    I see Syntax Error: await is a reserved word, and I think await always needs to be within an async function. So I think this code doesn't work.
  • aljgom
    aljgom about 6 years
    reject would raise an exception if it is called, and a value would not be returned, so isIncognito would always be true or false 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
    aljgom about 6 years
    Alternatively, 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
    Maykonn almost 6 years
  • tmarois
    tmarois over 5 years
    Does 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
    user2434435 over 5 years
    This is for Chrome ONLY!! so.. do not use it for OTHER browsers
  • blueren
    blueren about 5 years
    This is going to go away soon thanks to these commits
  • Alok
    Alok about 5 years
    Semi-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
    LWC almost 5 years
    Funny enough @Alok - last month Chrome tried to beat your script, but failed!
  • Muhammad Faizan Uddin
    Muhammad Faizan Uddin almost 5 years
    Try running Chrome's incognito mode with disable-web-security flag and the FileSystem API will still work on it
  • LWC
    LWC almost 5 years
    Meanwhile, 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
    LWC almost 5 years
    Chrome 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
    Cruncher over 4 years
    This 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
    Cruncher over 4 years
    This answer is invalidated in chrome 76+
  • Alok
    Alok over 4 years
  • Gitesh Purbia
    Gitesh Purbia over 4 years
    fail in chrome v 77.0.3865.90
  • Jay Momaya
    Jay Momaya about 4 years
    @AmirB if you get any solution please share. Thank You.
  • Amir H. Bagheri
    Amir H. Bagheri almost 4 years
    Not yet. I haven’t found one.
  • Amit
    Amit over 3 years
    const {usage, quota} = await navigator.storage.estimate(); if(quota < 120000000){//Incognito} else {// not Incognito} This thing is still working in latest chrome browser.
  • Pragati Dugar
    Pragati Dugar over 3 years
    This 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
    Alok over 3 years
    try stackoverflow.com/a/57438917/2217509 for more recent Chrome versions.
  • vanisk
    vanisk over 3 years
    It 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
    djdance over 3 years
    Unfortunately, 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
    SRR almost 3 years
    Your fiddle works for me but testing on localhost in incognito tells me that I'm not in incognito
  • Ivan Kuckir
    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
    Matěj Štágl over 2 years
    works with chrome 96. As noted by author the script needs to be loaded server-side