Skip to content

Instantly share code, notes, and snippets.

@aravindanve
Last active May 2, 2025 17:57
Show Gist options
  • Save aravindanve/3e13d995fac35e4a07c236b11cc432c7 to your computer and use it in GitHub Desktop.
Save aravindanve/3e13d995fac35e4a07c236b11cc432c7 to your computer and use it in GitHub Desktop.
Bypass disable-devtool

(Working as of 2025-02-09)

There are websites that use disable-devtool to prevent you from opening or using devtools. They typically prevent you from right clicking or using the keyboard shortcut to open devtools. Even if you successfully do so, they detect it and redirect you elsewhere. You can bypass this by using one of the following ways.

Opening devtools

If the shortcut F12 on Windows or Option + ⌘ + I on Mac do not work. Press the three vertically aligned dots in the top right corner of your Google Chrome or Microsoft Edge window. Under the section "More Tools", you'll see the option to select "Developer Tools" which opens the toolkit in your window.

Once devtools is open, the script may also have debugger statements that may interrupt your browsing experience. You can disable all debugger statements by going to "Sources", and clicking on "Deactivate breakpoints"

Screenshot 2025-02-09 at 3 03 43 PM Screenshot 2025-02-09 at 3 05 10 PM

Bypass external script

When disable-devtool is included as an external script, it can be disabled with a single line of javascript or using an url blocker extension.

  • First try executing this line of javascript from your address bar as suggested here on reddit

    javascript:DisableDevtool.isSuspend = true
    
  • Or you can bypass it by finding the url in the page source, and blocking it using an url blocker extension, as suggested here on reddit

    1. If the website is thewebsite.com, go to view-source:https://thewebsite.com
    2. Find the url for the external script by searching for disable-devtool. It'll typically be
      //cdn.jsdelivr.net/npm/disable-devtool
      
    3. Block the url using ublock or any browser url blocking extension of your choice

Bypass bundled script

If disable-devtool is bundled into the application, the solutions above will not work.

To bypass this, we'll have to modify the bundled script and disable it.

Prerequisites

We are going to make some changes to the script. To do this, we have to enable overriding scripts.

Go to a new tab, and open devtools. In "Sources", under "Overrides" tab, check "Enable Local Overrides" and pick a folder to save the modified scripts locally.

Screenshot 2025-02-09 at 3 18 03 PM

Steps

  1. We'll look for a literal from the source to find it's location in the bundle, I'm going to use already running

    Screenshot 2025-03-10 at 1 20 31 PM
  2. If the website is thewebsite.com, go to view-source:http://thewebsite.com

  3. Search for the string literal already running.

  4. If there is no match, find all included scripts by searching for .js

    Screenshot 2025-02-09 at 2 52 06 PM
  5. Follow the links to the bundled scripts and search within them, you'll usually find them in a script called main or app. I found mine in a script starting with _app-

    Screenshot 2025-03-10 at 1 31 05 PM
  6. Open devtools (there should be no issue here since we are viewing the source, not the actual page). In "Search", find already running again and click on the result

    Screenshot 2025-03-10 at 1 27 19 PM Screenshot 2025-03-10 at 1 37 54 PM
  7. Add a return statement after this line so that the package is never initialized. Make sure to hit save (Ctrl/Cmd + S) after modifying the file

    Screenshot 2025-03-10 at 1 20 00 PM

Now, if you open devtools using the methods described under the opening devtools section, you'll find that disable-devtool has been successfully disabled

@aravindanve
Copy link
Author

aravindanve commented Feb 10, 2025

@lae yes md5 has been proven to be weak, but it would still take you a few minutes to a couple of hours to crack depending on the complexity of the token.

The reason I've gone with code modification is its easier and it’ll still work even if the author upgrades to a more secure hashing algorithm.

@lae
Copy link

lae commented Feb 10, 2025

no, it actually only takes a second to look it up in a table (people are rarely going to ever use anything other than ascii for it), but anyway sure

@aravindanve
Copy link
Author

@lae oh really, I wasn't aware. I tried a reverse lookup on popular md5 databases online, no luck with this hash.

Screenshot 2025-02-09 at 3 27 35 PM

@andysleep
Copy link

I was wondering if disable-devtool could affect Selenium web scraping, even when DevTools is not open?

@aravindanve
Copy link
Author

aravindanve commented Mar 1, 2025

@andysleep I have not tried it on selenium, but I just tired it on puppeteer. It seems to detect it, but not reliably.

Screenshot 2025-03-01 at 1 55 19 PM

Sometimes it detected it instantly, and other times it took a minute. Type 6 is the performance detector that uses console logging performance to detect i.e. the time taken to log large objects:

https://github.com/theajack/disable-devtool/blob/009a3492eb11110addf62dc2782be41e5f656d77/src/utils/enum.ts#L14-L16

https://github.com/theajack/disable-devtool/blob/009a3492eb11110addf62dc2782be41e5f656d77/src/detector/sub-detector/performance.ts#L37-L39

I used puppeteer's await page.on("console", ...) to listen to console events, I'm not sure what happens if the console is not being observed. Without observing the console, it's difficult to say what's happening, as even the screenshots turn up blank. Will need to investigate this further.

@SuiYunsy
Copy link

SuiYunsy commented Mar 9, 2025

https://hideip.network is tough to bypass...

@aravindanve
Copy link
Author

@SuiYunsy not really, it appears to use a simpler library https://github.com/cool-ts/console-ban

Screen.Recording.2025-03-09.at.11.41.36.AM.mov

Just look for this variable name from the source: _debugTime

Screenshot 2025-03-09 at 11 31 32 AM Screenshot 2025-03-09 at 11 38 28 AM

Note that the enclosing class has been transpiled to AA. Find and comment out these two lines that initialize the console ban:

Screenshot 2025-03-09 at 11 44 58 AM Screenshot 2025-03-09 at 11 39 50 AM

@SuiYunsy
Copy link

SuiYunsy commented Mar 9, 2025

Ty, I thought it bundled the disable-devtool so I spent time searching for the wrong keywords.

@itzzzme
Copy link

itzzzme commented Mar 13, 2025

I was debugging the disable-devtool bundled script and apparently wrote a script which seems to be working fine.

Steps

  1. Install tampermonkey in your browser
  2. According to your browser whether it's firefox or chrome paste the script accordingly as given below
  3. Make sure to disable the script after you are done with debugging the website otherwise it may cause redirection issue in some other websites.

Script for chrome (In case even after loading the script into tampermonkey it redirects you just enable responsive mode in chrome and choose any mobile device's resolution and it should work)

// ==UserScript==
// @name         Bypass devtool-detection
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  Bypasses devtool detection
// @author       itzzzme
// @match        *://*/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // --- Override Window Dimension Properties ---
    Object.defineProperty(window, 'outerWidth', {
        get: function() { return window.innerWidth; }
    });
    Object.defineProperty(window, 'outerHeight', {
        get: function() { return window.innerHeight; }
    });

    const originalSetInterval = window.setInterval;
    window.setInterval = function(callback, delay) {
        if (typeof callback === 'function' && typeof delay === 'number' && delay <= 2000) {
            console.log(`Blocked setInterval with delay ${delay}ms`);
            return originalSetInterval(function() {}, delay); // No-op callback
        }
        return originalSetInterval.apply(this, arguments);
    };

    const originalSetTimeout = window.setTimeout;
    window.setTimeout = function(callback, delay) {
        if (typeof callback === 'function' && typeof delay === 'number' && delay <= 2000) {
            console.log(`Blocked setTimeout with delay ${delay}ms`);
            return originalSetTimeout(function() {}, delay);
        }
        return originalSetTimeout.apply(this, arguments);
    };

    // --- Block or override resize events ---
    const originalAddEventListener = window.addEventListener;
    window.addEventListener = function(type, listener, options) {
        if (type === 'resize') {
            console.log('Blocked resize event listener');
            return;
        }
        return originalAddEventListener.apply(this, arguments);
    };
    window.onresize = function() {
        console.log('Blocked onresize event');
    };

    // --- Prevent Forced Reloads ---
    window.location.reload = function() {
        console.log('Reload attempt blocked');
    };


    const originalConsole = window.console;
    window.console = {
        log: function() {},
        warn: function() {},
        error: function() {},
        table: function() {},
        clear: function() {},
        ...originalConsole
    };

    const originalRegExpToString = RegExp.prototype.toString;
    RegExp.prototype.toString = function() {
        try {
            return originalRegExpToString.call(this);
        } catch (e) {
            return '';
        }
    };

    const originalDefineProperty = Object.defineProperty;
    Object.defineProperty = function(obj, prop, descriptor) {
        if (prop === 'id' && obj instanceof HTMLElement && descriptor.get) {
            console.log('Blocked suspicious id getter on element');
            return originalDefineProperty(obj, prop, { value: 'bypassed-id' });
        }
        return originalDefineProperty.apply(this, arguments);
    };

    console.log('Bypass for disable-devtool initialized');
})();

Sciript for Firefox (In case even after loading the script into tampermonkey it redirects you just enable responsive mode in firefox and choose any mobile device's resolution and it should work)

// ==UserScript==
// @name         Bypass devtool-detection
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  Bypasses devtool detection
// @author       itzzzme
// @match        *://*/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // Store original functions
    const originalSetInterval = window.setInterval;
    const originalAddEventListener = window.addEventListener;
    const originalConsole = window.console;

    // Override setInterval to block detection intervals
    window.setInterval = function(callback, delay) {
        // If the callback is a function and delay is a typical detection value, neutralize it
        if (typeof callback === 'function' && typeof delay === 'number' && delay <= 2000) {
            console.log(`Blocked setInterval with delay ${delay}ms`);
            return originalSetInterval(function() {}, delay); // Return a no-op interval
        }
        return originalSetInterval.apply(this, arguments);
    };

    // Override addEventListener to block resize listeners
    window.addEventListener = function(type, listener, options) {
        if (type === 'resize') {
            console.log('Blocked resize event listener');
            return; // Do nothing
        }
        return originalAddEventListener.apply(this, arguments);
    };

    // Neutralize console methods to prevent timing-based detection
    window.console = {
        log: function() {},
        table: function() {},
        warn: function() {},
        clear: function() {},
        ...originalConsole
    };

    // Prevent RegExp toString traps
    const originalRegExpToString = RegExp.prototype.toString;
    RegExp.prototype.toString = function() {
        try {
            return originalRegExpToString.call(this);
        } catch (e) {
            return '';
        }
    };

    // Prevent DOM element getter traps (e.g., DefineId)
    const originalDefineProperty = Object.defineProperty;
    Object.defineProperty = function(obj, prop, descriptor) {
        if (prop === 'id' && obj instanceof HTMLElement && descriptor.get) {
            console.log('Blocked suspicious id getter on element');
            return originalDefineProperty(obj, prop, { value: 'bypassed-id' });
        }
        return originalDefineProperty.apply(this, arguments);
    };

    // Remove disable-devtool-auto attribute as early as possible
    document.addEventListener('DOMContentLoaded', function() {
        const elements = document.querySelectorAll('[disable-devtool-auto]');
        elements.forEach(el => {
            el.removeAttribute('disable-devtool-auto');
            console.log('Removed disable-devtool-auto attribute');
        });
    });

    Object.defineProperty(window.location, 'href', {
        set: function(value) {
            console.log(`Blocked location.href redirect to ${value}`);
            // Do nothing
        }
    });

    console.log('Devtool detection bypass initialized');
})();

let me know if it works

@boimeiji
Copy link

@itzzzme Thanks... it works, but the script makes websites like google translate broken, when you enter or start a new line, the previous text is lost and google translate doesn't translate anything. i use chrome

@itzzzme
Copy link

itzzzme commented Mar 26, 2025

@boimeiji Yes the script do somethings forcefullly so it may break something here and there. It's only made for debugging purposes so after you are done debugging it will be good if you disable the script and reload the page and everything will get back to normal

@peres07
Copy link

peres07 commented Apr 28, 2025

This worked for this, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment