TypeScript 97.5%
SQL 1.4%
Python 0.8%
1/**2 * Init script injected in every page before any site script runs. Removes the usual headless /3 * automation tells that anti-bot vendors probe (webdriver flag, missing `chrome` object, empty4 * plugin list, SwiftShader WebGL renderer, permission API quirks, notification permission5 * mismatch, `outerWidth === 0`, headless UA hints).6 */7export function stealthScript(opts: { platform: string; languages: string[]; hardwareConcurrency: number; deviceMemory: number; vendor: string; renderer: string; mobile: boolean }): string {8 return `(() => {9 const opts = ${JSON.stringify(opts)};10 const define = (obj, key, value) => { try { Object.defineProperty(obj, key, { get: () => value, configurable: true }); } catch {} };1112 // navigator.webdriver → false (and not enumerable like real Chrome)13 try { Object.defineProperty(Navigator.prototype, 'webdriver', { get: () => false, configurable: true }); } catch {}1415 // window.chrome (present in every Chrome, absent in headless-shell)16 if (!window.chrome) {17 const chrome = {18 app: { isInstalled: false, InstallState: { DISABLED: 'disabled', INSTALLED: 'installed', NOT_INSTALLED: 'not_installed' }, RunningState: { CANNOT_RUN: 'cannot_run', READY_TO_RUN: 'ready_to_run', RUNNING: 'running' } },19 runtime: { OnInstalledReason: { CHROME_UPDATE: 'chrome_update', INSTALL: 'install', SHARED_MODULE_UPDATE: 'shared_module_update', UPDATE: 'update' }, PlatformArch: { ARM: 'arm', ARM64: 'arm64', MIPS: 'mips', MIPS64: 'mips64', X86_32: 'x86-32', X86_64: 'x86-64' }, PlatformOs: { ANDROID: 'android', CROS: 'cros', LINUX: 'linux', MAC: 'mac', OPENBSD: 'openbsd', WIN: 'win' }, RequestUpdateCheckStatus: { NO_UPDATE: 'no_update', THROTTLED: 'throttled', UPDATE_AVAILABLE: 'update_available' }, connect: function() {}, sendMessage: function() {}, id: undefined },20 csi: function() { return { onloadT: Date.now(), pageT: Math.random() * 1000, startE: Date.now(), tran: 15 }; },21 loadTimes: function() { const t = Date.now() / 1000; return { commitLoadTime: t, connectionInfo: 'h2', finishDocumentLoadTime: t, finishLoadTime: t, firstPaintAfterLoadTime: 0, firstPaintTime: t, navigationType: 'Other', npnNegotiatedProtocol: 'h2', requestTime: t - 0.5, startLoadTime: t - 0.4, wasAlternateProtocolAvailable: false, wasFetchedViaSpdy: true, wasNpnNegotiated: true }; },22 };23 define(window, 'chrome', chrome);24 }2526 // Plugins & mimeTypes (Chrome ships 5 PDF-related plugins)27 try {28 const mk = (name, filename, description) => ({ name, filename, description, length: 1, item: () => null, namedItem: () => null, 0: { type: 'application/pdf', suffixes: 'pdf', description } });29 const list = [mk('PDF Viewer', 'internal-pdf-viewer', 'Portable Document Format'), mk('Chrome PDF Viewer', 'internal-pdf-viewer', 'Portable Document Format'), mk('Chromium PDF Viewer', 'internal-pdf-viewer', 'Portable Document Format'), mk('Microsoft Edge PDF Viewer', 'internal-pdf-viewer', 'Portable Document Format'), mk('WebKit built-in PDF', 'internal-pdf-viewer', 'Portable Document Format')];30 const plugins = Object.create(PluginArray.prototype);31 list.forEach((p, i) => { plugins[i] = p; });32 define(plugins, 'length', opts.mobile ? 0 : list.length);33 plugins.item = (i) => plugins[i] ?? null; plugins.namedItem = (n) => list.find((p) => p.name === n) ?? null; plugins.refresh = () => {};34 if (navigator.plugins.length === 0) define(Navigator.prototype, 'plugins', plugins);35 } catch {}3637 define(Navigator.prototype, 'languages', opts.languages);38 define(Navigator.prototype, 'platform', opts.platform);39 define(Navigator.prototype, 'hardwareConcurrency', opts.hardwareConcurrency);40 define(Navigator.prototype, 'deviceMemory', opts.deviceMemory);41 if (opts.mobile) define(Navigator.prototype, 'maxTouchPoints', 5);4243 // Permissions: headless reports 'denied' for notifications while Notification.permission is 'default'44 try {45 const q = Permissions.prototype.query;46 Permissions.prototype.query = function(p) {47 if (p && p.name === 'notifications') return Promise.resolve({ state: Notification.permission === 'default' ? 'prompt' : Notification.permission, onchange: null });48 return q.call(this, p);49 };50 } catch {}5152 // WebGL vendor/renderer (SwiftShader / "Google Inc. (Google)" is a headless tell)53 try {54 const patch = (proto) => {55 const gp = proto.getParameter;56 proto.getParameter = function(param) {57 if (param === 37445) return opts.vendor;58 if (param === 37446) return opts.renderer;59 return gp.call(this, param);60 };61 };62 if (window.WebGLRenderingContext) patch(WebGLRenderingContext.prototype);63 if (window.WebGL2RenderingContext) patch(WebGL2RenderingContext.prototype);64 } catch {}6566 // outerWidth/outerHeight are 0 in headless67 if (!window.outerWidth) define(window, 'outerWidth', window.innerWidth);68 if (!window.outerHeight) define(window, 'outerHeight', window.innerHeight + 85);6970 // Hide automation-only properties leaking through Function.prototype.toString71 try {72 const nativeToString = Function.prototype.toString;73 const patched = new WeakSet([Permissions.prototype.query]);74 Function.prototype.toString = function() {75 if (patched.has(this)) return 'function query() { [native code] }';76 return nativeToString.call(this);77 };78 } catch {}7980 // Connection / battery plausibility81 try { if (navigator.connection) define(navigator.connection, 'rtt', 50); } catch {}82})();`;83}8485const TIMEZONES: Record<string, string> = {86 CA: "America/Toronto",87 US: "America/New_York",88 GB: "Europe/London",89 FR: "Europe/Paris",90 DE: "Europe/Berlin",91 ES: "Europe/Madrid",92 IT: "Europe/Rome",93 NL: "Europe/Amsterdam",94 BE: "Europe/Brussels",95 CH: "Europe/Zurich",96 SE: "Europe/Stockholm",97 PL: "Europe/Warsaw",98 PT: "Europe/Lisbon",99 IE: "Europe/Dublin",100 AU: "Australia/Sydney",101 NZ: "Pacific/Auckland",102 JP: "Asia/Tokyo",103 KR: "Asia/Seoul",104 IN: "Asia/Kolkata",105 SG: "Asia/Singapore",106 HK: "Asia/Hong_Kong",107 BR: "America/Sao_Paulo",108 MX: "America/Mexico_City",109 AR: "America/Argentina/Buenos_Aires",110 ZA: "Africa/Johannesburg",111 AE: "Asia/Dubai",112 TR: "Europe/Istanbul",113 RU: "Europe/Moscow",114 IL: "Asia/Jerusalem",115};116117export function timezoneFor(country: string | null | undefined): string {118 return (country && TIMEZONES[country.toUpperCase()]) || "America/New_York";119}120121export function webglFor(platform: string, tls: string): { vendor: string; renderer: string } {122 if (tls === "safari" || /mac/i.test(platform)) return { vendor: "Google Inc. (Apple)", renderer: "ANGLE (Apple, ANGLE Metal Renderer: Apple M2, Unspecified Version)" };123 if (/linux/i.test(platform) && !/arm/i.test(platform)) return { vendor: "Google Inc. (Intel)", renderer: "ANGLE (Intel, Mesa Intel(R) UHD Graphics 630 (CFL GT2), OpenGL 4.6)" };124 if (/arm/i.test(platform)) return { vendor: "Google Inc. (Qualcomm)", renderer: "ANGLE (Qualcomm, Adreno (TM) 750, OpenGL ES 3.2 V@0744.0)" };125 return { vendor: "Google Inc. (NVIDIA)", renderer: "ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 (0x00002504) Direct3D11 vs_5_0 ps_5_0, D3D11)" };126}127