Find out whether Chrome console is open

I am using this little script to find out whether Firebug is open:

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

And it works well. Now I was searching for half an hour to find a way to detect whether Google Chrome’s built-in web developer console is open, but I couldn’t find any hint.

This:

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

doesn’t work.

EDIT:

So it seems that it is not possible to detect whether the Chrome console is open. But there is a “hack” that works, with some drawbacks:

  • will not work when console is undocked
  • will not work when console is open on page load

So, I am gonna choose Unsigned´s answer for now, but if some1 comes up with a brilliant idea, he is welcome to still answer and I change the selected answer! Thanks!

12 thoughts on “Find out whether Chrome console is open”

  1. There is a tricky way to check it for extensions with ‘tabs’ permission:

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

    Also you can check if it open for your page:

    chrome.tabs.query({
        url: 'chrome-devtools://*/*',
        title: '*example.com/your/page*'
    }, function(tabs){ ... })
    
    Reply
  2. I created devtools-detect which detects when DevTools is open:

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

    You can also listen to an event:

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

    It doesn’t work when DevTools is undocked. However, works with the Chrome/Safari/Firefox DevTools and Firebug.

    Reply
  3. Also you can try this: 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);
    });
    
    Reply
  4. Very Reliable hack

    Basically set a getter on property and log it in console. Apparently the thing gets accessed only when console is open.

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

    var checkStatus;
    var indicator = document.querySelector('#devtool-status');
    
    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);
      indicator.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>
    Reply
  5. Muhammad Umer’s approach worked for me, and I’m using React, so I decided to make a hooks solution:

    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
    }
    

    NOTE: When I was messing with it, it didn’t work for the longest time and I couldn’t figure out why. I had deleted console.dir(element); which is critical to how it works. I delete most non-descriptive console actions since they just take up space and aren’t usually necessary to the function, so that was why it wasn’t working for me.

    To use it:

    import React from 'react'
    
    const App = () => {
      const consoleOpen = useConsoleOpen()
    
      return (
        <div className="App">
          <h1>{"Console is " + (consoleOpen ? "Open" : "Closed")}</h1>
        </div>
      );
    }
    

    I hope this helps anyone using React. If anyone wants to expand on this, I would like to be able stop the infinite loop at some point (since I don’t use this in every component) and to find a way to keep the console clean.

    Reply
  6. If you are developers who are doing stuff during development. Check out this Chrome extension. It helps you detect when Chrome Devtoos is opened or closed.

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

    This extension helps Javascript developers detect when Chrome Devtools is open or closed on current page.
    When Chrome Devtools closes/opens, the extension will raise a event named ‘devtoolsStatusChanged’ on window.document element.

    This is example code:

     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
        }
    });
    
    Reply
  7. If your goal is to jam the developer tools, try this (I found a more complicated version of it at a place where JS code was obfuscated, it’s very annoying):

    setTimeout(function() {while (true) {eval("debugger");}}, 0);
    
    Reply
  8. Some answers here will stop working in Chrome 65. Here’s a timing attack alternative that works pretty reliably in Chrome, and is much harder to mitigate than the toString() method. Unfortunately it’s not that reliable in 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);
    
    });
    
    Reply
  9. var div = document.createElement('div');
    Object.defineProperty(div,'id',{get:function(){
        document.title = 'xxxxxx'
    }});
    
    setTimeout(()=>console.log(div),3000)
    
    
    Reply
  10. As for Chrome/77.0.3865.75 a version of 2019 not works. toString invokes immediately without Inspector opening.

    const resultEl = document.getElementById('result')
    const detector = function () {}
    
    detector.toString = function () {
    	resultEl.innerText = 'Triggered'
    }
    
    console.log('%c', detector)
    <div id="result">Not detected</div>
    Reply

Leave a Comment