Undetectorized – Limited RAF

Keeps sites blind to tab switches and window blur. Fully blocks all focus and visibility checks, now with requestAnimationFrame capped below 10fps.

От 21.11.2025. Виж последната версия.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name          Undetectorized – Limited RAF
// @namespace     bypass.focus.fixed
// @version       5.5
// @author        Gaze
// @icon          https://i.imgur.com/l8qT82q.jpeg
// @description   Keeps sites blind to tab switches and window blur. Fully blocks all focus and visibility checks, now with requestAnimationFrame capped below 10fps.
// @include       *
// @run-at        document-start
// ==/UserScript==

(function() {
    const uw = unsafeWindow;

    // --- Patch document & window focus/visibility ---
    const patch = () => {
        try {
            uw.document.hasFocus = () => true;
            uw.hasFocus = () => true;
            Object.defineProperty(document, "visibilityState", { get: () => "visible" });
            ["hidden","mozHidden","msHidden","webkitHidden"].forEach(p =>
                Object.defineProperty(document, p, { value: false })
            );
            window.onblur = null;
            window.onfocus = null;
            document.onblur = null;
            document.onfocus = null;
            window.focus = () => true;
            document.focus = () => true;
            window.onbeforeunload = null;
            document.onbeforeunload = null;
            Object.defineProperty(window, "onbeforeunload", { set: () => true, get: () => null });
        } catch(e){}
    };

    // --- Block all focus/blur/visibility events ---
    const blockEvents = () => {
        try {
            const evs = [
                "visibilitychange","webkitvisibilitychange","mozvisibilitychange","msvisibilitychange",
                "blur","focus","focusin","focusout",
                "mouseleave","mouseout","mouseenter","mouseover",
                "pageshow","pagehide","resume","freeze"
            ];
            const handler = e => {
                e.stopImmediatePropagation();
                e.stopPropagation();
                e.preventDefault();
            };
            evs.forEach(ev => {
                window.addEventListener(ev, handler, true);
                document.addEventListener(ev, handler, true);
            });
        } catch(e){}
    };

    // --- Hook addEventListener to ignore critical events ---
    const hookAddEvent = () => {
        try {
            const blocked = [
                "visibilitychange","webkitvisibilitychange","mozvisibilitychange","msvisibilitychange",
                "blur","focus","focusin","focusout",
                "mouseleave","mouseout","mouseenter","mouseover",
                "beforeunload",
                "pageshow","pagehide","resume","freeze"
            ];
            const orig = EventTarget.prototype.addEventListener;
            EventTarget.prototype.addEventListener = function(type, listener, opts) {
                if (blocked.includes(type)) return;
                return orig.call(this, type, listener, opts);
            };
        } catch(e){}
    };

    // --- Patch timing & limit requestAnimationFrame ---
    const patchTiming = () => {
        try {
            const base = performance.now();
            performance.now = () => base + Math.random() * 0.01;

            const oRAF = uw.requestAnimationFrame;
            let lastCall = 0;
            const minInterval = 111; // ~9 FPS

            uw.requestAnimationFrame = cb => {
                const now = performance.now();
                const delay = Math.max(0, minInterval - (now - lastCall));
                lastCall = now + delay;
                return setTimeout(() => cb(performance.now()), delay);
            };

            const oTO = uw.setTimeout;
            uw.setTimeout = (fn, t) => oTO(fn, 0);
        } catch(e){}
    };

    // --- Initial patching ---
    patch();
    blockEvents();
    hookAddEvent();
    patchTiming();

    // --- Keep patches alive ---
    setInterval(() => {
        patch();
        hookAddEvent();
        patchTiming();
    }, 100);

})();