Descubra se o console do Chrome está aberto

141

Estou usando este pequeno script para descobrir se o Firebug está aberto:

if (window.console && window.console.firebug) {
    //is open
};

E isso funciona bem. Agora, eu estava procurando por meia hora para encontrar uma maneira de detectar se o console do desenvolvedor da Web incorporado do Google Chrome está aberto, mas não consegui encontrar nenhuma dica.

Este:

if (window.console && window.console.chrome) {
    //is open
};

não funciona

EDITAR:

Portanto, parece que não é possível detectar se o console do Chrome está aberto. Mas existe um " hack " que funciona, com algumas desvantagens:

  • não funcionará quando o console estiver desencaixado
  • não funcionará quando o console estiver aberto no carregamento da página

Então, eu vou escolher a resposta de Unsigned por enquanto, mas se alguém1 tiver uma idéia brilhante, ele poderá responder e eu altero a resposta selecionada! Obrigado!

r0skar
fonte
A solução na resposta parece funcionar, no entanto, apenas se o console estiver encaixado. Também não funciona se o console já estiver aberto no carregamento da página, enquanto o script Firebug não apresenta esses problemas e parece sempre funcionar. Mas eu posso viver com isso por enquanto! Muito obrigado @pimvdb !! De qualquer forma, manterei a pergunta em aberto para talvez encontrar uma maneira semelhante ao script do Firebug, que sempre funcione.
r0skar
Eu tenho tentado coisas como lançar um erro e ver se .messageé buscado (o que acontece quando o depurador é aberto porque você vê a mensagem), mas infelizmente isso também acontece quando o depurador não é aberto. Eu gostaria de saber um truque para isso, se ela existe ...
pimvdb
4
@ Spudley Não é relevante para a pergunta por que eu preciso disso e não quero começar a explicar. Eu sei que não há como impedir que some1 depure, mas não é isso que estou tentando fazer. Estou apenas tentando descobrir uma maneira de saber se o console está aberto ou não. Isso é tudo :)
r0skar 18/10/11
1
JFYI método console.profiles foi removido da consola API recentemente src.chromium.org/viewvc/blink?view=revision&revision=151136
loislo

Respostas:

97

requestAnimationFrame (final de 2019)

Deixando aqui as respostas anteriores para o contexto histórico. Atualmente, a abordagem de Muhammad Umer funciona no Chrome 78, com a vantagem adicional de detectar eventos próximos e abertos.

função toString (2019)

Os nossos agradecimentos ao comentário de Overcl9ck nesta resposta. Substituir o regex /./por um objeto de função vazio ainda funciona.

var devtools = function() {};
devtools.toString = function() {
  if (!this.opened) {
    alert("Opened");
  }
  this.opened = true;
}

console.log('%c', devtools);
// devtools.opened will become true if/when the console is opened

regex toString (2017-2018)

Como o solicitante original parece não estar mais por perto e esta ainda é a resposta aceita, adicionando esta solução para visibilidade. O crédito vai para o comentário de Antonin Hildebrand sobre a resposta de zswang . Esta solução tira proveito do fato de que não é chamado em objetos registrados, a menos que o console esteja aberto.toString()

var devtools = /./;
devtools.toString = function() {
  if (!this.opened) {
    alert("Opened");
  }
  this.opened = true;
}

console.log('%c', devtools);
// devtools.opened will become true if/when the console is opened

console.profiles (2013)

Atualização: console.profiles foi removida do Chrome. Esta solução não funciona mais.

Agradecemos a Paul Irish por apontar esta solução no Discover DevTools , usando o criador de perfil:

function isInspectOpen() {
  console.profile();
  console.profileEnd();
  if (console.clear) {
    console.clear();
  }
  return console.profiles.length > 0;
}
function showIfInspectIsOpen() {
  alert(isInspectOpen());
}
<button onClick="showIfInspectIsOpen()">Is it open?</button>

window.innerHeight (2011)

Essa outra opção pode detectar a abertura do inspetor encaixado , após o carregamento da página, mas não será possível detectar um inspetor desencaixado ou se o inspetor já estava aberto no carregamento da página. Também existe algum potencial para falsos positivos.

window.onresize = function() {
  if ((window.outerHeight - window.innerHeight) > 100) {
    alert('Docked inspector was opened');
  }
}

Não assinado
fonte
1
Obtendo TypeError: Não é possível ler a propriedade 'length' de undefined em isInspectOpen ()
sandeep
2
Há um novo novos melhores vias (créditos: @zswang): stackoverflow.com/questions/7798748/...
Vicky Chijwani
3
a solução de 'toString (2017)' não funciona no chrome
Richard Chan
2
toString parece ter sido corrigido no chrome. Editar. Na verdade, ele funciona se você usar um function() {}em vez de um regex
Overcl9ck
1
@ Overcl9ck, sua solução estava funcionando até a atualização mais recente do Chrome 77. Você pode nos indicar a direção certa para uma solução alternativa?
Agustin Haller
118

Chrome 65+ (2018)

r = /./
r.toString = function () {
    document.title = '1'
}
console.log('%c', r);

demo: https://jsbin.com/cecuzeb/edit?output (atualização em 16/03/2018)

pacote: https://github.com/zswang/jdetects


Ao imprimir as ferramentas de desenvolvedor do Chrome "Element", ele recebe seu ID

var checkStatus;

var element = document.createElement('any');
element.__defineGetter__('id', function() {
    checkStatus = 'on';
});

setInterval(function() {
    checkStatus = 'off';
    console.log(element);
    console.clear();
}, 1000);

Outra versão (dos comentários)

var element = new Image();
Object.defineProperty(element, 'id', {
  get: function () {
    /* TODO */
    alert('囧');
  }
});
console.log('%cHello', element);

Imprima uma variável regular:

var r = /./;
r.toString = function() {
  document.title = 'on';
};
console.log(r);
zswang
fonte
3
Ótima resposta. Uma coisa a acrescentar ... A MDN diz que __defineGetter__está obsoleta, então mudei para Object.defineProperty(element, 'id', {get:function() {checkStatus='on';}});... ainda funcionando.
Denikov 7/03/16
5
Além disso, o console 'lerá' o elemento assim que o console for aberto, para que você possa imprimir apenas uma vez e aguardar a execução da função no getter, em vez de definir umsetInterval
xpy
8
Com base nessa descoberta, consegui encontrar um método menos intrusivo. O DevTools chama toString () em funções ao imprimi-las no console. Portanto, pode-se imprimir um objeto de função personalizado com o método toString () substituindo o retorno da string vazia. Além disso, você pode usar a string de formatação do console% ce definir a cor: transparent para garantir que o texto potencialmente impresso seja impresso como invisível. Eu usei essa técnica aqui: github.com/binaryage/cljs-devtools/blob/…
Antonin Hildebrand
3
Ano de 2017 aqui. O Chrome ainda grava coisas no console sem que você o abra. E seu hack não funciona mais.
precisa saber é
2
Testado no firefox não funciona com o Elemento de Inspeção (Q) e o Elemento de Inspeção com o firebug
Asif Ashraf 17/17
27

Corte muito confiável

Defina basicamente um getter na propriedade e faça logon no console. Aparentemente, a coisa só é acessada quando o console está aberto.

https://jsfiddle.net/gcdfs3oo/44/

var checkStatus;

var element = new Image();
Object.defineProperty(element, 'id', {
  get: function() {
    checkStatus='on';
    throw new Error("Dev tools checker");
  }
});

requestAnimationFrame(function check() {
  checkStatus = 'off';
  console.dir(element);
  document.querySelector('#devtool-status').className  = checkStatus;
  requestAnimationFrame(check);
});
.on{
  color:limegreen;
}

.off{
  color:red;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.css" integrity="sha256-DVK12s61Wqwmj3XI0zZ9MFFmnNH8puF/eRHTB4ftKwk=" crossorigin="anonymous" />

<p>
  <ul>
    <li>
      dev toolbar open: icon is <span class="on">green</span>
    </li>
    <li>
      dev toolbar closed: icon is <span class="off">red</span>
    </li>
  </ul>
</p>
<div id="devtool-status"><i class="fas fa-7x fa-power-off"></i></div>
<br/>
<p><b>Now press F12 to see if this works for your browser!</b></p>

Muhammad Umer
fonte
Chrome versão 79 ✅
Legends
4
Para que serve throw new Error("Dev tools checker");? Porque funciona sem ele.
Legends
isso parece enviar spam ao console (quando aberto)? que eu suponho que começará a consumir quantidades significativas de memória depois de alguns dias :)
pythonator 06/07
24

Criei o devtools-detect que detecta quando o DevTools está aberto:

console.log('is DevTools open?', window.devtools.open);

Você também pode ouvir um evento:

window.addEventListener('devtoolschange', function (e) {
    console.log('is DevTools open?', e.detail.open);
});

Não funciona quando o DevTools está desencaixado. No entanto, funciona com o DevTools do Chrome / Safari / Firefox e o Firebug.

Sindre Sorhus
fonte
@barbushin Acho que o seu devtool aberto está ancorado, ele não consegue detectar uma janela separada.
Mithril
15

Encontrei uma maneira de saber se o Chrome Console está aberto ou não. Ainda é um truque, mas é muito mais preciso e funcionará quando o console estiver desencaixado ou não.

Basicamente, a execução desse código com o console fechado leva cerca de ~ 100 microssegundos e, enquanto o console é aberto, leva cerca de duas vezes mais ~ 200 microssegundos.

console.log(1);
console.clear();

(1 milissegundo = 1000 microssegundos)

Eu escrevi mais sobre isso aqui .

A demonstração está aqui .


Atualizar:

@zswang encontrou a melhor solução atual - confira sua resposta

guya
fonte
1
É uma solução muito errada. Pesquise no Google -> "Race Hazard". Computador mais lento ou mais rápido e ...?
18C
1
"Risco de corrida" não está relacionado aqui. Sempre há uma relativa lentidão quando o console é aberto.
Guya
1
Lentidão relativa, mas nem sempre 100 ou 200ms. Assim, risco de corrida. Btw. Se você jogar um jogo ao mesmo tempo, esta "solução" retornará resultado falso positivo.
18C
8

Se seu objetivo é bloquear as ferramentas do desenvolvedor, tente isso (eu achei uma versão mais complicada em um local onde o código JS estava ofuscado, é muito irritante):

setTimeout(function() {while (true) {eval("debugger");}}, 0);
Robert Moore
fonte
O usuário pode, no Chrome, desativar a escuta do depurador.
Jack Giffin
3

Existe uma maneira complicada de verificar extensões com a permissão 'tabs':

chrome.tabs.query({url:'chrome-devtools://*/*'}, function(tabs){
    if (tabs.length > 0){
        //devtools is open
    }
});

Além disso, você pode verificar se está aberto para sua página:

chrome.tabs.query({
    url: 'chrome-devtools://*/*',
    title: '*example.com/your/page*'
}, function(tabs){ ... })
Norlin
fonte
3

Eu escrevi um post sobre isso: http://nepjua.org/check-if-browser-console-is-open/

Ele pode detectar se está encaixado ou desencaixado

function isConsoleOpen() {  
  var startTime = new Date();
  debugger;
  var endTime = new Date();

  return endTime - startTime > 100;
}

$(function() {
  $(window).resize(function() {
    if(isConsoleOpen()) {
        alert("You're one sneaky dude, aren't you ?")
    }
  });
});
nepjua
fonte
3
Isso é legal, mas a página ficará obsoleta e nenhuma mensagem será exibida até que o usuário clique no botão Continuar. Será altamente intrusivo para o usuário.
Guya
2
Próxima solução "Race Hazard". Muito errado. Entre. O comando "debugger" pode ser desativado.
18C
3
var div = document.createElement('div');
Object.defineProperty(div,'id',{get:function(){
    document.title = 'xxxxxx'
}});

setTimeout(()=>console.log(div),3000)
Huu Chen
fonte
Não deu certo. E o link para test onlinenão funcionou.
Samuel
2

As ferramentas de desenvolvedor do Chrome são realmente apenas uma parte da biblioteca WebCore do WebKit. Portanto, esta pergunta se aplica ao Safari, Chrome e outros consumidores da WebCore.

Se existir uma solução, ela será baseada na diferença no DOM quando o inspetor da Web WebKit estiver aberto e fechado. Infelizmente, esse é um tipo de problema de galinha e ovo, porque não podemos usar o inspetor para observar o DOM quando o inspetor está fechado.

O que você pode fazer é escrever um pouco de JavaScript para despejar toda a árvore do DOM. Em seguida, execute-o uma vez quando o inspetor estiver aberto e uma vez quando o inspetor estiver fechado. Qualquer diferença no DOM provavelmente é um efeito colateral do inspetor da web, e podemos usá-lo para testar se o usuário está inspecionando ou não.

Esse link é um bom começo para um script de dumping do DOM, mas você deseja despejar o DOMWindowobjeto inteiro , não apenas document.

Atualizar:

Parece que há uma maneira de fazer isso agora. Confira o Chrome Inspector Detector

Pepsi
fonte
Chrome Inspector Detector já não trabalha para o Google Chrome como mencionado pelo desenvolvedor
Angelo
1

Além disso, você pode tentar o seguinte: https://github.com/sindresorhus/devtools-detect

// check if it's open
console.log('is DevTools open?', window.devtools.open);
// check it's orientation, null if not open
console.log('and DevTools orientation?', window.devtools.orientation);

// get notified when it's opened/closed or orientation changes
window.addEventListener('devtoolschange', function (e) {
    console.log('is DevTools open?', e.detail.open);
    console.log('and DevTools orientation?', e.detail.orientation);
});
Vladimir Ishenko
fonte
1
Não funciona bem. Se um usuário estiver em um dispositivo móvel, eles girarão o dispositivo em 90 graus e a tela será redimensionada.
Jack Giffin
obras em cromo e ff não IE ou borda como de 2019/04/05
Solid Snake
0

Se você é desenvolvedor que faz coisas durante o desenvolvimento. Confira esta extensão do Chrome. Ajuda a detectar quando o Chrome Devtoos é aberto ou fechado.

https://chrome.google.com/webstore/detail/devtools-status-detector/pmbbjdhohceladenbdjjoejcanjijoaa?authuser=1

Esta extensão ajuda os desenvolvedores de Javascript a detectar quando o Chrome Devtools está aberto ou fechado na página atual. Quando o Chrome Devtools fecha / abre, a extensão gera um evento chamado 'devtoolsStatusChanged' no elemento window.document.

Este é um código de exemplo:

 function addEventListener(el, eventName, handler) {
    if (el.addEventListener) {
        el.addEventListener(eventName, handler);
    } else {
        el.attachEvent('on' + eventName,
            function() {
                handler.call(el);
            });
    }
}


// Add an event listener.
addEventListener(document, 'devtoolsStatusChanged', function(e) {
    if (e.detail === 'OPENED') {
        // Your code when Devtools opens
    } else {
        // Your code when Devtools Closed
    }
});
vothaison
fonte
0

Algumas respostas aqui param de funcionar no Chrome 65. Aqui está uma alternativa de ataque de tempo que funciona de maneira bastante confiável no Chrome e é muito mais difícil de mitigar do que o toString()método. Infelizmente, não é tão confiável no Firefox.

addEventListener("load", () => {

var baseline_measurements = [];
var measurements = 20;
var warmup_runs = 3;

const status = document.documentElement.appendChild(document.createTextNode("DevTools are closed"));
const junk = document.documentElement.insertBefore(document.createElement("div"), document.body);
junk.style.display = "none";
const junk_filler = new Array(1000).join("junk");
const fill_junk = () => {
  var i = 10000;
  while (i--) {
    junk.appendChild(document.createTextNode(junk_filler));
  }
};
const measure = () => {
    if (measurements) {
    const baseline_start = performance.now();
    fill_junk();
    baseline_measurements.push(performance.now() - baseline_start);
    junk.textContent = "";
    measurements--;
    setTimeout(measure, 0);
  } else {
    baseline_measurements = baseline_measurements.slice(warmup_runs); // exclude unoptimized runs
    const baseline = baseline_measurements.reduce((sum, el) => sum + el, 0) / baseline_measurements.length;

    setInterval(() => {
      const start = performance.now();
      fill_junk();
      const time = performance.now() - start;
      // in actual usage you would also check document.hasFocus()
      // as background tabs are throttled and get false positives
      status.data = "DevTools are " + (time > 1.77 * baseline ? "open" : "closed");
      junk.textContent = "";
    }, 1000);
  }
};

setTimeout(measure, 300);

});
Eli Gray
fonte
0

Quanto ao Chrome / 77.0.3865.75, uma versão do 2019 não funciona. toString chama imediatamente sem a abertura do Inspetor.

const resultEl = document.getElementById('result')
const detector = function () {}

detector.toString = function () {
	resultEl.innerText = 'Triggered'
}

console.log('%c', detector)
<div id="result">Not detected</div>

korzhyk
fonte
0

A abordagem de Muhammad Umer funcionou para mim, e eu estou usando o React, então decidi fazer uma solução de ganchos:

const useConsoleOpen = () => {
  const [consoleOpen, setConsoleOpen] = useState(true)

  useEffect(() => {
    var checkStatus;

    var element = new Image();
    Object.defineProperty(element, "id", {
      get: function () {
        checkStatus = true;
        throw new Error("Dev tools checker");
      },
    });

    requestAnimationFrame(function check() {
      checkStatus = false;
      console.dir(element); //Don't delete this line!
      setConsoleOpen(checkStatus)
      requestAnimationFrame(check);
    });
  }, []);

  return consoleOpen
}

NOTA: Quando eu estava mexendo com isso, não funcionou por muito tempo e não consegui descobrir o porquê. Eu havia excluído, o console.dir(element);que é fundamental para como ele funciona. Excluo a maioria das ações não descritivas do console, pois elas ocupam espaço e geralmente não são necessárias para a função, por isso não funcionou para mim.

Para usá-lo:

import React from 'react'

const App = () => {
  const consoleOpen = useConsoleOpen()

  return (
    <div className="App">
      <h1>{"Console is " + (consoleOpen ? "Open" : "Closed")}</h1>
    </div>
  );
}

Espero que isso ajude quem usa o React. Se alguém quiser expandir isso, eu gostaria de poder parar o loop infinito em algum momento (já que não uso isso em todos os componentes) e encontrar uma maneira de manter o console limpo.

Luke Redmore
fonte