Bypass DevTools Detection

Prevent websites from detecting DevTools (Inspect Element) is open

// ==UserScript==
// @name         Bypass DevTools Detection
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Prevent websites from detecting DevTools (Inspect Element) is open
// @author       Serial Desegnation J
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // --- Override debugger to noop ---
    window.debugger = function() {};

    // Spoof Function.prototype.constructor to strip debugger statements from strings
    const originalConstructor = Function.prototype.constructor;
    Function.prototype.constructor = new Proxy(originalConstructor, {
        apply(target, thisArg, args) {
            if (args[0] && typeof args[0] === 'string' && args[0].includes('debugger')) {
                args[0] = args[0].replace(/debugger/g, '');
            }
            return Reflect.apply(target, thisArg, args);
        }
    });

    // Spoof Function.prototype.toString to hide overrides (especially debugger function)
    const originalToString = Function.prototype.toString;
    Function.prototype.toString = new Proxy(originalToString, {
        apply(target, thisArg, args) {
            if (thisArg === window.debugger) {
                return 'function debugger() { [native code] }';
            }
            return Reflect.apply(target, thisArg, args);
        }
    });

    // Override eval to strip debugger statements from any eval'd code
    const originalEval = window.eval;
    window.eval = function(code) {
        if (typeof code === 'string') {
            code = code.replace(/debugger;?/g, '');
        }
        return originalEval(code);
    };

    // Override console methods to disable traps and weird behaviors
    ['log', 'debug', 'error', 'info', 'warn'].forEach(method => {
        const originalMethod = console[method];
        console[method] = function(...args) {
            // Skip logging if args include certain trap images or weird data (optional)
            for (const arg of args) {
                if (arg instanceof Image) return;
            }
            return originalMethod.apply(console, args);
        };
    });

    // Block console.clear to prevent wiping logs
    console.clear = function () {
        console.log('[Tampermonkey] Blocked console.clear()');
    };

    // Spoof window.outerWidth and outerHeight to match inner dimensions (for devtools detection)
    function spoofWindowSize() {
        Object.defineProperty(window, 'outerWidth', {
            get: () => window.innerWidth,
            configurable: true
        });
        Object.defineProperty(window, 'outerHeight', {
            get: () => window.innerHeight,
            configurable: true
        });
    }
    spoofWindowSize();
    // Repeat periodically to counter site attempts to redefine
    setInterval(spoofWindowSize, 1000);

    // Override requestAnimationFrame to fudge timestamps (blocks timing detection)
    const originalRAF = window.requestAnimationFrame;
    window.requestAnimationFrame = function(callback) {
        return originalRAF(function(time) {
            callback(time + 1000);
        });
    };

    // Prevent key combos that open DevTools or View Source
    document.addEventListener('keydown', function(e) {
        if (
            e.key === 'F12' ||
            (e.ctrlKey && e.shiftKey && ['I', 'J', 'C'].includes(e.key.toUpperCase())) ||
            (e.ctrlKey && e.key.toUpperCase() === 'U')
        ) {
            e.stopImmediatePropagation();
            e.preventDefault();
        }
    }, true);

    // Prevent detection via image get traps (used in object inspection)
    const imageProto = Object.getPrototypeOf(new Image());
    if (imageProto) {
        Object.defineProperty(imageProto, 'id', {
            get: function() {
                return null;
            },
            configurable: true
        });
    }

    // Spoof performance navigation type to hide reload detection
    try {
        if (performance.getEntriesByType("navigation")[0].type === "reload") {
            Object.defineProperty(performance, 'getEntriesByType', {
                value: () => [{ type: "navigate" }],
                configurable: true
            });
        }
    } catch (e) {}

    // Spoof navigator.plugins and navigator.languages to look real
    Object.defineProperty(navigator, 'plugins', {
        get: () => [1, 2, 3],
        configurable: true
    });
    Object.defineProperty(navigator, 'languages', {
        get: () => ['en-US', 'en'],
        configurable: true
    });

    // Spoof HTMLElement.prototype.toString to prevent element inspection detection
    const originalGetOwnPropDesc = Object.getOwnPropertyDescriptor;
    Object.getOwnPropertyDescriptor = new Proxy(originalGetOwnPropDesc, {
        apply(target, thisArg, args) {
            if (args[0] === HTMLElement.prototype && args[1] === 'toString') {
                return {
                    configurable: true,
                    enumerable: false,
                    value: () => '[object HTMLElement]'
                };
            }
            return Reflect.apply(target, thisArg, args);
        }
    });

    // Debugging confirmation message
    console.log('[Tampermonkey] DevTools detection blocked (enhanced).');

})();