Safari Fingerprint blocker

Hide browser fingerprint. Derived from "No Fingerprint"

  1. // ==UserScript==
  2. // @name Safari Fingerprint blocker
  3. // @version 1.0
  4. // @description Hide browser fingerprint. Derived from "No Fingerprint"
  5. // @match *://*/*
  6. // @grant none
  7. // @run-at document-start
  8. // @noframes false
  9. // @license The Unlicense
  10. // @namespace https://greasyfork.org/users/1405117
  11. // ==/UserScript==
  12. let script = document.createElement("script");
  13. script.textContent = "(" + (function() {
  14. "use strict";
  15. let debug = function(topOnly) {
  16. if (!topOnly || window === window.top) {
  17. // debugger;
  18. }
  19. };
  20. (function() {
  21. document.documentElement.dataset.fbscriptallow = true;
  22. })();
  23. let randomChange = function(n, m) {
  24. if (!m) {
  25. m = 0.1;
  26. }
  27. return Math.round(n + ((Math.random() - 0.5) * 2 * n * 0.3));
  28. };
  29. let setValue = function(object, propertyName, value, writable) {
  30. if (!writable) {
  31. writable = false;
  32. }
  33. Object.defineProperty(object, propertyName, {
  34. value: value,
  35. writable: writable,
  36. enumerable: true
  37. });
  38. };
  39. (function() { // Date
  40. window.Date.prototype.getDate = window.Date.prototype.getUTCDate;
  41. window.Date.prototype.getDay = window.Date.prototype.getUTCDay;
  42. window.Date.prototype.getFullYear = window.Date.prototype.getUTCFullYear;
  43. window.Date.prototype.getHours = window.Date.prototype.getUTCHours;
  44. window.Date.prototype.getMilliseconds = window.Date.prototype.getUTCMilliseconds;
  45. window.Date.prototype.getMinutes = window.Date.prototype.getUTCMinutes;
  46. window.Date.prototype.getMonth = window.Date.prototype.getUTCMonth;
  47. window.Date.prototype.getSeconds = window.Date.prototype.getUTCSeconds;
  48. window.Date.prototype.getTimezoneOffset = function() { return 0; }; // -480
  49. window.Date.prototype.getYear = function() { return this.getFullYear() - 1900; };
  50. window.Date.prototype.setDate = window.Date.prototype.setUTCDate;
  51. window.Date.prototype.setFullYear = window.Date.prototype.setUTCFullYear;
  52. window.Date.prototype.setHours = window.Date.prototype.setUTCHours;
  53. window.Date.prototype.setMilliseconds = window.Date.prototype.setUTCMilliseconds;
  54. window.Date.prototype.setMinutes = window.Date.prototype.setUTCMinutes;
  55. window.Date.prototype.setMonth = window.Date.prototype.setUTCMonth;
  56. window.Date.prototype.setSeconds = window.Date.prototype.setUTCSeconds;
  57. window.Date.prototype.setYear = function(n) { return this.setFullYear(n + 1900); };
  58. window.Date.prototype.toLocaleDateString = function() { return ""; };
  59. window.Date.prototype.toLocaleString = function() { return ""; }; //America/Los_Angeles
  60. window.Date.prototype.toLocaleTimeString = function() { return ""; };
  61. window.Date.prototype.toString = function() { return ""; };
  62. window.Date.prototype.toTimeString = function() { return ""; };
  63. })();
  64. (function() {
  65. let fakeNavigator = {
  66. appCodeName: "",
  67. appName: "",
  68. appVersion: "",
  69. product: "",
  70. productSub: "",
  71. vendor: "",
  72. vendorSub: "",
  73. deviceMemory: Math.floor((Math.random() * 8) + 1),
  74. hardwareConcurrency: Math.floor((Math.random() * 8) + 1),
  75. maxTouchPoints: Math.floor((Math.random() * 8) + 1),
  76. bluetooth: undefined,
  77. clipboard: undefined,
  78. connection: undefined,
  79. credentials: undefined,
  80. doNotTrack: "false",
  81. geolocation: undefined,
  82. //globalPrivacyControl: 1,
  83. keyboard: undefined,
  84. language: "en-US",
  85. languages: "en-US",
  86. locks: undefined,
  87. mediaCapabilities: undefined,
  88. mediaDevices: undefined,
  89. mediaSession: undefined,
  90. onLine: undefined,
  91. permissions: undefined,
  92. presentation: undefined,
  93. scheduling: undefined,
  94. serviceWorker: undefined,
  95. usb: undefined,
  96. userActivation: undefined,
  97. userAgentData: "",
  98. wakeLock: undefined,
  99. webkitPersistentStorage: undefined,
  100. webkitTemporaryStorage: undefined,
  101. xr: undefined,
  102. getBattery: "",
  103. platform: "",
  104. };
  105. // Define getters for the properties in window.navigator
  106. for (let prop in window.navigator) {
  107. if (fakeNavigator[prop] !== undefined) {
  108. try {
  109. Object.defineProperty(window.navigator, prop, {
  110. get: function() {
  111. if (fakeNavigator[prop] === "undefined") {
  112. return undefined;
  113. }
  114. return fakeNavigator[prop];
  115. },
  116. });
  117. } catch (e) {}
  118. }
  119. }
  120. })();
  121. // Randomized Plugins
  122. (function() {
  123. function generateRandomString(length) {
  124. const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  125. let result = '';
  126. for (let i = 0; i < length; i++) {
  127. const randomIndex = Math.floor(Math.random() * characters.length);
  128. result += characters.charAt(randomIndex);
  129. }
  130. return result;
  131. }
  132. const numPlugins = Math.floor(Math.random() * 5) + 1;
  133. const customPlugins = [];
  134. // Generate random plugins
  135. for (let i = 0; i < numPlugins; i++) {
  136. const pluginName = generateRandomString(10);
  137. const pluginDescription = generateRandomString(20);
  138. customPlugins.push({
  139. name: pluginName,
  140. description: pluginDescription,
  141. });
  142. }
  143. // Override navigator.plugins with the custom plugins
  144. Object.defineProperty(navigator, 'plugins', {
  145. get: function() {
  146. return customPlugins;
  147. },
  148. });
  149. })();
  150. (function() { // Screen size
  151.  
  152. var choice2 = Math.floor(Math.random() * 4);
  153.  
  154. switch(choice2){
  155. case 0:
  156. var screenSize = [360,800];
  157. break;
  158.  
  159. case 1:
  160. var screenSize = [1920,1080];
  161. break;
  162.  
  163. case 2:
  164. var screenSize = [1366,768];
  165. break;
  166. case 3:
  167. var screenSize = [1536,864];
  168. };
  169. //let screenSize = [1920, 1080];
  170. screen.availWidth && setValue(screen, "availWidth", screenSize[0]);
  171. screen.availHeight && setValue(screen, "availHeight", screenSize[1] - 40);
  172. screen.availLeft && setValue(screen, "availLeft", undefined, true);
  173. screen.availTop && setValue(screen, "availTop", undefined, true);
  174. screen.width && setValue(screen, "width", screenSize[0]);
  175. screen.height && setValue(screen, "height", screenSize[1]);
  176. screen.Brightness && setValue(screen, "Brightness", randomChange(screen.Brightness));
  177. screen.mozBrightness && setValue(screen, "mozBrightness", randomChange(screen.mozBrightness));
  178. screen.left && setValue(screen, "left", undefined, true);
  179. screen.top && setValue(screen, "top", undefined, true);
  180. screen.enabled && setValue(screen, "enabled", undefined);
  181. screen.mozEnabled && setValue(screen, "mozEnabled", undefined);
  182. screen.pixelDepth && setValue(screen, "pixelDepth", 32);
  183. screen.colorDepth && setValue(screen, "colorDepth", 32);
  184. })();
  185. (function() { // Debugger panel size
  186. let n = Math.round(71.5 + (Math.random() * 15)), wChanged = false, wValue, hChanged = false, hValue;
  187. Object.defineProperty(window, "outerWidth", {
  188. get: function() {
  189. if (!wChanged) {
  190. return window.innerWidth;
  191. }
  192. return wValue;
  193. },
  194. set: function(value) {
  195. wChanged = true;
  196. wValue = value;
  197. }
  198. });
  199. Object.defineProperty(window, "outerHeight", {
  200. get: function() {
  201. if (!hChanged) {
  202. return window.innerHeight + n;
  203. }
  204. return hValue;
  205. },
  206. set: function(value) {
  207. hChanged = true;
  208. hValue = value;
  209. }
  210. });
  211. })();
  212. (function() { // AudioContext
  213. let origGetFloatFrequencyData = window.AnalyserNode.prototype.getFloatFrequencyData;
  214. window.AnalyserNode.prototype.getFloatFrequencyData = function getFloatFrequencyData(array) {
  215. let ret = origGetFloatFrequencyData.apply(this, arguments);
  216. for (let i = 0; i < array.length; i++) {
  217. array[i] = array[i] + Math.random() * 0.2;
  218. }
  219. return ret;
  220. };
  221. window.AnalyserNode.prototype.getFloatFrequencyData.toString = origGetFloatFrequencyData.toString.bind(origGetFloatFrequencyData);
  222. let origGetChannelData = window.AudioBuffer.prototype.getChannelData;
  223. window.AudioBuffer.prototype.getChannelData = function getChannelData() {
  224. let ret = origGetChannelData.apply(this, arguments);
  225. for (let i = 0; i < ret.length; i++) {
  226. ret[i] = ret[i] + Math.random() * 0.0001;
  227. }
  228. return ret;
  229. };
  230. window.AudioBuffer.prototype.getChannelData.toString = origGetChannelData.toString.bind(origGetChannelData);
  231. })();
  232. (function() { // Canvas
  233. // Save original methods
  234. let origGetContext = HTMLCanvasElement.prototype.getContext;
  235. let origGetImageData = CanvasRenderingContext2D.prototype.getImageData;
  236. let origToDataURL = HTMLCanvasElement.prototype.toDataURL;
  237. // Function to randomize image data
  238. let randomizeImageData = function(imageData) {
  239. let data = imageData.data;
  240. for (let i = 0; i < data.length; i += 4) {
  241. // Modify pixel data to include random variations
  242. data[i] = (data[i] + Math.random() * 10) % 256; // Red
  243. data[i + 1] = (data[i + 1] + Math.random() * 10) % 256; // Green
  244. data[i + 2] = (data[i + 2] + Math.random() * 10) % 256; // Blue
  245. // Alpha remains the same
  246. }
  247. };
  248. // Override the getImageData method to randomize image data
  249. CanvasRenderingContext2D.prototype.getImageData = function() {
  250. let imageData = origGetImageData.apply(this, arguments);
  251. randomizeImageData(imageData);
  252. return imageData;
  253. };
  254. // Function to randomize canvas data URL
  255. let randomizeDataURL = function(dataURL) {
  256. // Append random query string to data URL to prevent caching
  257. return dataURL + '?random=' + Math.random();
  258. };
  259. // Override the toDataURL method to randomize data URL
  260. HTMLCanvasElement.prototype.toDataURL = function() {
  261. let dataURL = origToDataURL.apply(this, arguments);
  262. return randomizeDataURL(dataURL);
  263. };
  264. // Override getContext to ensure modifications are applied
  265. HTMLCanvasElement.prototype.getContext = function() {
  266. let context = origGetContext.apply(this, arguments);
  267. if (arguments[0] === '2d' && typeof context.getImageData === 'function') {
  268. context.getImageData = CanvasRenderingContext2D.prototype.getImageData;
  269. }
  270. return context;
  271. };
  272. })();
  273. // Randomize WebGL Rendering Context attributes
  274. const originalGetExtension = WebGLRenderingContext.prototype.getExtension;
  275. WebGLRenderingContext.prototype.getExtension = function(name) {
  276. if (name === 'WEBGL_debug_renderer_info') {
  277. return null;
  278. }
  279. return originalGetExtension.call(this, name);
  280. };
  281. const originalGetSupportedExtensions = WebGLRenderingContext.prototype.getSupportedExtensions;
  282. WebGLRenderingContext.prototype.getSupportedExtensions = function() {
  283. return (originalGetSupportedExtensions.call(this) || []).filter(ext => ext !== 'WEBGL_debug_renderer_info');
  284. };
  285. // Local storage noise
  286. (function() {
  287. let originalSetItem = localStorage.setItem;
  288. let originalGetItem = localStorage.getItem;
  289. localStorage.setItem = function(key, value) {
  290. let noise = (Math.random() * 0.0001).toString();
  291. originalSetItem.call(this, key, value + noise);
  292. };
  293. localStorage.getItem = function(key) {
  294. let value = originalGetItem.call(this, key);
  295. if (value) {
  296. return value.replace(/0\.\d+$/, "");
  297. }
  298. return value;
  299. };
  300. })();
  301. // WebGL noise
  302. (function() {
  303. let originalGetParameter = WebGLRenderingContext.prototype.getParameter;
  304. WebGLRenderingContext.prototype.getParameter = function(parameter) {
  305. let value = originalGetParameter.call(this, parameter);
  306. if (typeof value === "number") {
  307. return value + Math.random() * 0.01;
  308. }
  309. return value;
  310. };
  311. })();
  312. }).toString() + ")();";
  313.  
  314.  
  315.  
  316.  
  317. Object.defineProperty(navigator, 'userAgent', {
  318. get: function () { return ''; }
  319. });
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327. (function () { // Intl
  328. window.Intl = undefined;
  329. })();
  330.  
  331.  
  332. 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);
  333.  
  334.  
  335.  
  336. (function() {
  337.  
  338. // Override the getVoices method
  339. const originalGetVoices = window.speechSynthesis.getVoices;
  340.  
  341. window.speechSynthesis.getVoices = function() {
  342. return []; // Return an empty array
  343. };
  344.  
  345. // Optionally, you can also override the voices property
  346. Object.defineProperty(window.speechSynthesis, 'voices', {
  347. get: function() {
  348. return []; // Return an empty array
  349. }
  350. });
  351.  
  352. })();
  353.  
  354.  
  355.  
  356.  
  357.  
  358. (function() {
  359.  
  360. // Override the getBoundingClientRect method for spans
  361. const originalGetBoundingClientRect = HTMLElement.prototype.getBoundingClientRect;
  362. HTMLElement.prototype.getBoundingClientRect = function() {
  363. // Check if the element is a span
  364. if (this.tagName.toLowerCase() === 'span') {
  365. // Return a fixed rectangle to prevent accurate width measurement
  366. return {
  367. width: 100, // Fixed width
  368. height: 20, // Fixed height
  369. top: 0,
  370. right: 100,
  371. bottom: 20,
  372. left: 0,
  373. // Include other properties as needed
  374. };
  375. }
  376. // Call the original method for other elements
  377. return originalGetBoundingClientRect.call(this);
  378. };
  379.  
  380. // Optionally, override the offsetWidth property for spans
  381. Object.defineProperty(HTMLElement.prototype, 'offsetWidth', {
  382. get: function() {
  383. if (this.tagName.toLowerCase() === 'span') {
  384. return 100; // Fixed width
  385. }
  386. return originalGetBoundingClientRect.call(this).width;
  387. }
  388. });
  389.  
  390. // Optionally, override the offsetHeight property for spans
  391. Object.defineProperty(HTMLElement.prototype, 'offsetHeight', {
  392. get: function() {
  393. if (this.tagName.toLowerCase() === 'span') {
  394. return 20; // Fixed height
  395. }
  396. return originalGetBoundingClientRect.call(this).height;
  397. }
  398. });
  399. })();
  400.  
  401. document.documentElement.appendChild(script);