¿Puedes determinar si Chrome está en modo incógnito mediante un script?

114

¿Es posible determinar si Google Chrome está en modo incógnito mediante un script?

Editar: en realidad quise decir si es posible a través de un script de usuario, pero las respuestas asumen que JavaScript se está ejecutando en una página web. He vuelto a hacer la pregunta aquí con respecto a los scripts de usuario.

RodeoPayaso
fuente
28
No sería mucho incognitosi pudiera determinarlo fácilmente :)
Aren
Y hay que recordar que el usuario debe permitir el modo incógnito para el manual de la extensión. Por defecto, todo es cierto.
Mohamed Mansour
@Mohamed: El usuario que tenga que permitirlo sería yo, así que no será un problema :)
RodeoClown
1
@PeteAlvin O el sitio podría restar valor al detectar de incógnito. El sitio de Boston Globe no mostrará sus artículos en modo incógnito, lo que evitará que el usuario eluda su cuota de artículos gratuitos. En general, prefiero un sitio que sepa menos sobre mí.
JohnC

Respuestas:

232

Si. La API FileSystem está deshabilitada en modo incógnito. Consulte https://jsfiddle.net/w49x9f1a/ cuando esté y no esté en modo incógnito.

Código de muestra:

    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"));
    }

Alok
fuente
19
Esta es la forma menos pirateada y debería estar en la parte superior. Limpio y elegante.
Tom Teman
1
@ user2718671 jsfiddle.net/w49x9f1a todavía funciona bien para mí en la última versión de Chrome en mac osx. raro ...
Alok
1
Probé en Chrome. Funciona, pero la lógica está al revés.
Lucas Massuh
9
Esto desaparecerá pronto gracias a estas confirmaciones
blueren
8
falla en Chrome v 77.0.3865.90
Gitesh Purbia
18

Una forma es visitar una URL única y luego verificar si un enlace a esa URL es tratado como visitado por CSS.

Puede ver un ejemplo de esto en "Detección de incógnito" (enlace muerto) .

Artículo de investigación del mismo autor para reemplazar el enlace Detecting Incognito anterior

En main.htmlagregar un iframe,

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

y algo de código 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 = '';
}

Luego, en test.htmleso se cargan en el 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> 

NOTA: intentar esto desde el sistema de archivos puede hacer que Chrome llore por "Javascript no seguro". Sin embargo, funcionará sirviendo desde un servidor web.

JHurrah
fuente
Eso es muy bueno, no me di cuenta de que el modo incógnito no resalta los enlaces visitados. Sin embargo, esto requiere que el usuario haga clic en un enlace.
Igor Zevaka
1
No, no es así, el iframe "hace clic" en el enlace.
kibibu
40
En realidad, esto no funciona ya que la mayoría de los navegadores no exponen: información de estilo visitado a través de javascript. La interfaz CSS dirá como si el enlace tuviera el color no visitado. Esta es una medida de seguridad que ha estado en los navegadores WebKit y Gecko al menos desde 2010. Esto era para proteger el historial del usuario (por ejemplo, uno podría probar todas las URL posibles y enviar las visitadas a un tercero. De esta manera, se podría obtener acceso a tokens en URL y qué no).
Timo Tijhof
2
Artículo oficial de Mozilla que explica los cambios de privacidad relacionados con :visited: hacks.mozilla.org/2010/03/…
Denilson Sá Maia
18

En Chrome 74+, puede determinar esto estimando el espacio de almacenamiento disponible en el sistema de archivos

Ver el 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')
}
Vinnie James
fuente
4
Esta es la respuesta correcta ahora. O la respuesta aceptada debe actualizarse con esto, o la respuesta aceptada debe cambiar. No quitarle la respuesta originalmente aceptada, ya que era la solución correcta en ese momento.
Cruncher
8

Puede, en JavaScript, ver la respuesta de JHurrah . Excepto por no resaltar enlaces, el modo incógnito no guarda el historial de navegación ni las cookies. Desde la página de ayuda de Google :

  • Las páginas web que abre y los archivos descargados mientras está en modo incógnito no se registran en sus historiales de navegación y descarga.
  • Todas las cookies nuevas se eliminan después de cerrar todas las ventanas de incógnito que ha abierto.

Como puede ver, las diferencias entre la navegación normal y la navegación de incógnito ocurren después de visitar la página web, por lo tanto, no hay nada que el navegador se comunique con el servidor cuando está en este modo.

Puede ver qué envía exactamente su navegador al servidor utilizando uno de los muchos analizadores de solicitudes HTTP, como este aquí . Compare los encabezados entre sesión normal e incógnito y no verá ninguna diferencia.

Igor Zevaka
fuente
Recientemente, deshabilita todas las extensiones excepto aquellas que fueron marcadas específicamente por el usuario como seguras de incógnito.
Tiberiu-Ionuț Stan
4

Si está desarrollando una extensión, puede usar la API de pestañas para determinar si se trata de una ventana / pestaña de incógnito.

Puede encontrar más información aquí .

Si solo está trabajando con una página web, no es fácil y está diseñado para ser así. Sin embargo, he notado que todos los intentos de abrir una base de datos (window.database) fallan cuando están en incongnito, esto se debe a que cuando están en incógnito no se permite dejar rastro de datos en la máquina del usuario.

No lo he probado, pero sospecho que todas las llamadas a localStorage también fallan.

Kinlan
fuente
3

Esto usa una promesa de esperar a que el código asincrónico establezca una bandera, por lo que podemos usarlo sincrónicamente después.

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));      
});

entonces podemos hacer

if(isIncognito) alert('in incognito');
else alert('not in incognito');
Aljgom
fuente
Esto parece muy interesante y es una forma de Javascript con la que no estoy familiarizado y parece que mi Netbeans 8.2 IDE no es compatible con Windows 10. Pero si puedo hacer que funcione, también tengo curiosidad: ¿podría reemplazarlo reject('Check incognito failed')con resolve(false)si quiero? isIncognitoser un booleano que solo sea verdadero o falso? Gracias.
Ryan
2
Ya veo Syntax Error: await is a reserved word, y creo que awaitsiempre debe estar dentro de una asyncfunción. Entonces creo que este código no funciona.
Ryan
1
rejectgeneraría una excepción si se llama, y ​​no se devolvería un valor, por isIncognitolo que siempre lo sería trueo falsela forma en que se escribe el código. Sin embargo, también podrá usar una 'resolución' allí si desea que se devuelva un valor. ¿Y podría depender de cómo se maneja el entorno en el ámbito global? Funciona en la consola de Chrome en el alcance global, pero puede intentar ajustar todo (async function() { 'everything here' })();para que se ejecute dentro de una función asíncrona
aljgom
2
Alternativamente, puede guardar la promesa en isIncognitolugar del resultado y ejecutarla luego en una función asincrónica: let isIncognito = new Promise( ...etcluego en otro lugar tendría una función como(async function() { if( !(await isIncognito) ) {alert('not incognito') } })();
aljgom
1
Esta respuesta está invalidada en Chrome 76+
Cruncher
0

Función de copiar y pegar rápida basada en la respuesta de Alok (nota: esto es asincrónico)

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, ()=>{});
    }
} 

uso:

ifIncognito(true,  ()=>{ alert('in incognito') });
// or
ifIncognito(false, ()=>{ alert('not in incognito') });
Aljgom
fuente
esto ya no funciona (tal vez funcionó en el pasado)
Alexandru R
2
Acabo de actualizar mi Chrome ahora y todavía funciona. Veo que publicaste lo mismo arriba y luego dijiste que estabas equivocado, solo señalando esto para los futuros espectadores (siéntete libre de eliminar tu comentario, eliminaré este si lo haces).
aljgom
0

Aquí está la respuesta sugerida escrita en sintaxis ES6 y ligeramente limpia.

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)
nikksan
fuente
0

Aquí la solución usando promesas

const isIncognito = () => {
    return new Promise((resolve, reject) => {
      if ("storage" in navigator && "estimate" in navigator.storage) {
        navigator.storage.estimate().then((res) => {
          console.log(`Using ${res.usage} out of ${res.quota} bytes.`);
          if (res.quota < 120000000) {
            resolve(true);
          } else {
            reject(false);
          }
        });
      } else {
        reject(false);
      }
    });
  };

Cómo usarlo:

isIncognito().then(yes => console.log(yes)).catch(isnot => console.log(isnot))
Juan ricardo
fuente
-10

La documentación para el modo incógnito dice específicamente que los sitios web no se comportarán de manera diferente. Creo que esto significa que la respuesta es no.

Perrito
fuente
9
Sé que esta respuesta tiene 4 años, pero recientemente Netflix implementó la función de detección de "incógnito" y eso despertó mi interés en investigar cómo lo logran. Si visita Netflix en modo incógnito, Netflix no le permite reproducir videos.
ILikeTacos
<Chrome> verificado: "Error de modo incógnito Su navegador parece estar en modo incógnito".
Pete Alvin
Creo que esta publicación podría mejorarse porque ciertamente no habla de hechos. Como ya se ha demostrado tanto hacia arriba como hacia abajo a partir de esta respuesta, se puede ver si alguien desea ver si lo visitan desde el modo incógnito o desde un navegador Chrome normal.
FortuneSoldier
@ILikeTacos Sé que tu comentario tiene (más de) cuatro años, pero Chrome rompió intencionalmente su detección de incógnito, así que todavía siento que gané en ese ..
Puppy
@Puppy Bueno, sí. Pero en realidad no mishravikas.com/articles/2019-07/…
Cruncher