// ==UserScript==
// @name Leave No Trace
// @version 2.0
// @description Hide browser fingerprint. Derived from "No Fingerprint"
// @author janandreiiii
// @match *://*/*
// @grant none
// @run-at document-start
// @noframes false
// @license The Unlicense
// @namespace https://github.com/Sam0230
// ==/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; };
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 ""; };
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: "Gecko",
productSub: "20030107",
vendor: "Google Inc.",
vendorSub: "",
deviceMemory: Math.floor((Math.random() * 8) + 1),
hardwareConcurrency: Math.floor((Math.random() * 8) + 1),
maxTouchPoints: 0,
bluetooth: undefined,
clipboard: undefined,
connection: undefined,
credentials: undefined,
doNotTrack: "false",
geolocation: undefined,
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: undefined,
wakeLock: undefined,
webkitPersistentStorage: undefined,
webkitTemporaryStorage: undefined,
xr: undefined,
getBattery: "",
platform: "Win32",
};
// 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
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() + ")();";
document.documentElement.appendChild(script);