no anti-devtools

kills every known method of devtools detection and blocking. window size spoofing, debugger traps, toString getter traps, timing attacks, keyboard/contextmenu blocking, console method abuse, redirect interception, eval-based loops, and more.. anti anti-devtools

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name            no anti-devtools
// @namespace       https://minoa.cat/
// @version         1.1.1
// @description     kills every known method of devtools detection and blocking. window size spoofing, debugger traps, toString getter traps, timing attacks, keyboard/contextmenu blocking, console method abuse, redirect interception, eval-based loops, and more.. anti anti-devtools
// @author          minoa
// @license         MIT
// @homepageURL     https://greasyfork.org/scripts/no-anti-devtools
// @supportURL      https://github.com/M2noa/no-anti-devtools/issues
// @match           *://*/*
// @exclude         *://*.google.com/*
// @exclude         *://*.google.co.uk/*
// @exclude         *://*.google.ca/*
// @exclude         *://*.google.com.au/*
// @exclude         *://*.googleapis.com/*
// @exclude         *://*.gstatic.com/*
// @exclude         *://*.youtube.com/*
// @exclude         *://*.facebook.com/*
// @exclude         *://*.instagram.com/*
// @exclude         *://*.twitter.com/*
// @exclude         *://*.x.com/*
// @exclude         *://*.microsoft.com/*
// @exclude         *://*.live.com/*
// @exclude         *://*.outlook.com/*
// @exclude         *://*.office.com/*
// @exclude         *://*.apple.com/*
// @exclude         *://*.icloud.com/*
// @exclude         *://*.github.com/*
// @exclude         *://*.gitlab.com/*
// @exclude         *://*.paypal.com/*
// @exclude         *://*.stripe.com/*
// @exclude         *://*.amazon.com/*
// @exclude         *://*.twitch.tv/*
// @exclude         *://*.discord.com/*
// @exclude         *://*.cloudflare.com/*
// @grant           unsafeWindow
// @run-at          document-start
// ==/UserScript==

;(function (w) {
  'use strict'

  // --- 0. internal safe logger & native spoofing helper ---
  const _rawConsole = {
    log: w.console && w.console.log ? w.console.log.bind(w.console) : () => {},
    warn: w.console && w.console.warn ? w.console.warn.bind(w.console) : () => {},
    error: w.console && w.console.error ? w.console.error.bind(w.console) : () => {},
  }

  function reportError(section, err) {
    _rawConsole.warn(`[no-anti-devtools] Issue in ${section}:`, err)
  }

  const NATIVE_FN_MAP = new WeakMap()

  function makeNative(fn, name = '') {
    try {
      const str = `function ${name}() { [native code] }`
      NATIVE_FN_MAP.set(fn, str)
      fn.toString = () => str
    } catch (e) {}
    return fn
  }

  // --- domain blocklist (runtime safety net) ---
  const BLOCKED_DOMAINS = [
    // google
    'google.com', 'google.co.uk', 'google.ca', 'google.com.au',
    'googleapis.com', 'gstatic.com', 'accounts.google.com',
    'youtube.com',
    // meta
    'facebook.com', 'instagram.com', 'threads.net',
    // twitter / x
    'twitter.com', 'x.com',
    // microsoft
    'microsoft.com', 'live.com', 'outlook.com', 'office.com',
    'microsoftonline.com', 'azure.com',
    // apple
    'apple.com', 'icloud.com',
    // dev platforms
    'github.com', 'gitlab.com',
    // payments
    'paypal.com', 'stripe.com',
    // shopping
    'amazon.com',
    // social / comms
    'twitch.tv', 'discord.com',
    // infra
    'cloudflare.com',
  ]

  function isBlockedDomain() {
    try {
      const host = w.location.hostname
      return BLOCKED_DOMAINS.some(d => host === d || host.endsWith('.' + d))
    } catch (e) {
      reportError('domain blocklist check', e)
      return false
    }
  }

  if (isBlockedDomain()) return

  const TRAP_PROPS = new Set(['id', 'name', 'stack', 'message', 'nodeName', 'tagName', 'className'])

  // --- 1. window size spoofing ---
  try {
    Object.defineProperty(w, 'outerWidth',  { get: () => w.innerWidth,  configurable: true })
    Object.defineProperty(w, 'outerHeight', { get: () => w.innerHeight, configurable: true })
  } catch (e) {
    reportError('Section 1 (window size spoofing)', e)
  }

  // --- 2. keyboard shortcut unblocking ---
  try {
    const DEVTOOLS_KEYS = new Set(['F12', 'I', 'J', 'C', 'U', 'S', 'K', 'P'])

    function isDevtoolsShortcut(e) {
      if (e.key === 'F12') return true
      if ((e.ctrlKey || e.metaKey) && e.shiftKey && DEVTOOLS_KEYS.has(e.key.toUpperCase())) return true
      if ((e.ctrlKey || e.metaKey) && (e.key === 'u' || e.key === 'U')) return true
      return false
    }

    w.addEventListener('keydown', function (e) {
      if (isDevtoolsShortcut(e)) {
        e.stopImmediatePropagation()
      }
    }, true)
  } catch (e) {
    reportError('Section 2 (keyboard shortcuts)', e)
  }

  // --- 3. context menu unblocking ---
  try {
    w.addEventListener('contextmenu', function (e) {
      e.stopImmediatePropagation()
    }, true)
  } catch (e) {
    reportError('Section 3 (context menu)', e)
  }

  // --- 4. console method protection ---
  try {
    const con = w.console
    const noop = makeNative(() => {}, '')

    con.clear         = noop
    con.profile       = noop
    con.profileEnd    = noop
    con.table         = noop

    const dangerous = ['log', 'dir', 'warn', 'error', 'info', 'debug']
    dangerous.forEach(method => {
      if (!con[method]) return
      const orig = con[method].bind(con)

      const wrapped = function (...args) {
        const safe = args.filter(a => {
          if (a === null || typeof a !== 'object') return true
          try {
            for (const prop of TRAP_PROPS) {
              const desc = Object.getOwnPropertyDescriptor(a, prop)
              if (desc && (typeof desc.get === 'function' || typeof desc.set === 'function')) {
                return false
              }
            }
          } catch (e) {
            return false
          }
          return true
        })
        if (safe.length) orig(...safe)
      }

      makeNative(wrapped, method)
      con[method] = wrapped
    })
  } catch (e) {
    reportError('Section 4 (console protection)', e)
  }

  // --- 5. Object.defineProperty & Object.defineProperties interception ---
  const _defineProperty = Object.defineProperty.bind(Object)
  const _defineProperties = Object.defineProperties ? Object.defineProperties.bind(Object) : null

  function sanitizeDescriptor(obj, prop, descriptor) {
    if (
      descriptor &&
      typeof descriptor.get === 'function' &&
      TRAP_PROPS.has(prop) &&
      obj !== w &&
      obj !== Object.prototype
    ) {
      return Object.assign({}, descriptor, {
        get: () => undefined,
        set: undefined,
      })
    }
    return descriptor
  }

  try {
    const patchedDefineProperty = function defineProperty(obj, prop, descriptor) {
      try {
        descriptor = sanitizeDescriptor(obj, String(prop), descriptor)
      } catch (e) {
        reportError('defineProperty descriptor sanitizer', e)
      }
      return _defineProperty(obj, prop, descriptor)
    }
    makeNative(patchedDefineProperty, 'defineProperty')

    _defineProperty(Object, 'defineProperty', {
      value: patchedDefineProperty,
      writable:     true,
      configurable: true,
      enumerable:   false,
    })
  } catch (e) {
    reportError('Section 5 (defineProperty)', e)
  }

  if (_defineProperties) {
    try {
      const patchedDefineProperties = function defineProperties(obj, props) {
        try {
          if (props && typeof props === 'object') {
            const sanitizedProps = {}
            for (const key of Object.keys(props)) {
              sanitizedProps[key] = sanitizeDescriptor(obj, key, props[key])
            }
            props = sanitizedProps
          }
        } catch (e) {
          reportError('defineProperties descriptor sanitizer', e)
        }
        return _defineProperties(obj, props)
      }
      makeNative(patchedDefineProperties, 'defineProperties')

      _defineProperty(Object, 'defineProperties', {
        value: patchedDefineProperties,
        writable:     true,
        configurable: true,
        enumerable:   false,
      })
    } catch (e) {
      reportError('Section 5 (defineProperties)', e)
    }
  }

  // --- 6. debugger trap neutralization ---
  const _eval     = w.eval
  const _Function = w.Function
  const debuggerOnlyRe = /^\s*debugger\s*;?\s*$/

  try {
    w.eval = function safeEval(code) {
      if (typeof code === 'string' && debuggerOnlyRe.test(code)) return undefined
      return _eval.call(w, code)
    }
    makeNative(w.eval, 'eval')
  } catch (e) {
    reportError('Section 6 (eval wrapper)', e)
  }

  try {
    w.Function = function safeFunction(...args) {
      const body = args[args.length - 1]
      if (typeof body === 'string') {
        args[args.length - 1] = body.replace(/\bdebugger\b/g, '')
      }
      return _Function(...args)
    }
    Object.setPrototypeOf(w.Function, _Function)
    w.Function.prototype = _Function.prototype
    makeNative(w.Function, 'Function')
  } catch (e) {
    reportError('Section 6 (Function wrapper)', e)
  }

  // --- 7. setInterval / setTimeout detection loop killing ---
  const _setInterval = w.setInterval
  const _setTimeout  = w.setTimeout

  const DETECTION_SIGS = [
    'debugger',
    'outerWidth', 'outerHeight',
    'devtools', 'DevTools',
    'firebug', 'Firebug',
    'console.profile', 'profileEnd',
    'performance.now',
    'DisableDevtool', 'disable-devtool',
  ]

  function looksLikeDetection(fn) {
    if (typeof fn !== 'function') return false
    try {
      const src = _Function.prototype.toString.call(fn)
      return DETECTION_SIGS.some(sig => src.includes(sig))
    } catch (e) {
      return false
    }
  }

  try {
    w.setInterval = function safeSetInterval(fn, delay, ...rest) {
      if (looksLikeDetection(fn)) {
        return _setInterval(() => {}, 99999999)
      }
      return _setInterval(fn, delay, ...rest)
    }
    makeNative(w.setInterval, 'setInterval')
  } catch (e) {
    reportError('Section 7 (setInterval)', e)
  }

  try {
    w.setTimeout = function safeSetTimeout(fn, delay, ...rest) {
      if (looksLikeDetection(fn)) {
        return _setTimeout(() => {}, 99999999)
      }
      return _setTimeout(fn, delay, ...rest)
    }
    makeNative(w.setTimeout, 'setTimeout')
  } catch (e) {
    reportError('Section 7 (setTimeout)', e)
  }

  // --- 8. location / navigation redirect interception ---
  const _reload  = w.location.reload.bind(w.location)
  const _replace = w.location.replace.bind(w.location)
  const ERROR_PAGE_RE = /(?:404|blocked|disabled|error|403|detect|devtool|acellus\.com)/i

  try {
    Object.defineProperty(w.location, 'reload', {
      get: () => function safeReload() {
        if (w.navigator.userActivation && w.navigator.userActivation.isActive) {
          _reload()
        }
      },
      configurable: true,
    })
  } catch (e) {
    reportError('Section 8 (location.reload)', e)
  }

  try {
    Object.defineProperty(w.location, 'replace', {
      get: () => function safeReplace(url) {
        if (typeof url === 'string' && ERROR_PAGE_RE.test(url)) return
        _replace(url)
      },
      configurable: true,
    })
  } catch (e) {
    reportError('Section 8 (location.replace)', e)
  }

  try {
    const _docWrite = document.write.bind(document)
    document.write = function safeWrite(...args) {
      if (document.readyState === 'loading') return _docWrite(...args)
    }
    makeNative(document.write, 'write')
  } catch (e) {
    reportError('Section 8 (document.write)', e)
  }

  // --- 9. alert / confirm / prompt neutralization ---
  const ALERT_BLOCK_RE = /devtools?|inspect|developer\s*tools?|f12|debug/i
  const _alert   = w.alert.bind(w)
  const _confirm = w.confirm.bind(w)

  try {
    w.alert = function safeAlert(msg) {
      if (typeof msg === 'string' && ALERT_BLOCK_RE.test(msg)) return
      _alert(msg)
    }
    makeNative(w.alert, 'alert')
  } catch (e) {
    reportError('Section 9 (alert)', e)
  }

  try {
    w.confirm = function safeConfirm(msg) {
      if (typeof msg === 'string' && ALERT_BLOCK_RE.test(msg)) return true
      return _confirm(msg)
    }
    makeNative(w.confirm, 'confirm')
  } catch (e) {
    reportError('Section 9 (confirm)', e)
  }

  // --- 10. firebug / third-party debug lib spoofing ---
  const DEBUGLIB_NAMES = [
    'firebug', '_firebug',
    'eruda', '__eruda',
    'vConsole', 'VConsole',
    'weinre', '__weinre',
    'remoteDebugger',
  ]

  DEBUGLIB_NAMES.forEach(name => {
    try {
      if (w[name] !== undefined) return
      Object.defineProperty(w, name, {
        get: () => undefined,
        set: () => {},
        configurable: true,
      })
    } catch (e) {
      reportError(`Section 10 (${name})`, e)
    }
  })

  try {
    if (w.console && w.console.firebug) {
      Object.defineProperty(w.console, 'firebug', { get: () => undefined, configurable: true })
    }
  } catch (e) {
    reportError('Section 10 (console.firebug)', e)
  }

  // --- 11. performance.now() timing attack mitigation ---
  const _perfNow = w.performance.now.bind(w.performance)

  try {
    w.performance.now = function safePerfNow() {
      return _perfNow() + (Math.random() * 0.5)
    }
    makeNative(w.performance.now, 'now')
  } catch (e) {
    reportError('Section 11 (performance.now)', e)
  }

  // --- 12. toString / regex detection bypass ---
  try {
    const _reToString = RegExp.prototype.toString
    Object.defineProperty(RegExp.prototype, 'toString', {
      get: () => _reToString,
      set: () => {},
      configurable: false,
    })
  } catch (e) {
    reportError('Section 12 (RegExp.toString)', e)
  }

  try {
    const _fnToString = Function.prototype.toString
    const patchedFnToString = function toString() {
      if (NATIVE_FN_MAP.has(this)) {
        return NATIVE_FN_MAP.get(this)
      }
      return _fnToString.call(this)
    }
    makeNative(patchedFnToString, 'toString')

    Object.defineProperty(Function.prototype, 'toString', {
      get: () => patchedFnToString,
      set: () => {},
      configurable: false,
    })
  } catch (e) {
    reportError('Section 12 (Function.toString)', e)
  }

  // --- 13. text selection and drag unblocking ---
  try {
    const UNBLOCK_EVENTS = ['selectstart', 'copy', 'cut', 'dragstart', 'paste']
    UNBLOCK_EVENTS.forEach(type => {
      w.addEventListener(type, e => e.stopImmediatePropagation(), true)
    })

    w.addEventListener('DOMContentLoaded', () => {
      try {
        if (document.body) {
          document.body.style.userSelect = ''
          document.body.style.webkitUserSelect = ''
        }
      } catch (e) {}
    })
  } catch (e) {
    reportError('Section 13 (unblock events)', e)
  }

  // --- 14. disable-devtool library kill switch ---
  try {
    if (w.DisableDevtool) {
      w.DisableDevtool.isSuspend = true
    }

    let _ddt = undefined
    Object.defineProperty(w, 'DisableDevtool', {
      get: () => _ddt,
      set: (lib) => {
        _ddt = lib
        if (_ddt && typeof _ddt === 'object') {
          _ddt.isSuspend = true
          if (typeof _ddt.stop === 'function') try { _ddt.stop() } catch (e) {}
        }
      },
      configurable: true,
    })
  } catch (e) {
    reportError('Section 14 (DisableDevtool)', e)
  }

})(unsafeWindow)