Safari Fingerprint blocker

Hide browser fingerprint. Derived from "No Fingerprint"

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Safari Fingerprint blocker
// @version      1.0
// @description  Hide browser fingerprint. Derived from "No Fingerprint"
// @match        *://*/*
// @grant        none
// @run-at       document-start
// @noframes     false
// @license      The Unlicense
// @namespace https://greasyfork.org/users/1405117
// ==/UserScript==
 
let script = document.createElement("script");
script.textContent = "(" + (function() {
    "use strict";
 
    let debug = function(topOnly) {
        if (!topOnly || window === window.top) {
            // debugger;
        }
    };
 
    (function() {
        document.documentElement.dataset.fbscriptallow = true;
    })();
 
    let randomChange = function(n, m) {
        if (!m) {
            m = 0.1;
        }
        return Math.round(n + ((Math.random() - 0.5) * 2 * n * 0.3));
    };
 
    let setValue = function(object, propertyName, value, writable) {
        if (!writable) {
            writable = false;
        }
        Object.defineProperty(object, propertyName, {
            value: value,
            writable: writable,
            enumerable: true
        });
    };
 
    (function() { // Date
        window.Date.prototype.getDate = window.Date.prototype.getUTCDate;
        window.Date.prototype.getDay = window.Date.prototype.getUTCDay;
        window.Date.prototype.getFullYear = window.Date.prototype.getUTCFullYear;
        window.Date.prototype.getHours = window.Date.prototype.getUTCHours;
        window.Date.prototype.getMilliseconds = window.Date.prototype.getUTCMilliseconds;
        window.Date.prototype.getMinutes = window.Date.prototype.getUTCMinutes;
        window.Date.prototype.getMonth = window.Date.prototype.getUTCMonth;
        window.Date.prototype.getSeconds = window.Date.prototype.getUTCSeconds;
        window.Date.prototype.getTimezoneOffset = function() { return 0; }; // -480
        window.Date.prototype.getYear = function() { return this.getFullYear() - 1900; };
        window.Date.prototype.setDate = window.Date.prototype.setUTCDate;
        window.Date.prototype.setFullYear = window.Date.prototype.setUTCFullYear;
        window.Date.prototype.setHours = window.Date.prototype.setUTCHours;
        window.Date.prototype.setMilliseconds = window.Date.prototype.setUTCMilliseconds;
        window.Date.prototype.setMinutes = window.Date.prototype.setUTCMinutes;
        window.Date.prototype.setMonth = window.Date.prototype.setUTCMonth;
        window.Date.prototype.setSeconds = window.Date.prototype.setUTCSeconds;
        window.Date.prototype.setYear = function(n) { return this.setFullYear(n + 1900); };
        window.Date.prototype.toLocaleDateString = function() { return ""; };
        window.Date.prototype.toLocaleString = function() { return ""; }; //America/Los_Angeles
        window.Date.prototype.toLocaleTimeString = function() { return ""; };
        window.Date.prototype.toString = function() { return ""; };
        window.Date.prototype.toTimeString = function() { return ""; };
    })();
 
    (function() {
        let fakeNavigator = {
            appCodeName: "",
            appName: "",
            appVersion: "",
            product: "",
            productSub: "",
            vendor: "",
            vendorSub: "",
            deviceMemory: Math.floor((Math.random() * 8) + 1),
            hardwareConcurrency: Math.floor((Math.random() * 8) + 1),
            maxTouchPoints: Math.floor((Math.random() * 8) + 1),
            bluetooth: undefined,
            clipboard: undefined,
            connection: undefined,
            credentials: undefined,
            doNotTrack: "false",
            geolocation: undefined,
            //globalPrivacyControl: 1,
            keyboard: undefined,
            language: "en-US",
            languages: "en-US",
            locks: undefined,
            mediaCapabilities: undefined,
            mediaDevices: undefined,
            mediaSession: undefined,
            onLine: undefined,
            permissions: undefined,
            presentation: undefined,
            scheduling: undefined,
            serviceWorker: undefined,
            usb: undefined,
            userActivation: undefined,
            userAgentData: "",
            wakeLock: undefined,
            webkitPersistentStorage: undefined,
            webkitTemporaryStorage: undefined,
            xr: undefined,
            getBattery: "",
            platform: "",
        };
 
        // Define getters for the properties in window.navigator
        for (let prop in window.navigator) {
            if (fakeNavigator[prop] !== undefined) {
                try {
                    Object.defineProperty(window.navigator, prop, {
                        get: function() {
                            if (fakeNavigator[prop] === "undefined") {
                                return undefined;
                            }
                            return fakeNavigator[prop];
                        },
                    });
                } catch (e) {}
            }
        }
    })();
 
    // Randomized Plugins
    (function() {
        function generateRandomString(length) {
            const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
            let result = '';
            for (let i = 0; i < length; i++) {
                const randomIndex = Math.floor(Math.random() * characters.length);
                result += characters.charAt(randomIndex);
            }
            return result;
        }
 
        const numPlugins = Math.floor(Math.random() * 5) + 1;
        const customPlugins = [];
 
        // Generate random plugins
        for (let i = 0; i < numPlugins; i++) {
            const pluginName = generateRandomString(10);
            const pluginDescription = generateRandomString(20);
            customPlugins.push({
                name: pluginName,
                description: pluginDescription,
            });
        }
 
        // Override navigator.plugins with the custom plugins
        Object.defineProperty(navigator, 'plugins', {
            get: function() {
                return customPlugins;
            },
        });
    })();
 
    (function() { // Screen size

        var choice2 = Math.floor(Math.random() * 4);

            switch(choice2){
    
    case 0:
            var screenSize = [360,800];   
             break;

    case 1:
            var screenSize = [1920,1080];
            break;

    case 2:
            var screenSize = [1366,768];
            break;
   
    
    case 3:
            var screenSize = [1536,864];
            
 };
        //let screenSize = [1920, 1080];
        screen.availWidth && setValue(screen, "availWidth", screenSize[0]);
        screen.availHeight && setValue(screen, "availHeight", screenSize[1] - 40);
        screen.availLeft && setValue(screen, "availLeft", undefined, true);
        screen.availTop && setValue(screen, "availTop", undefined, true);
        screen.width && setValue(screen, "width", screenSize[0]);
        screen.height && setValue(screen, "height", screenSize[1]);
        screen.Brightness && setValue(screen, "Brightness", randomChange(screen.Brightness));
        screen.mozBrightness && setValue(screen, "mozBrightness", randomChange(screen.mozBrightness));
        screen.left && setValue(screen, "left", undefined, true);
        screen.top && setValue(screen, "top", undefined, true);
        screen.enabled && setValue(screen, "enabled", undefined);
        screen.mozEnabled && setValue(screen, "mozEnabled", undefined);
        screen.pixelDepth && setValue(screen, "pixelDepth", 32);
        screen.colorDepth && setValue(screen, "colorDepth", 32);
    })();
 
    (function() { // Debugger panel size
        let n = Math.round(71.5 + (Math.random() * 15)), wChanged = false, wValue, hChanged = false, hValue;
        Object.defineProperty(window, "outerWidth", {
            get: function() {
                if (!wChanged) {
                    return window.innerWidth;
                }
                return wValue;
            },
            set: function(value) {
                wChanged = true;
                wValue = value;
            }
        });
        Object.defineProperty(window, "outerHeight", {
            get: function() {
                if (!hChanged) {
                    return window.innerHeight + n;
                }
                return hValue;
            },
            set: function(value) {
                hChanged = true;
                hValue = value;
            }
        });
    })();
 
    (function() { // AudioContext
        let origGetFloatFrequencyData = window.AnalyserNode.prototype.getFloatFrequencyData;
        window.AnalyserNode.prototype.getFloatFrequencyData = function getFloatFrequencyData(array) {
            let ret = origGetFloatFrequencyData.apply(this, arguments);
            for (let i = 0; i < array.length; i++) {
                array[i] = array[i] + Math.random() * 0.2;
            }
            return ret;
        };
        window.AnalyserNode.prototype.getFloatFrequencyData.toString = origGetFloatFrequencyData.toString.bind(origGetFloatFrequencyData);
 
        let origGetChannelData = window.AudioBuffer.prototype.getChannelData;
        window.AudioBuffer.prototype.getChannelData = function getChannelData() {
            let ret = origGetChannelData.apply(this, arguments);
            for (let i = 0; i < ret.length; i++) {
                ret[i] = ret[i] + Math.random() * 0.0001;
            }
            return ret;
        };
        window.AudioBuffer.prototype.getChannelData.toString = origGetChannelData.toString.bind(origGetChannelData);
    })();
 
   (function() { // Canvas
    // Save original methods
    let origGetContext = HTMLCanvasElement.prototype.getContext;
    let origGetImageData = CanvasRenderingContext2D.prototype.getImageData;
    let origToDataURL = HTMLCanvasElement.prototype.toDataURL;
 
    // Function to randomize image data
    let randomizeImageData = function(imageData) {
        let data = imageData.data;
        for (let i = 0; i < data.length; i += 4) {
            // Modify pixel data to include random variations
            data[i] = (data[i] + Math.random() * 10) % 256;       // Red
            data[i + 1] = (data[i + 1] + Math.random() * 10) % 256; // Green
            data[i + 2] = (data[i + 2] + Math.random() * 10) % 256; // Blue
            // Alpha remains the same
        }
    };
 
    // Override the getImageData method to randomize image data
    CanvasRenderingContext2D.prototype.getImageData = function() {
        let imageData = origGetImageData.apply(this, arguments);
        randomizeImageData(imageData);
        return imageData;
    };
 
    // Function to randomize canvas data URL
    let randomizeDataURL = function(dataURL) {
        // Append random query string to data URL to prevent caching
        return dataURL + '?random=' + Math.random();
    };
 
    // Override the toDataURL method to randomize data URL
    HTMLCanvasElement.prototype.toDataURL = function() {
        let dataURL = origToDataURL.apply(this, arguments);
        return randomizeDataURL(dataURL);
    };
 
    // Override getContext to ensure modifications are applied
    HTMLCanvasElement.prototype.getContext = function() {
        let context = origGetContext.apply(this, arguments);
        if (arguments[0] === '2d' && typeof context.getImageData === 'function') {
            context.getImageData = CanvasRenderingContext2D.prototype.getImageData;
        }
        return context;
    };
})();
 
   // Randomize WebGL Rendering Context attributes
    const originalGetExtension = WebGLRenderingContext.prototype.getExtension;
    WebGLRenderingContext.prototype.getExtension = function(name) {
        if (name === 'WEBGL_debug_renderer_info') {
            return null;
        }
        return originalGetExtension.call(this, name);
    };
 
    const originalGetSupportedExtensions = WebGLRenderingContext.prototype.getSupportedExtensions;
    WebGLRenderingContext.prototype.getSupportedExtensions = function() {
        return (originalGetSupportedExtensions.call(this) || []).filter(ext => ext !== 'WEBGL_debug_renderer_info');
    };
 
    // Local storage noise
    (function() {
        let originalSetItem = localStorage.setItem;
        let originalGetItem = localStorage.getItem;
 
        localStorage.setItem = function(key, value) {
            let noise = (Math.random() * 0.0001).toString();
            originalSetItem.call(this, key, value + noise);
        };
 
        localStorage.getItem = function(key) {
            let value = originalGetItem.call(this, key);
            if (value) {
                return value.replace(/0\.\d+$/, "");
            }
            return value;
        };
    })();
 
    // WebGL noise
    (function() {
        let originalGetParameter = WebGLRenderingContext.prototype.getParameter;
 
        WebGLRenderingContext.prototype.getParameter = function(parameter) {
            let value = originalGetParameter.call(this, parameter);
            if (typeof value === "number") {
                return value + Math.random() * 0.01;
            }
            return value;
        };
    })();
}).toString() + ")();";




Object.defineProperty(navigator, 'userAgent', {
           get: function () { return ''; }
        });







(function () { // Intl
		window.Intl = undefined;
	})();


function hideRefer(c){var b=c.target;if(b&&b.tagName!=="A"){b=b.parentNode}if(b&&b.tagName==="A"){b.rel="noreferrer"}}window.addEventListener("click",hideRefer,true);window.addEventListener("contextmenu",hideRefer,true);



(function() {
    

    // Override the getVoices method
    const originalGetVoices = window.speechSynthesis.getVoices;

    window.speechSynthesis.getVoices = function() {
        return []; // Return an empty array
    };

    // Optionally, you can also override the voices property
    Object.defineProperty(window.speechSynthesis, 'voices', {
        get: function() {
            return []; // Return an empty array
        }
    });

})();





(function() {
    

    // Override the getBoundingClientRect method for spans
    const originalGetBoundingClientRect = HTMLElement.prototype.getBoundingClientRect;
    HTMLElement.prototype.getBoundingClientRect = function() {
        // Check if the element is a span
        if (this.tagName.toLowerCase() === 'span') {
            // Return a fixed rectangle to prevent accurate width measurement
            return {
                width: 100, // Fixed width
                height: 20, // Fixed height
                top: 0,
                right: 100,
                bottom: 20,
                left: 0,
                // Include other properties as needed
            };
        }
        // Call the original method for other elements
        return originalGetBoundingClientRect.call(this);
    };

    // Optionally, override the offsetWidth property for spans
    Object.defineProperty(HTMLElement.prototype, 'offsetWidth', {
        get: function() {
            if (this.tagName.toLowerCase() === 'span') {
                return 100; // Fixed width
            }
            return originalGetBoundingClientRect.call(this).width;
        }
    });

    // Optionally, override the offsetHeight property for spans
    Object.defineProperty(HTMLElement.prototype, 'offsetHeight', {
        get: function() {
            if (this.tagName.toLowerCase() === 'span') {
                return 20; // Fixed height
            }
            return originalGetBoundingClientRect.call(this).height;
        }
    });
})();

 
document.documentElement.appendChild(script);