fpscanner 0.9.5-beta.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Fingerprint Scanner
2
2
 
3
- > **News:** After more than 7 years without any updates, I'm releasing a completely new version of FPScanner! This version includes both the fingerprinting code and detection logic in a single library. Consider this a beta release — feel free to use it in your projects. The overall API should remain stable, but expect some small changes as we refine the library based on feedback.
3
+ > **News:** After more than 7 years without any updates, the first release of the new FPScanner is here. This version combines fingerprinting and bot detection in a single library. Try the live demo at [fpscanner.com](https://fpscanner.com/). Expect new fingerprinting signals and more detection logic over time.
4
4
 
5
5
  [![CI](https://github.com/antoinevastel/fpscanner/actions/workflows/ci.yml/badge.svg)](https://github.com/antoinevastel/fpscanner/actions/workflows/ci.yml)
6
6
 
@@ -497,9 +497,12 @@ npx fpscanner build --key=your-secret-key-here
497
497
  ```
498
498
 
499
499
  This will:
500
- 1. Rebuild the library with your key baked in
501
- 2. Obfuscate the output to protect the key
502
- 3. Overwrite the files in `node_modules/fpscanner/dist/`
500
+ 1. Create backups of original files (for idempotent rebuilds)
501
+ 2. Inject your encryption key into the library
502
+ 3. Obfuscate the output to protect the key
503
+ 4. Overwrite the files in `node_modules/fpscanner/dist/`
504
+
505
+ > **Note**: The build command is idempotent - you can run it multiple times safely. Original files are backed up as `.original` and restored before each build, preventing issues with re-obfuscating already-obfuscated code. This makes the build safe to use in watch mode or repeated CI/CD runs.
503
506
 
504
507
  ### Key Injection Methods
505
508
 
@@ -649,6 +652,14 @@ Make sure you're using the **exact same key** on your server that you used when
649
652
 
650
653
  Use `--no-obfuscate` during development. Only enable obfuscation for production builds.
651
654
 
655
+ ### Build fails with "heap out of memory" in watch mode
656
+
657
+ If you're running the build command repeatedly (e.g., in a watch task), this is now fixed. The build script automatically backs up and restores original files to prevent re-obfuscating already-obfuscated code. If you still encounter this issue:
658
+
659
+ 1. Update to the latest version of fpscanner
660
+ 2. Use `--no-obfuscate` for development/watch mode (recommended)
661
+ 3. Only enable obfuscation for production builds
662
+
652
663
  ### `postinstall` fails in CI
653
664
 
654
665
  Ensure `FINGERPRINT_KEY` is set as an environment variable before `npm install` runs.
@@ -1 +1 @@
1
- {"version":3,"file":"hasPlatformMismatch.d.ts","sourceRoot":"","sources":["../../src/detections/hasPlatformMismatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGvC,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,WA0C3D"}
1
+ {"version":3,"file":"hasPlatformMismatch.d.ts","sourceRoot":"","sources":["../../src/detections/hasPlatformMismatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGvC,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,WAkC3D"}
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});function ne(){return navigator.webdriver}function ie(){return navigator.userAgent}function ae(){return navigator.platform}const l="ERROR",r="INIT",s="NA",f="SKIPPED",d="high",b="low",oe="medium";function p(t){let e=0;for(let n=0,i=t.length;n<i;n++){let a=t.charCodeAt(n);e=(e<<5)-e+a,e|=0}return e.toString(16).padStart(8,"0")}function h(t,e){for(const n in t)t[n]=e}function se(){return navigator.buildID==="20181001000000"}function ce(){try{let t=!1;const e=Error.prepareStackTrace;Error.prepareStackTrace=function(){return t=!0,e};const n=new Error("");return console.log(n),t}catch{return l}}function le(){const t={vendor:r,renderer:r};if(se())return h(t,s),t;try{var e=document.createElement("canvas"),n=e.getContext("webgl")||e.getContext("experimental-webgl");n.getSupportedExtensions().indexOf("WEBGL_debug_renderer_info")>=0?(t.vendor=n.getParameter(n.getExtension("WEBGL_debug_renderer_info").UNMASKED_VENDOR_WEBGL),t.renderer=n.getParameter(n.getExtension("WEBGL_debug_renderer_info").UNMASKED_RENDERER_WEBGL)):h(t,s)}catch{h(t,l)}return t}function ue(){return"__pwInitScripts"in window||"__playwright__binding__"in window}function de(){return navigator.hardwareConcurrency||s}function he(){const t=[],e=.123456789;return["E","LN10","LN2","LOG10E","LOG2E","PI","SQRT1_2","SQRT2"].forEach(function(a){try{t.push(Math[a])}catch{t.push(-1)}}),["tan","sin","exp","atan","acosh","asinh","atanh","expm1","log1p","sinh"].forEach(function(a){try{t.push(Math[a](e))}catch{t.push(-1)}}),p(t.map(String).join(","))}function ge(){return navigator.deviceMemory||s}function me(){return eval.toString().length}function pe(){const t={timezone:r,localeLanguage:r};try{if(typeof Intl<"u"&&typeof Intl.DateTimeFormat<"u"){const e=Intl.DateTimeFormat().resolvedOptions();t.timezone=e.timeZone,t.localeLanguage=e.locale}else t.timezone=s,t.localeLanguage=s}catch{t.timezone=l,t.localeLanguage=l}return t}function fe(){return{width:window.screen.width,height:window.screen.height,pixelDepth:window.screen.pixelDepth,colorDepth:window.screen.colorDepth,availableWidth:window.screen.availWidth,availableHeight:window.screen.availHeight,innerWidth:window.innerWidth,innerHeight:window.innerHeight,hasMultipleDisplays:typeof screen.isExtended<"u"?screen.isExtended:s}}function ve(){return{languages:navigator.languages,language:navigator.language}}async function we(){const t={vendor:r,architecture:r,device:r,description:r};if("gpu"in navigator)try{const e=await navigator.gpu.requestAdapter();e&&(t.vendor=e.info.vendor,t.architecture=e.info.architecture,t.device=e.info.device,t.description=e.info.description)}catch{h(t,l)}else h(t,s);return t}function ye(){const t=["__driver_evaluate","__webdriver_evaluate","__selenium_evaluate","__fxdriver_evaluate","__driver_unwrapped","__webdriver_unwrapped","__selenium_unwrapped","__fxdriver_unwrapped","_Selenium_IDE_Recorder","_selenium","calledSelenium","$cdc_asdjflasutopfhvcZLmcfl_","$chrome_asyncScriptInfo","__$webdriverAsyncExecutor","webdriver","__webdriverFunc","domAutomation","domAutomationController","__lastWatirAlert","__lastWatirConfirm","__lastWatirPrompt","__webdriver_script_fn","_WEBDRIVER_ELEM_CACHE"];let e=!1;for(let n=0;n<t.length;n++)if(t[n]in window){e=!0;break}return e=e||!!document.__webdriver_script_fn||!!window.domAutomation||!!window.domAutomationController,e}function be(){try{const t="webdriver",e=window.navigator;if(!e[t]&&!e.hasOwnProperty(t)){e[t]=1;const n=e[t]===1;return delete e[t],n}return!0}catch{return!1}}async function Se(){const t=window.navigator,e={architecture:r,bitness:r,brands:r,mobile:r,model:r,platform:r,platformVersion:r,uaFullVersion:r};if("userAgentData"in t)try{const n=await t.userAgentData.getHighEntropyValues(["architecture","bitness","brands","mobile","model","platform","platformVersion","uaFullVersion"]);e.architecture=n.architecture,e.bitness=n.bitness,e.brands=n.brands,e.mobile=n.mobile,e.model=n.model,e.platform=n.platform,e.platformVersion=n.platformVersion,e.uaFullVersion=n.uaFullVersion}catch{h(e,l)}else h(e,s);return e}function Ce(){if(!navigator.plugins)return!1;const t=typeof navigator.plugins.toString=="function"?navigator.plugins.toString():navigator.plugins.constructor&&typeof navigator.plugins.constructor.toString=="function"?navigator.plugins.constructor.toString():typeof navigator.plugins;return t==="[object PluginArray]"||t==="[object MSPluginsCollection]"||t==="[object HTMLPluginsCollection]"}function Ae(){if(!navigator.plugins)return s;const t=[];for(let e=0;e<navigator.plugins.length;e++)t.push(navigator.plugins[e].name);return p(t.join(","))}function Pe(){return navigator.plugins?navigator.plugins.length:s}function Me(){if(!navigator.plugins)return s;try{return navigator.plugins[0]===navigator.plugins[0][0].enabledPlugin}catch{return l}}function Ee(){if(!navigator.plugins)return s;try{return navigator.plugins.item(4294967296)!==navigator.plugins[0]}catch{return l}}function We(){const t={isValidPluginArray:r,pluginCount:r,pluginNamesHash:r,pluginConsistency1:r,pluginOverflow:r};try{t.isValidPluginArray=Ce(),t.pluginCount=Pe(),t.pluginNamesHash=Ae(),t.pluginConsistency1=Me(),t.pluginOverflow=Ee()}catch{h(t,l)}return t}async function xe(){return new Promise(async function(t){var e={audiooutput:0,audioinput:0,videoinput:0};if(navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices){const a=await navigator.mediaDevices.enumerateDevices();if(typeof a<"u"){for(var n=0;n<a.length;n++){var i=a[n].kind;e[i]=e[i]+1}return t({speakers:e.audiooutput,microphones:e.audioinput,webcams:e.videoinput})}else return h(e,s),t(e)}else return h(e,s),t(e)})}function ke(){const t={webdriver:r,userAgent:r,platform:r,memory:r,cpuCount:r,language:r},e=document.createElement("iframe");let n=!1;try{e.style.display="none",e.src="about:blank",document.body.appendChild(e),n=!0;const i=e.contentWindow?.navigator;t.webdriver=i.webdriver??!1,t.userAgent=i.userAgent??s,t.platform=i.platform??s,t.memory=i.deviceMemory??s,t.cpuCount=i.hardwareConcurrency??s,t.language=i.language??s}catch{h(t,l)}finally{if(n)try{document.body.removeChild(e)}catch{}}return t}async function De(){return new Promise(t=>{const e={vendor:r,renderer:r,userAgent:r,language:r,platform:r,memory:r,cpuCount:r};let n=null,i=null,a=null;const g=()=>{a&&clearTimeout(a),n&&n.terminate(),i&&URL.revokeObjectURL(i)};try{const m=`try {
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});function ne(){return navigator.webdriver}function ie(){return navigator.userAgent}function ae(){return navigator.platform}const l="ERROR",r="INIT",s="NA",f="SKIPPED",d="high",b="low",oe="medium";function p(t){let e=0;for(let n=0,i=t.length;n<i;n++){let a=t.charCodeAt(n);e=(e<<5)-e+a,e|=0}return e.toString(16).padStart(8,"0")}function g(t,e){for(const n in t)t[n]=e}function se(){return navigator.buildID==="20181001000000"}function ce(){try{let t=!1;const e=Error.prepareStackTrace;Error.prepareStackTrace=function(){return t=!0,e};const n=new Error("");return console.log(n),t}catch{return l}}function le(){const t={vendor:r,renderer:r};if(se())return g(t,s),t;try{var e=document.createElement("canvas"),n=e.getContext("webgl")||e.getContext("experimental-webgl");n.getSupportedExtensions().indexOf("WEBGL_debug_renderer_info")>=0?(t.vendor=n.getParameter(n.getExtension("WEBGL_debug_renderer_info").UNMASKED_VENDOR_WEBGL),t.renderer=n.getParameter(n.getExtension("WEBGL_debug_renderer_info").UNMASKED_RENDERER_WEBGL)):g(t,s)}catch{g(t,l)}return t}function ue(){return"__pwInitScripts"in window||"__playwright__binding__"in window}function de(){return navigator.hardwareConcurrency||s}function ge(){const t=[],e=.123456789;return["E","LN10","LN2","LOG10E","LOG2E","PI","SQRT1_2","SQRT2"].forEach(function(a){try{t.push(Math[a])}catch{t.push(-1)}}),["tan","sin","exp","atan","acosh","asinh","atanh","expm1","log1p","sinh"].forEach(function(a){try{t.push(Math[a](e))}catch{t.push(-1)}}),p(t.map(String).join(","))}function he(){return navigator.deviceMemory||s}function me(){return eval.toString().length}function pe(){const t={timezone:r,localeLanguage:r};try{if(typeof Intl<"u"&&typeof Intl.DateTimeFormat<"u"){const e=Intl.DateTimeFormat().resolvedOptions();t.timezone=e.timeZone,t.localeLanguage=e.locale}else t.timezone=s,t.localeLanguage=s}catch{t.timezone=l,t.localeLanguage=l}return t}function fe(){return{width:window.screen.width,height:window.screen.height,pixelDepth:window.screen.pixelDepth,colorDepth:window.screen.colorDepth,availableWidth:window.screen.availWidth,availableHeight:window.screen.availHeight,innerWidth:window.innerWidth,innerHeight:window.innerHeight,hasMultipleDisplays:typeof screen.isExtended<"u"?screen.isExtended:s}}function ve(){return{languages:navigator.languages,language:navigator.language}}async function we(){const t={vendor:r,architecture:r,device:r,description:r};if("gpu"in navigator)try{const e=await navigator.gpu.requestAdapter();e&&(t.vendor=e.info.vendor,t.architecture=e.info.architecture,t.device=e.info.device,t.description=e.info.description)}catch{g(t,l)}else g(t,s);return t}function ye(){const t=["__driver_evaluate","__webdriver_evaluate","__selenium_evaluate","__fxdriver_evaluate","__driver_unwrapped","__webdriver_unwrapped","__selenium_unwrapped","__fxdriver_unwrapped","_Selenium_IDE_Recorder","_selenium","calledSelenium","$cdc_asdjflasutopfhvcZLmcfl_","$chrome_asyncScriptInfo","__$webdriverAsyncExecutor","webdriver","__webdriverFunc","domAutomation","domAutomationController","__lastWatirAlert","__lastWatirConfirm","__lastWatirPrompt","__webdriver_script_fn","_WEBDRIVER_ELEM_CACHE"];let e=!1;for(let n=0;n<t.length;n++)if(t[n]in window){e=!0;break}return e=e||!!document.__webdriver_script_fn||!!window.domAutomation||!!window.domAutomationController,e}function be(){try{const t="webdriver",e=window.navigator;if(!e[t]&&!e.hasOwnProperty(t)){e[t]=1;const n=e[t]===1;return delete e[t],n}return!0}catch{return!1}}async function Se(){const t=window.navigator,e={architecture:r,bitness:r,brands:r,mobile:r,model:r,platform:r,platformVersion:r,uaFullVersion:r};if("userAgentData"in t)try{const n=await t.userAgentData.getHighEntropyValues(["architecture","bitness","brands","mobile","model","platform","platformVersion","uaFullVersion"]);e.architecture=n.architecture,e.bitness=n.bitness,e.brands=n.brands,e.mobile=n.mobile,e.model=n.model,e.platform=n.platform,e.platformVersion=n.platformVersion,e.uaFullVersion=n.uaFullVersion}catch{g(e,l)}else g(e,s);return e}function Ce(){if(!navigator.plugins)return!1;const t=typeof navigator.plugins.toString=="function"?navigator.plugins.toString():navigator.plugins.constructor&&typeof navigator.plugins.constructor.toString=="function"?navigator.plugins.constructor.toString():typeof navigator.plugins;return t==="[object PluginArray]"||t==="[object MSPluginsCollection]"||t==="[object HTMLPluginsCollection]"}function Ae(){if(!navigator.plugins)return s;const t=[];for(let e=0;e<navigator.plugins.length;e++)t.push(navigator.plugins[e].name);return p(t.join(","))}function Pe(){return navigator.plugins?navigator.plugins.length:s}function Me(){if(!navigator.plugins)return s;try{return navigator.plugins[0]===navigator.plugins[0][0].enabledPlugin}catch{return l}}function xe(){if(!navigator.plugins)return s;try{return navigator.plugins.item(4294967296)!==navigator.plugins[0]}catch{return l}}function We(){const t={isValidPluginArray:r,pluginCount:r,pluginNamesHash:r,pluginConsistency1:r,pluginOverflow:r};try{t.isValidPluginArray=Ce(),t.pluginCount=Pe(),t.pluginNamesHash=Ae(),t.pluginConsistency1=Me(),t.pluginOverflow=xe()}catch{g(t,l)}return t}async function Ee(){return new Promise(async function(t){var e={audiooutput:0,audioinput:0,videoinput:0};if(navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices){const a=await navigator.mediaDevices.enumerateDevices();if(typeof a<"u"){for(var n=0;n<a.length;n++){var i=a[n].kind;e[i]=e[i]+1}return t({speakers:e.audiooutput,microphones:e.audioinput,webcams:e.videoinput})}else return g(e,s),t(e)}else return g(e,s),t(e)})}function ke(){const t={webdriver:r,userAgent:r,platform:r,memory:r,cpuCount:r,language:r},e=document.createElement("iframe");let n=!1;try{e.style.display="none",e.src="about:blank",document.body.appendChild(e),n=!0;const i=e.contentWindow?.navigator;t.webdriver=i.webdriver??!1,t.userAgent=i.userAgent??s,t.platform=i.platform??s,t.memory=i.deviceMemory??s,t.cpuCount=i.hardwareConcurrency??s,t.language=i.language??s}catch{g(t,l)}finally{if(n)try{document.body.removeChild(e)}catch{}}return t}async function De(){return new Promise(t=>{const e={vendor:r,renderer:r,userAgent:r,language:r,platform:r,memory:r,cpuCount:r};let n=null,i=null,a=null;const h=()=>{a&&clearTimeout(a),n&&n.terminate(),i&&URL.revokeObjectURL(i)};try{const m=`try {
2
2
  var fingerprintWorker = {};
3
3
 
4
4
  fingerprintWorker.userAgent = navigator.userAgent;
@@ -12,8 +12,9 @@
12
12
  fingerprintWorker.vendor = 'INIT';
13
13
  fingerprintWorker.renderer = 'INIT';
14
14
  var gl = canvas.getContext('webgl');
15
+ const isFirefox = navigator.userAgent.includes('Firefox');
15
16
  try {
16
- if (gl) {
17
+ if (gl && !isFirefox) {
17
18
  var glExt = gl.getExtension('WEBGL_debug_renderer_info');
18
19
  fingerprintWorker.vendor = gl.getParameter(glExt.UNMASKED_VENDOR_WEBGL);
19
20
  fingerprintWorker.renderer = gl.getParameter(glExt.UNMASKED_RENDERER_WEBGL);
@@ -28,4 +29,4 @@
28
29
  self.postMessage(fingerprintWorker);
29
30
  } catch (e) {
30
31
  self.postMessage(fingerprintWorker);
31
- }`,w=new Blob([m],{type:"application/javascript"});i=URL.createObjectURL(w),n=new Worker(i),a=window.setTimeout(()=>{g(),h(e,l),t(e)},2e3),n.onmessage=function(o){try{e.vendor=o.data.vendor,e.renderer=o.data.renderer,e.userAgent=o.data.userAgent,e.language=o.data.language,e.platform=o.data.platform,e.memory=o.data.memory,e.cpuCount=o.data.cpuCount}catch{h(e,l)}finally{g(),t(e)}},n.onerror=function(){g(),h(e,l),t(e)}}catch{g(),h(e,l),t(e)}})}function _e(){const t={toSourceError:r,hasToSource:!1};try{null.usdfsh}catch(e){t.toSourceError=e.toString()}try{throw"xyz"}catch(e){try{e.toSource(),t.hasToSource=!0}catch{t.hasToSource=!1}}return t}const S=['audio/mp4; codecs="mp4a.40.2"',"audio/mpeg;",'audio/webm; codecs="vorbis"','audio/ogg; codecs="vorbis"','audio/wav; codecs="1"','audio/ogg; codecs="speex"','audio/ogg; codecs="flac"','audio/3gpp; codecs="samr"'],C=['video/mp4; codecs="avc1.42E01E, mp4a.40.2"','video/mp4; codecs="avc1.42E01E"','video/mp4; codecs="avc1.58A01E"','video/mp4; codecs="avc1.4D401E"','video/mp4; codecs="avc1.64001E"','video/mp4; codecs="mp4v.20.8"','video/mp4; codecs="mp4v.20.240"','video/webm; codecs="vp8"','video/ogg; codecs="theora"','video/ogg; codecs="dirac"','video/3gpp; codecs="mp4v.20.8"','video/x-matroska; codecs="theora"'];function A(t,e){const n={};try{const i=document.createElement(e);for(const a of t)try{n[a]=i.canPlayType(a)||null}catch{n[a]=null}}catch{for(const i of t)n[i]=null}return n}function P(t){const e={},n=window.MediaSource;if(!n||typeof n.isTypeSupported!="function"){for(const i of t)e[i]=null;return e}for(const i of t)try{e[i]=n.isTypeSupported(i)}catch{e[i]=null}return e}function M(t){try{const e=window.RTCRtpReceiver;if(e&&typeof e.getCapabilities=="function"){const n=e.getCapabilities(t);return p(JSON.stringify(n))}return s}catch{return l}}function Re(){const t={audioCanPlayTypeHash:s,videoCanPlayTypeHash:s,audioMediaSourceHash:s,videoMediaSourceHash:s,rtcAudioCapabilitiesHash:s,rtcVideoCapabilitiesHash:s,hasMediaSource:!1};try{t.hasMediaSource=!!window.MediaSource;const e=A(S,"audio"),n=A(C,"video");t.audioCanPlayTypeHash=p(JSON.stringify(e)),t.videoCanPlayTypeHash=p(JSON.stringify(n));const i=P(S),a=P(C);t.audioMediaSourceHash=p(JSON.stringify(i)),t.videoMediaSourceHash=p(JSON.stringify(a)),t.rtcAudioCapabilitiesHash=M("audio"),t.rtcVideoCapabilitiesHash=M("video")}catch{h(t,l)}return t}async function Ie(){return new Promise(t=>{try{const e=new Image,n=document.createElement("canvas").getContext("2d");e.onload=()=>{n.drawImage(e,0,0),t(n.getImageData(0,0,1,1).data.filter(i=>i===0).length!=4)},e.onerror=()=>{t(l)},e.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAUAAarVyFEAAAAASUVORK5CYII="}catch{t(l)}})}function Te(){var t=document.createElement("canvas");t.width=400,t.height=200,t.style.display="inline";var e=t.getContext("2d");try{return e.rect(0,0,10,10),e.rect(2,2,6,6),e.textBaseline="alphabetic",e.fillStyle="#f60",e.fillRect(125,1,62,20),e.fillStyle="#069",e.font="11pt no-real-font-123",e.fillText("Cwm fjordbank glyphs vext quiz, 😃",2,15),e.fillStyle="rgba(102, 204, 0, 0.2)",e.font="18pt Arial",e.fillText("Cwm fjordbank glyphs vext quiz, 😃",4,45),e.globalCompositeOperation="multiply",e.fillStyle="rgb(255,0,255)",e.beginPath(),e.arc(50,50,50,0,2*Math.PI,!0),e.closePath(),e.fill(),e.fillStyle="rgb(0,255,255)",e.beginPath(),e.arc(100,50,50,0,2*Math.PI,!0),e.closePath(),e.fill(),e.fillStyle="rgb(255,255,0)",e.beginPath(),e.arc(75,100,50,0,2*Math.PI,!0),e.closePath(),e.fill(),e.fillStyle="rgb(255,0,255)",e.arc(75,75,75,0,2*Math.PI,!0),e.arc(75,75,25,0,2*Math.PI,!0),e.fill("evenodd"),p(t.toDataURL())}catch{return l}}async function Le(){const t={hasModifiedCanvas:r,canvasFingerprint:r};return t.hasModifiedCanvas=await Ie(),t.canvasFingerprint=Te(),t}function Oe(){const t=["deviceMemory","hardwareConcurrency","language","languages","platform"],e=[];for(const n of t){const i=Object.getOwnPropertyDescriptor(Object.getPrototypeOf(navigator),n);i&&i.value?e.push("1"):e.push("0")}return e.join("")}function He(){return Math.random().toString(36).substring(2,15)}function Ue(){return new Date().getTime()}function Ve(){return window.location.href}function E(t,e){const n=t.signals;return e==="iframe"?n.contexts.iframe.webdriver!==n.automation.webdriver||n.contexts.iframe.userAgent!==n.browser.userAgent||n.contexts.iframe.platform!==n.device.platform||n.contexts.iframe.memory!==n.device.memory||n.contexts.iframe.cpuCount!==n.device.cpuCount:n.contexts.webWorker.webdriver!==n.automation.webdriver||n.contexts.webWorker.userAgent!==n.browser.userAgent||n.contexts.webWorker.platform!==n.device.platform||n.contexts.webWorker.memory!==n.device.memory||n.contexts.webWorker.cpuCount!==n.device.cpuCount}function Fe(){const t={bitmask:r,extensions:[]},e=document.body.hasAttribute("data-gr-ext-installed"),n=typeof window.ethereum<"u",i=document.getElementById("coupon-birds-drop-div")!==null,a=document.querySelector("deepl-input-controller")!==null,g=document.getElementById("monica-content-root")!==null,m=document.querySelector("chatgpt-sidebar")!==null,w=typeof window.__REQUESTLY__<"u",o=Array.from(document.querySelectorAll("*")).filter(v=>v.tagName.toLowerCase().startsWith("veepn-")).length>0;return t.bitmask=[e?"1":"0",n?"1":"0",i?"1":"0",a?"1":"0",g?"1":"0",m?"1":"0",w?"1":"0",o?"1":"0"].join(""),e&&t.extensions.push("grammarly"),n&&t.extensions.push("metamask"),i&&t.extensions.push("coupon-birds"),a&&t.extensions.push("deepl"),g&&t.extensions.push("monica-ai"),m&&t.extensions.push("sider-ai"),w&&t.extensions.push("requestly"),o&&t.extensions.push("veepn"),t}function c(t){try{return t()}catch{return!1}}function Ge(){const t={bitmask:r,chrome:c(()=>"chrome"in window),brave:c(()=>"brave"in navigator),applePaySupport:c(()=>"ApplePaySetup"in window),opera:c(()=>typeof window.opr<"u"||typeof window.onoperadetachedviewchange=="object"),serial:c(()=>window.navigator.serial!==void 0),attachShadow:c(()=>!!Element.prototype.attachShadow),caches:c(()=>!!window.caches),webAssembly:c(()=>!!window.WebAssembly&&!!window.WebAssembly.instantiate),buffer:c(()=>"Buffer"in window),showModalDialog:c(()=>"showModalDialog"in window),safari:c(()=>"safari"in window),webkitPrefixedFunction:c(()=>"webkitCancelAnimationFrame"in window),mozPrefixedFunction:c(()=>"mozGetUserMedia"in navigator),usb:c(()=>typeof window.USB=="function"),browserCapture:c(()=>typeof window.BrowserCaptureMediaStreamTrack=="function"),paymentRequestUpdateEvent:c(()=>typeof window.PaymentRequestUpdateEvent=="function"),pressureObserver:c(()=>typeof window.PressureObserver=="function"),audioSession:c(()=>"audioSession"in navigator),selectAudioOutput:c(()=>typeof navigator<"u"&&typeof navigator.mediaDevices<"u"&&typeof navigator.mediaDevices.selectAudioOutput=="function"),barcodeDetector:c(()=>"BarcodeDetector"in window),battery:c(()=>"getBattery"in navigator),devicePosture:c(()=>"DevicePosture"in window),documentPictureInPicture:c(()=>"documentPictureInPicture"in window),eyeDropper:c(()=>"EyeDropper"in window),editContext:c(()=>"EditContext"in window),fencedFrame:c(()=>"FencedFrameConfig"in window),sanitizer:c(()=>"Sanitizer"in window),otpCredential:c(()=>"OTPCredential"in window)},e=Object.keys(t).filter(n=>n!=="bitmask").map(n=>t[n]?"1":"0").join("");return t.bitmask=e,t}function je(){const t={prefersColorScheme:r,prefersReducedMotion:r,prefersReducedTransparency:r,colorGamut:r,pointer:r,anyPointer:r,hover:r,anyHover:r,colorDepth:r};try{window.matchMedia("(prefers-color-scheme: dark)").matches?t.prefersColorScheme="dark":window.matchMedia("(prefers-color-scheme: light)").matches?t.prefersColorScheme="light":t.prefersColorScheme=null,t.prefersReducedMotion=window.matchMedia("(prefers-reduced-motion: reduce)").matches,t.prefersReducedTransparency=window.matchMedia("(prefers-reduced-transparency: reduce)").matches,window.matchMedia("(color-gamut: rec2020)").matches?t.colorGamut="rec2020":window.matchMedia("(color-gamut: p3)").matches?t.colorGamut="p3":window.matchMedia("(color-gamut: srgb)").matches?t.colorGamut="srgb":t.colorGamut=null,window.matchMedia("(pointer: fine)").matches?t.pointer="fine":window.matchMedia("(pointer: coarse)").matches?t.pointer="coarse":window.matchMedia("(pointer: none)").matches?t.pointer="none":t.pointer=null,window.matchMedia("(any-pointer: fine)").matches?t.anyPointer="fine":window.matchMedia("(any-pointer: coarse)").matches?t.anyPointer="coarse":window.matchMedia("(any-pointer: none)").matches?t.anyPointer="none":t.anyPointer=null,t.hover=window.matchMedia("(hover: hover)").matches,t.anyHover=window.matchMedia("(any-hover: hover)").matches;let e=0;for(let n=0;n<=16;n++)window.matchMedia(`(color: ${n})`).matches&&(e=n);t.colorDepth=e}catch{h(t,l)}return t}function Be(t){const e=t.signals.device.screenResolution;return e.width===600&&e.height===800||e.availableWidth===600&&e.availableHeight===800||e.innerWidth===600&&e.innerHeight===800}function Ne(t){return t.signals.automation.webdriver===!0}function ze(t){return!!t.signals.automation.selenium}function $e(t){return t.signals.automation.cdp===!0}function Qe(t){return t.signals.automation.playwright===!0}function qe(t){return typeof t.signals.device.memory!="number"?!1:t.signals.device.memory>32||t.signals.device.memory<.25}function Ke(t){return typeof t.signals.device.cpuCount!="number"?!1:t.signals.device.cpuCount>70}function Je(t){const e=t.signals.browser.userAgent;return t.signals.browser.features.chrome===!1&&typeof e=="string"&&e.includes("Chrome")}function Ye(t){return t.signals.contexts.iframe.webdriver===!0}function Ze(t){return t.signals.contexts.webWorker.webdriver===!0}function Xe(t){const e=t.signals.contexts.webWorker,n=t.signals.graphics.webGL;return e.vendor===l||e.renderer===l||n.vendor===s||n.renderer===s||e.vendor===f?!1:e.vendor!==n.vendor||e.renderer!==n.renderer}function et(t){return t.signals.contexts.webWorker.platform===s||t.signals.contexts.webWorker.platform===l||t.signals.contexts.webWorker.platform===f?!1:t.signals.device.platform!==t.signals.contexts.webWorker.platform}function tt(t){return t.signals.contexts.iframe.platform===s||t.signals.contexts.iframe.platform===l?!1:t.signals.device.platform!==t.signals.contexts.iframe.platform}function rt(t){return t.signals.automation.webdriverWritable===!0}function nt(t){return t.signals.graphics.webGL.renderer.includes("SwiftShader")}function it(t){return t.signals.locale.internationalization.timezone==="UTC"}function at(t){const e=t.signals.locale.languages.languages,n=t.signals.locale.languages.language;return n&&e&&Array.isArray(e)&&e.length>0?e[0]!==n:!1}function ot(t){return!!(t.signals.browser.features.chrome&&t.signals.browser.etsl!==33||t.signals.browser.features.safari&&t.signals.browser.etsl!==37||t.signals.browser.userAgent.includes("Firefox")&&t.signals.browser.etsl!==37)}function st(t){return[t.signals.browser.userAgent,t.signals.contexts.iframe.userAgent,t.signals.contexts.webWorker.userAgent].some(n=>/bot|headless/i.test(n.toLowerCase()))}function ct(t){const e=t.signals.graphics.webgpu,n=t.signals.graphics.webGL,i=t.signals.browser.userAgent;return!!((n.vendor.includes("Apple")||n.renderer.includes("Apple"))&&!i.includes("Mac")||e.vendor.includes("apple")&&!i.includes("Mac")||e.vendor.includes("apple")&&!n.renderer.includes("Apple"))}function lt(t){const e=t.signals.device.platform,n=t.signals.browser.userAgent,i=t.signals.browser.highEntropyValues.platform;return!!(n.includes("Mac")&&!e.includes("Mac")||n.includes("Windows")&&!e.includes("Win")||n.includes("Linux")&&!e.includes("Linux")||i!==l&&i!==s&&(i.includes("Mac")&&!e.includes("Mac")||i.includes("Windows")&&!e.includes("Win")||i.includes("Linux")&&!e.includes("Linux")||i.includes("Android")&&!e.includes("Android")||i.includes("iOS")&&!e.includes("iOS")))}async function ut(t,e){const n=new TextEncoder().encode(e),i=new TextEncoder().encode(t),a=new Uint8Array(i.length);for(let m=0;m<i.length;m++)a[m]=i[m]^n[m%n.length];const g=String.fromCharCode(...a);return btoa(g)}class dt{constructor(){this.fingerprint={signals:{automation:{webdriver:r,webdriverWritable:r,selenium:r,cdp:r,playwright:r,navigatorPropertyDescriptors:r},device:{cpuCount:r,memory:r,platform:r,screenResolution:{width:r,height:r,pixelDepth:r,colorDepth:r,availableWidth:r,availableHeight:r,innerWidth:r,innerHeight:r,hasMultipleDisplays:r},multimediaDevices:{speakers:r,microphones:r,webcams:r},mediaQueries:{prefersColorScheme:r,prefersReducedMotion:r,prefersReducedTransparency:r,colorGamut:r,pointer:r,anyPointer:r,hover:r,anyHover:r,colorDepth:r}},browser:{userAgent:r,features:{bitmask:r,chrome:r,brave:r,applePaySupport:r,opera:r,serial:r,attachShadow:r,caches:r,webAssembly:r,buffer:r,showModalDialog:r,safari:r,webkitPrefixedFunction:r,mozPrefixedFunction:r,usb:r,browserCapture:r,paymentRequestUpdateEvent:r,pressureObserver:r,audioSession:r,selectAudioOutput:r,barcodeDetector:r,battery:r,devicePosture:r,documentPictureInPicture:r,eyeDropper:r,editContext:r,fencedFrame:r,sanitizer:r,otpCredential:r},plugins:{isValidPluginArray:r,pluginCount:r,pluginNamesHash:r,pluginConsistency1:r,pluginOverflow:r},extensions:{bitmask:r,extensions:r},highEntropyValues:{architecture:r,bitness:r,brands:r,mobile:r,model:r,platform:r,platformVersion:r,uaFullVersion:r},etsl:r,maths:r,toSourceError:{toSourceError:r,hasToSource:r}},graphics:{webGL:{vendor:r,renderer:r},webgpu:{vendor:r,architecture:r,device:r,description:r},canvas:{hasModifiedCanvas:r,canvasFingerprint:r}},codecs:{audioCanPlayTypeHash:r,videoCanPlayTypeHash:r,audioMediaSourceHash:r,videoMediaSourceHash:r,rtcAudioCapabilitiesHash:r,rtcVideoCapabilitiesHash:r,hasMediaSource:r},locale:{internationalization:{timezone:r,localeLanguage:r},languages:{languages:r,language:r}},contexts:{iframe:{webdriver:r,userAgent:r,platform:r,memory:r,cpuCount:r,language:r},webWorker:{webdriver:r,userAgent:r,platform:r,memory:r,cpuCount:r,language:r,vendor:r,renderer:r}}},fsid:r,nonce:r,time:r,url:r,fastBotDetection:!1,fastBotDetectionDetails:{headlessChromeScreenResolution:{detected:!1,severity:"high"},hasWebdriver:{detected:!1,severity:"high"},hasWebdriverWritable:{detected:!1,severity:"high"},hasSeleniumProperty:{detected:!1,severity:"high"},hasCDP:{detected:!1,severity:"high"},hasPlaywright:{detected:!1,severity:"high"},hasImpossibleDeviceMemory:{detected:!1,severity:"high"},hasHighCPUCount:{detected:!1,severity:"high"},hasMissingChromeObject:{detected:!1,severity:"high"},hasWebdriverIframe:{detected:!1,severity:"high"},hasWebdriverWorker:{detected:!1,severity:"high"},hasMismatchWebGLInWorker:{detected:!1,severity:"high"},hasMismatchPlatformIframe:{detected:!1,severity:"high"},hasMismatchPlatformWorker:{detected:!1,severity:"high"},hasSwiftshaderRenderer:{detected:!1,severity:"low"},hasUTCTimezone:{detected:!1,severity:"medium"},hasMismatchLanguages:{detected:!1,severity:"low"},hasInconsistentEtsl:{detected:!1,severity:"high"},hasBotUserAgent:{detected:!1,severity:"high"},hasGPUMismatch:{detected:!1,severity:"high"},hasPlatformMismatch:{detected:!1,severity:"high"}}}}async collectSignal(e){try{return await e()}catch{return l}}generateFingerprintScannerId(){try{const e=this.fingerprint.signals,n=this.fingerprint.fastBotDetectionDetails,i="FS1",g=[n.headlessChromeScreenResolution.detected,n.hasWebdriver.detected,n.hasWebdriverWritable.detected,n.hasSeleniumProperty.detected,n.hasCDP.detected,n.hasPlaywright.detected,n.hasImpossibleDeviceMemory.detected,n.hasHighCPUCount.detected,n.hasMissingChromeObject.detected,n.hasWebdriverIframe.detected,n.hasWebdriverWorker.detected,n.hasMismatchWebGLInWorker.detected,n.hasMismatchPlatformIframe.detected,n.hasMismatchPlatformWorker.detected,n.hasSwiftshaderRenderer.detected,n.hasUTCTimezone.detected,n.hasMismatchLanguages.detected,n.hasInconsistentEtsl.detected,n.hasBotUserAgent.detected,n.hasGPUMismatch.detected,n.hasPlatformMismatch.detected].map(u=>u?"1":"0").join(""),m=[e.automation.webdriver===!0,e.automation.webdriverWritable===!0,e.automation.selenium===!0,e.automation.cdp===!0,e.automation.playwright===!0].map(u=>u?"1":"0").join(""),w=p(String(e.automation.navigatorPropertyDescriptors)).slice(0,4),o=`${m}h${w}`,v=typeof e.device.screenResolution.width=="number"?e.device.screenResolution.width:0,y=typeof e.device.screenResolution.height=="number"?e.device.screenResolution.height:0,W=typeof e.device.cpuCount=="number"?String(e.device.cpuCount).padStart(2,"0"):"00",x=typeof e.device.memory=="number"?String(Math.round(e.device.memory)).padStart(2,"0"):"00",k=[e.device.screenResolution.hasMultipleDisplays===!0,e.device.mediaQueries.prefersReducedMotion===!0,e.device.mediaQueries.prefersReducedTransparency===!0,e.device.mediaQueries.hover===!0,e.device.mediaQueries.anyHover===!0].map(u=>u?"1":"0").join(""),D=[e.device.platform,e.device.screenResolution.pixelDepth,e.device.screenResolution.colorDepth,e.device.multimediaDevices.speakers,e.device.multimediaDevices.microphones,e.device.multimediaDevices.webcams,e.device.mediaQueries.prefersColorScheme,e.device.mediaQueries.colorGamut,e.device.mediaQueries.pointer,e.device.mediaQueries.anyPointer,e.device.mediaQueries.colorDepth].map(u=>String(u)).join("|"),_=p(D).slice(0,6),R=`${v}x${y}c${W}m${x}b${k}h${_}`,I=typeof e.browser.features.bitmask=="string"?e.browser.features.bitmask:"0000000000",T=typeof e.browser.extensions.bitmask=="string"?e.browser.extensions.bitmask:"00000000",L=[e.browser.plugins.isValidPluginArray===!0,e.browser.plugins.pluginConsistency1===!0,e.browser.plugins.pluginOverflow===!0,e.browser.toSourceError.hasToSource===!0].map(u=>u?"1":"0").join(""),O=[e.browser.userAgent,e.browser.etsl,e.browser.maths,e.browser.plugins.pluginCount,e.browser.plugins.pluginNamesHash,e.browser.toSourceError.toSourceError,e.browser.highEntropyValues.architecture,e.browser.highEntropyValues.bitness,e.browser.highEntropyValues.platform,e.browser.highEntropyValues.platformVersion,e.browser.highEntropyValues.uaFullVersion,e.browser.highEntropyValues.mobile].map(u=>String(u)).join("|"),H=p(O).slice(0,6),U=`f${I}e${T}p${L}h${H}`,V=[e.graphics.canvas.hasModifiedCanvas===!0].map(u=>u?"1":"0").join(""),F=[e.graphics.webGL.vendor,e.graphics.webGL.renderer,e.graphics.webgpu.vendor,e.graphics.webgpu.architecture,e.graphics.webgpu.device,e.graphics.webgpu.description,e.graphics.canvas.canvasFingerprint].map(u=>String(u)).join("|"),G=p(F).slice(0,6),j=`${V}h${G}`,B=[e.codecs.hasMediaSource===!0].map(u=>u?"1":"0").join(""),N=[e.codecs.audioCanPlayTypeHash,e.codecs.videoCanPlayTypeHash,e.codecs.audioMediaSourceHash,e.codecs.videoMediaSourceHash,e.codecs.rtcAudioCapabilitiesHash,e.codecs.rtcVideoCapabilitiesHash].map(u=>String(u)).join("|"),z=p(N).slice(0,6),$=`${B}h${z}`,Q=typeof e.locale.languages.language=="string"?e.locale.languages.language.slice(0,2).toLowerCase():"xx",q=Array.isArray(e.locale.languages.languages)?e.locale.languages.languages.length:0,K=(typeof e.locale.internationalization.timezone=="string"?e.locale.internationalization.timezone:"unknown").replace(/[\/\s]/g,"-"),J=[e.locale.internationalization.timezone,e.locale.internationalization.localeLanguage,Array.isArray(e.locale.languages.languages)?e.locale.languages.languages.join(","):e.locale.languages.languages,e.locale.languages.language].map(u=>String(u)).join("|"),Y=p(J).slice(0,4),Z=`${Q}${q}t${K}_h${Y}`,X=[E(this.fingerprint,"iframe"),E(this.fingerprint,"worker"),e.contexts.iframe.webdriver===!0,e.contexts.webWorker.webdriver===!0].map(u=>u?"1":"0").join(""),ee=[e.contexts.iframe.userAgent,e.contexts.iframe.platform,e.contexts.iframe.memory,e.contexts.iframe.cpuCount,e.contexts.iframe.language,e.contexts.webWorker.userAgent,e.contexts.webWorker.platform,e.contexts.webWorker.memory,e.contexts.webWorker.cpuCount,e.contexts.webWorker.language,e.contexts.webWorker.vendor,e.contexts.webWorker.renderer].map(u=>String(u)).join("|"),te=p(ee).slice(0,6),re=`${X}h${te}`;return[i,g,o,R,U,j,$,Z,re].join("_")}catch(e){return console.error("Error generating fingerprint scanner id",e),l}}async encryptFingerprint(e){const n="__DEFAULT_FPSCANNER_KEY__";return n.length>20&&n.indexOf("DEFAULT")>0&&n.indexOf("FPSCANNER")>0&&console.warn('[fpscanner] WARNING: Using default encryption key! Run "npx fpscanner build --key=your-secret-key" to inject your own key. See: https://github.com/antoinevastel/fpscanner#advanced-custom-builds'),await ut(JSON.stringify(e),n)}getDetectionRules(){return[{name:"headlessChromeScreenResolution",severity:d,test:Be},{name:"hasWebdriver",severity:d,test:Ne},{name:"hasWebdriverWritable",severity:d,test:rt},{name:"hasSeleniumProperty",severity:d,test:ze},{name:"hasCDP",severity:d,test:$e},{name:"hasPlaywright",severity:d,test:Qe},{name:"hasImpossibleDeviceMemory",severity:d,test:qe},{name:"hasHighCPUCount",severity:d,test:Ke},{name:"hasMissingChromeObject",severity:d,test:Je},{name:"hasWebdriverIframe",severity:d,test:Ye},{name:"hasWebdriverWorker",severity:d,test:Ze},{name:"hasMismatchWebGLInWorker",severity:d,test:Xe},{name:"hasMismatchPlatformIframe",severity:d,test:tt},{name:"hasMismatchPlatformWorker",severity:d,test:et},{name:"hasSwiftshaderRenderer",severity:b,test:nt},{name:"hasUTCTimezone",severity:oe,test:it},{name:"hasMismatchLanguages",severity:b,test:at},{name:"hasInconsistentEtsl",severity:d,test:ot},{name:"hasBotUserAgent",severity:d,test:st},{name:"hasGPUMismatch",severity:d,test:ct},{name:"hasPlatformMismatch",severity:d,test:lt}]}runDetectionRules(){const e=this.getDetectionRules(),n={headlessChromeScreenResolution:{detected:!1,severity:"high"},hasWebdriver:{detected:!1,severity:"high"},hasWebdriverWritable:{detected:!1,severity:"high"},hasSeleniumProperty:{detected:!1,severity:"high"},hasCDP:{detected:!1,severity:"high"},hasPlaywright:{detected:!1,severity:"high"},hasImpossibleDeviceMemory:{detected:!1,severity:"high"},hasHighCPUCount:{detected:!1,severity:"high"},hasMissingChromeObject:{detected:!1,severity:"high"},hasWebdriverIframe:{detected:!1,severity:"high"},hasWebdriverWorker:{detected:!1,severity:"high"},hasMismatchWebGLInWorker:{detected:!1,severity:"high"},hasMismatchPlatformIframe:{detected:!1,severity:"high"},hasMismatchPlatformWorker:{detected:!1,severity:"high"},hasSwiftshaderRenderer:{detected:!1,severity:"low"},hasUTCTimezone:{detected:!1,severity:"medium"},hasMismatchLanguages:{detected:!1,severity:"low"},hasInconsistentEtsl:{detected:!1,severity:"high"},hasBotUserAgent:{detected:!1,severity:"high"},hasGPUMismatch:{detected:!1,severity:"high"},hasPlatformMismatch:{detected:!1,severity:"high"}};for(const i of e)try{const a=i.test(this.fingerprint);n[i.name]={detected:a,severity:i.severity}}catch{n[i.name]={detected:!1,severity:i.severity}}return n}async collectFingerprint(e={encrypt:!0}){const{encrypt:n=!0,skipWorker:i=!1}=e,a=this.fingerprint.signals,g={webdriver:this.collectSignal(ne),webdriverWritable:this.collectSignal(be),selenium:this.collectSignal(ye),cdp:this.collectSignal(ce),playwright:this.collectSignal(ue),navigatorPropertyDescriptors:this.collectSignal(Oe),cpuCount:this.collectSignal(de),memory:this.collectSignal(ge),platform:this.collectSignal(ae),screenResolution:this.collectSignal(fe),multimediaDevices:this.collectSignal(xe),mediaQueries:this.collectSignal(je),userAgent:this.collectSignal(ie),browserFeatures:this.collectSignal(Ge),plugins:this.collectSignal(We),browserExtensions:this.collectSignal(Fe),highEntropyValues:this.collectSignal(Se),etsl:this.collectSignal(me),maths:this.collectSignal(he),toSourceError:this.collectSignal(_e),webGL:this.collectSignal(le),webgpu:this.collectSignal(we),canvas:this.collectSignal(Le),mediaCodecs:this.collectSignal(Re),internationalization:this.collectSignal(pe),languages:this.collectSignal(ve),iframe:this.collectSignal(ke),webWorker:i?Promise.resolve({webdriver:f,userAgent:f,platform:f,memory:f,cpuCount:f,language:f,vendor:f,renderer:f}):this.collectSignal(De),nonce:this.collectSignal(He),time:this.collectSignal(Ue),url:this.collectSignal(Ve)},m=Object.keys(g),w=await Promise.all(Object.values(g)),o=Object.fromEntries(m.map((v,y)=>[v,w[y]]));return a.automation.webdriver=o.webdriver,a.automation.webdriverWritable=o.webdriverWritable,a.automation.selenium=o.selenium,a.automation.cdp=o.cdp,a.automation.playwright=o.playwright,a.automation.navigatorPropertyDescriptors=o.navigatorPropertyDescriptors,a.device.cpuCount=o.cpuCount,a.device.memory=o.memory,a.device.platform=o.platform,a.device.screenResolution=o.screenResolution,a.device.multimediaDevices=o.multimediaDevices,a.device.mediaQueries=o.mediaQueries,a.browser.userAgent=o.userAgent,a.browser.features=o.browserFeatures,a.browser.plugins=o.plugins,a.browser.extensions=o.browserExtensions,a.browser.highEntropyValues=o.highEntropyValues,a.browser.etsl=o.etsl,a.browser.maths=o.maths,a.browser.toSourceError=o.toSourceError,a.graphics.webGL=o.webGL,a.graphics.webgpu=o.webgpu,a.graphics.canvas=o.canvas,a.codecs=o.mediaCodecs,a.locale.internationalization=o.internationalization,a.locale.languages=o.languages,a.contexts.iframe=o.iframe,a.contexts.webWorker=o.webWorker,this.fingerprint.nonce=o.nonce,this.fingerprint.time=o.time,this.fingerprint.url=o.url,this.fingerprint.fastBotDetectionDetails=this.runDetectionRules(),this.fingerprint.fastBotDetection=Object.values(this.fingerprint.fastBotDetectionDetails).some(v=>v.detected),this.fingerprint.fsid=this.generateFingerprintScannerId(),n?await this.encryptFingerprint(JSON.stringify(this.fingerprint)):this.fingerprint}}exports.default=dt;
32
+ }`,w=new Blob([m],{type:"application/javascript"});i=URL.createObjectURL(w),n=new Worker(i),a=window.setTimeout(()=>{h(),g(e,l),t(e)},2e3),n.onmessage=function(o){try{e.vendor=o.data.vendor,e.renderer=o.data.renderer,e.userAgent=o.data.userAgent,e.language=o.data.language,e.platform=o.data.platform,e.memory=o.data.memory,e.cpuCount=o.data.cpuCount}catch{g(e,l)}finally{h(),t(e)}},n.onerror=function(){h(),g(e,l),t(e)}}catch{h(),g(e,l),t(e)}})}function _e(){const t={toSourceError:r,hasToSource:!1};try{null.usdfsh}catch(e){t.toSourceError=e.toString()}try{throw"xyz"}catch(e){try{e.toSource(),t.hasToSource=!0}catch{t.hasToSource=!1}}return t}const S=['audio/mp4; codecs="mp4a.40.2"',"audio/mpeg;",'audio/webm; codecs="vorbis"','audio/ogg; codecs="vorbis"','audio/wav; codecs="1"','audio/ogg; codecs="speex"','audio/ogg; codecs="flac"','audio/3gpp; codecs="samr"'],C=['video/mp4; codecs="avc1.42E01E, mp4a.40.2"','video/mp4; codecs="avc1.42E01E"','video/mp4; codecs="avc1.58A01E"','video/mp4; codecs="avc1.4D401E"','video/mp4; codecs="avc1.64001E"','video/mp4; codecs="mp4v.20.8"','video/mp4; codecs="mp4v.20.240"','video/webm; codecs="vp8"','video/ogg; codecs="theora"','video/ogg; codecs="dirac"','video/3gpp; codecs="mp4v.20.8"','video/x-matroska; codecs="theora"'];function A(t,e){const n={};try{const i=document.createElement(e);for(const a of t)try{n[a]=i.canPlayType(a)||null}catch{n[a]=null}}catch{for(const i of t)n[i]=null}return n}function P(t){const e={},n=window.MediaSource;if(!n||typeof n.isTypeSupported!="function"){for(const i of t)e[i]=null;return e}for(const i of t)try{e[i]=n.isTypeSupported(i)}catch{e[i]=null}return e}function M(t){try{const e=window.RTCRtpReceiver;if(e&&typeof e.getCapabilities=="function"){const n=e.getCapabilities(t);return p(JSON.stringify(n))}return s}catch{return l}}function Re(){const t={audioCanPlayTypeHash:s,videoCanPlayTypeHash:s,audioMediaSourceHash:s,videoMediaSourceHash:s,rtcAudioCapabilitiesHash:s,rtcVideoCapabilitiesHash:s,hasMediaSource:!1};try{t.hasMediaSource=!!window.MediaSource;const e=A(S,"audio"),n=A(C,"video");t.audioCanPlayTypeHash=p(JSON.stringify(e)),t.videoCanPlayTypeHash=p(JSON.stringify(n));const i=P(S),a=P(C);t.audioMediaSourceHash=p(JSON.stringify(i)),t.videoMediaSourceHash=p(JSON.stringify(a)),t.rtcAudioCapabilitiesHash=M("audio"),t.rtcVideoCapabilitiesHash=M("video")}catch{g(t,l)}return t}async function Ie(){return new Promise(t=>{try{const e=new Image,n=document.createElement("canvas").getContext("2d");e.onload=()=>{n.drawImage(e,0,0),t(n.getImageData(0,0,1,1).data.filter(i=>i===0).length!=4)},e.onerror=()=>{t(l)},e.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAUAAarVyFEAAAAASUVORK5CYII="}catch{t(l)}})}function Te(){var t=document.createElement("canvas");t.width=400,t.height=200,t.style.display="inline";var e=t.getContext("2d");try{return e.rect(0,0,10,10),e.rect(2,2,6,6),e.textBaseline="alphabetic",e.fillStyle="#f60",e.fillRect(125,1,62,20),e.fillStyle="#069",e.font="11pt no-real-font-123",e.fillText("Cwm fjordbank glyphs vext quiz, 😃",2,15),e.fillStyle="rgba(102, 204, 0, 0.2)",e.font="18pt Arial",e.fillText("Cwm fjordbank glyphs vext quiz, 😃",4,45),e.globalCompositeOperation="multiply",e.fillStyle="rgb(255,0,255)",e.beginPath(),e.arc(50,50,50,0,2*Math.PI,!0),e.closePath(),e.fill(),e.fillStyle="rgb(0,255,255)",e.beginPath(),e.arc(100,50,50,0,2*Math.PI,!0),e.closePath(),e.fill(),e.fillStyle="rgb(255,255,0)",e.beginPath(),e.arc(75,100,50,0,2*Math.PI,!0),e.closePath(),e.fill(),e.fillStyle="rgb(255,0,255)",e.arc(75,75,75,0,2*Math.PI,!0),e.arc(75,75,25,0,2*Math.PI,!0),e.fill("evenodd"),p(t.toDataURL())}catch{return l}}async function Le(){const t={hasModifiedCanvas:r,canvasFingerprint:r};return t.hasModifiedCanvas=await Ie(),t.canvasFingerprint=Te(),t}function Oe(){const t=["deviceMemory","hardwareConcurrency","language","languages","platform"],e=[];for(const n of t){const i=Object.getOwnPropertyDescriptor(Object.getPrototypeOf(navigator),n);i&&i.value?e.push("1"):e.push("0")}return e.join("")}function He(){return Math.random().toString(36).substring(2,15)}function Fe(){return new Date().getTime()}function Ue(){return window.location.href}function x(t,e){const n=t.signals;return e==="iframe"?n.contexts.iframe.webdriver!==n.automation.webdriver||n.contexts.iframe.userAgent!==n.browser.userAgent||n.contexts.iframe.platform!==n.device.platform||n.contexts.iframe.memory!==n.device.memory||n.contexts.iframe.cpuCount!==n.device.cpuCount:n.contexts.webWorker.webdriver!==n.automation.webdriver||n.contexts.webWorker.userAgent!==n.browser.userAgent||n.contexts.webWorker.platform!==n.device.platform||n.contexts.webWorker.memory!==n.device.memory||n.contexts.webWorker.cpuCount!==n.device.cpuCount}function Ve(){const t={bitmask:r,extensions:[]},e=document.body.hasAttribute("data-gr-ext-installed"),n=typeof window.ethereum<"u",i=document.getElementById("coupon-birds-drop-div")!==null,a=document.querySelector("deepl-input-controller")!==null,h=document.getElementById("monica-content-root")!==null,m=document.querySelector("chatgpt-sidebar")!==null,w=typeof window.__REQUESTLY__<"u",o=Array.from(document.querySelectorAll("*")).filter(v=>v.tagName.toLowerCase().startsWith("veepn-")).length>0;return t.bitmask=[e?"1":"0",n?"1":"0",i?"1":"0",a?"1":"0",h?"1":"0",m?"1":"0",w?"1":"0",o?"1":"0"].join(""),e&&t.extensions.push("grammarly"),n&&t.extensions.push("metamask"),i&&t.extensions.push("coupon-birds"),a&&t.extensions.push("deepl"),h&&t.extensions.push("monica-ai"),m&&t.extensions.push("sider-ai"),w&&t.extensions.push("requestly"),o&&t.extensions.push("veepn"),t}function c(t){try{return t()}catch{return!1}}function Ge(){const t={bitmask:r,chrome:c(()=>"chrome"in window),brave:c(()=>"brave"in navigator),applePaySupport:c(()=>"ApplePaySetup"in window),opera:c(()=>typeof window.opr<"u"||typeof window.onoperadetachedviewchange=="object"),serial:c(()=>window.navigator.serial!==void 0),attachShadow:c(()=>!!Element.prototype.attachShadow),caches:c(()=>!!window.caches),webAssembly:c(()=>!!window.WebAssembly&&!!window.WebAssembly.instantiate),buffer:c(()=>"Buffer"in window),showModalDialog:c(()=>"showModalDialog"in window),safari:c(()=>"safari"in window),webkitPrefixedFunction:c(()=>"webkitCancelAnimationFrame"in window),mozPrefixedFunction:c(()=>"mozGetUserMedia"in navigator),usb:c(()=>typeof window.USB=="function"),browserCapture:c(()=>typeof window.BrowserCaptureMediaStreamTrack=="function"),paymentRequestUpdateEvent:c(()=>typeof window.PaymentRequestUpdateEvent=="function"),pressureObserver:c(()=>typeof window.PressureObserver=="function"),audioSession:c(()=>"audioSession"in navigator),selectAudioOutput:c(()=>typeof navigator<"u"&&typeof navigator.mediaDevices<"u"&&typeof navigator.mediaDevices.selectAudioOutput=="function"),barcodeDetector:c(()=>"BarcodeDetector"in window),battery:c(()=>"getBattery"in navigator),devicePosture:c(()=>"DevicePosture"in window),documentPictureInPicture:c(()=>"documentPictureInPicture"in window),eyeDropper:c(()=>"EyeDropper"in window),editContext:c(()=>"EditContext"in window),fencedFrame:c(()=>"FencedFrameConfig"in window),sanitizer:c(()=>"Sanitizer"in window),otpCredential:c(()=>"OTPCredential"in window)},e=Object.keys(t).filter(n=>n!=="bitmask").map(n=>t[n]?"1":"0").join("");return t.bitmask=e,t}function je(){const t={prefersColorScheme:r,prefersReducedMotion:r,prefersReducedTransparency:r,colorGamut:r,pointer:r,anyPointer:r,hover:r,anyHover:r,colorDepth:r};try{window.matchMedia("(prefers-color-scheme: dark)").matches?t.prefersColorScheme="dark":window.matchMedia("(prefers-color-scheme: light)").matches?t.prefersColorScheme="light":t.prefersColorScheme=null,t.prefersReducedMotion=window.matchMedia("(prefers-reduced-motion: reduce)").matches,t.prefersReducedTransparency=window.matchMedia("(prefers-reduced-transparency: reduce)").matches,window.matchMedia("(color-gamut: rec2020)").matches?t.colorGamut="rec2020":window.matchMedia("(color-gamut: p3)").matches?t.colorGamut="p3":window.matchMedia("(color-gamut: srgb)").matches?t.colorGamut="srgb":t.colorGamut=null,window.matchMedia("(pointer: fine)").matches?t.pointer="fine":window.matchMedia("(pointer: coarse)").matches?t.pointer="coarse":window.matchMedia("(pointer: none)").matches?t.pointer="none":t.pointer=null,window.matchMedia("(any-pointer: fine)").matches?t.anyPointer="fine":window.matchMedia("(any-pointer: coarse)").matches?t.anyPointer="coarse":window.matchMedia("(any-pointer: none)").matches?t.anyPointer="none":t.anyPointer=null,t.hover=window.matchMedia("(hover: hover)").matches,t.anyHover=window.matchMedia("(any-hover: hover)").matches;let e=0;for(let n=0;n<=16;n++)window.matchMedia(`(color: ${n})`).matches&&(e=n);t.colorDepth=e}catch{g(t,l)}return t}function Be(t){const e=t.signals.device.screenResolution;return e.width===600&&e.height===800||e.availableWidth===600&&e.availableHeight===800||e.innerWidth===600&&e.innerHeight===800}function Ne(t){return t.signals.automation.webdriver===!0}function ze(t){return!!t.signals.automation.selenium}function $e(t){return t.signals.automation.cdp===!0}function Qe(t){return t.signals.automation.playwright===!0}function qe(t){return typeof t.signals.device.memory!="number"?!1:t.signals.device.memory>32||t.signals.device.memory<.25}function Ke(t){return typeof t.signals.device.cpuCount!="number"?!1:t.signals.device.cpuCount>70}function Je(t){const e=t.signals.browser.userAgent;return t.signals.browser.features.chrome===!1&&typeof e=="string"&&e.includes("Chrome")}function Ye(t){return t.signals.contexts.iframe.webdriver===!0}function Ze(t){return t.signals.contexts.webWorker.webdriver===!0}function Xe(t){const e=t.signals.contexts.webWorker,n=t.signals.graphics.webGL;return e.vendor===l||e.renderer===l||n.vendor===s||n.renderer===s||e.vendor===f?!1:e.vendor!==n.vendor||e.renderer!==n.renderer}function et(t){return t.signals.contexts.webWorker.platform===s||t.signals.contexts.webWorker.platform===l||t.signals.contexts.webWorker.platform===f?!1:t.signals.device.platform!==t.signals.contexts.webWorker.platform}function tt(t){return t.signals.contexts.iframe.platform===s||t.signals.contexts.iframe.platform===l?!1:t.signals.device.platform!==t.signals.contexts.iframe.platform}function rt(t){return t.signals.automation.webdriverWritable===!0}function nt(t){return t.signals.graphics.webGL.renderer.includes("SwiftShader")}function it(t){return t.signals.locale.internationalization.timezone==="UTC"}function at(t){const e=t.signals.locale.languages.languages,n=t.signals.locale.languages.language;return n&&e&&Array.isArray(e)&&e.length>0?e[0]!==n:!1}function ot(t){return!!(t.signals.browser.features.chrome&&t.signals.browser.etsl!==33||t.signals.browser.features.safari&&t.signals.browser.etsl!==37||t.signals.browser.userAgent.includes("Firefox")&&t.signals.browser.etsl!==37)}function st(t){return[t.signals.browser.userAgent,t.signals.contexts.iframe.userAgent,t.signals.contexts.webWorker.userAgent].some(n=>/bot|headless/i.test(n.toLowerCase()))}function ct(t){const e=t.signals.graphics.webgpu,n=t.signals.graphics.webGL,i=t.signals.browser.userAgent;return!!((n.vendor.includes("Apple")||n.renderer.includes("Apple"))&&!i.includes("Mac")||e.vendor.includes("apple")&&!i.includes("Mac")||e.vendor.includes("apple")&&!n.renderer.includes("Apple"))}function lt(t){const e=t.signals.device.platform,n=t.signals.browser.userAgent,i=t.signals.browser.highEntropyValues.platform;return!!(n.includes("Mac")&&(e.includes("Win")||e.includes("Linux"))||n.includes("Windows")&&(e.includes("Mac")||e.includes("Linux"))||n.includes("Linux")&&(e.includes("Mac")||e.includes("Win"))||i!==l&&i!==s&&(i.includes("Mac")&&(e.includes("Win")||e.includes("Linux"))||i.includes("Windows")&&(e.includes("Mac")||e.includes("Linux"))||i.includes("Linux")&&(e.includes("Mac")||e.includes("Win"))))}async function ut(t,e){const n=new TextEncoder().encode(e),i=new TextEncoder().encode(t),a=new Uint8Array(i.length);for(let m=0;m<i.length;m++)a[m]=i[m]^n[m%n.length];const h=String.fromCharCode(...a);return btoa(h)}class dt{constructor(){this.fingerprint={signals:{automation:{webdriver:r,webdriverWritable:r,selenium:r,cdp:r,playwright:r,navigatorPropertyDescriptors:r},device:{cpuCount:r,memory:r,platform:r,screenResolution:{width:r,height:r,pixelDepth:r,colorDepth:r,availableWidth:r,availableHeight:r,innerWidth:r,innerHeight:r,hasMultipleDisplays:r},multimediaDevices:{speakers:r,microphones:r,webcams:r},mediaQueries:{prefersColorScheme:r,prefersReducedMotion:r,prefersReducedTransparency:r,colorGamut:r,pointer:r,anyPointer:r,hover:r,anyHover:r,colorDepth:r}},browser:{userAgent:r,features:{bitmask:r,chrome:r,brave:r,applePaySupport:r,opera:r,serial:r,attachShadow:r,caches:r,webAssembly:r,buffer:r,showModalDialog:r,safari:r,webkitPrefixedFunction:r,mozPrefixedFunction:r,usb:r,browserCapture:r,paymentRequestUpdateEvent:r,pressureObserver:r,audioSession:r,selectAudioOutput:r,barcodeDetector:r,battery:r,devicePosture:r,documentPictureInPicture:r,eyeDropper:r,editContext:r,fencedFrame:r,sanitizer:r,otpCredential:r},plugins:{isValidPluginArray:r,pluginCount:r,pluginNamesHash:r,pluginConsistency1:r,pluginOverflow:r},extensions:{bitmask:r,extensions:r},highEntropyValues:{architecture:r,bitness:r,brands:r,mobile:r,model:r,platform:r,platformVersion:r,uaFullVersion:r},etsl:r,maths:r,toSourceError:{toSourceError:r,hasToSource:r}},graphics:{webGL:{vendor:r,renderer:r},webgpu:{vendor:r,architecture:r,device:r,description:r},canvas:{hasModifiedCanvas:r,canvasFingerprint:r}},codecs:{audioCanPlayTypeHash:r,videoCanPlayTypeHash:r,audioMediaSourceHash:r,videoMediaSourceHash:r,rtcAudioCapabilitiesHash:r,rtcVideoCapabilitiesHash:r,hasMediaSource:r},locale:{internationalization:{timezone:r,localeLanguage:r},languages:{languages:r,language:r}},contexts:{iframe:{webdriver:r,userAgent:r,platform:r,memory:r,cpuCount:r,language:r},webWorker:{webdriver:r,userAgent:r,platform:r,memory:r,cpuCount:r,language:r,vendor:r,renderer:r}}},fsid:r,nonce:r,time:r,url:r,fastBotDetection:!1,fastBotDetectionDetails:{headlessChromeScreenResolution:{detected:!1,severity:"high"},hasWebdriver:{detected:!1,severity:"high"},hasWebdriverWritable:{detected:!1,severity:"high"},hasSeleniumProperty:{detected:!1,severity:"high"},hasCDP:{detected:!1,severity:"high"},hasPlaywright:{detected:!1,severity:"high"},hasImpossibleDeviceMemory:{detected:!1,severity:"high"},hasHighCPUCount:{detected:!1,severity:"high"},hasMissingChromeObject:{detected:!1,severity:"high"},hasWebdriverIframe:{detected:!1,severity:"high"},hasWebdriverWorker:{detected:!1,severity:"high"},hasMismatchWebGLInWorker:{detected:!1,severity:"high"},hasMismatchPlatformIframe:{detected:!1,severity:"high"},hasMismatchPlatformWorker:{detected:!1,severity:"high"},hasSwiftshaderRenderer:{detected:!1,severity:"low"},hasUTCTimezone:{detected:!1,severity:"medium"},hasMismatchLanguages:{detected:!1,severity:"low"},hasInconsistentEtsl:{detected:!1,severity:"high"},hasBotUserAgent:{detected:!1,severity:"high"},hasGPUMismatch:{detected:!1,severity:"high"},hasPlatformMismatch:{detected:!1,severity:"high"}}}}async collectSignal(e){try{return await e()}catch{return l}}generateFingerprintScannerId(){try{const e=this.fingerprint.signals,n=this.fingerprint.fastBotDetectionDetails,i="FS1",h=[n.headlessChromeScreenResolution.detected,n.hasWebdriver.detected,n.hasWebdriverWritable.detected,n.hasSeleniumProperty.detected,n.hasCDP.detected,n.hasPlaywright.detected,n.hasImpossibleDeviceMemory.detected,n.hasHighCPUCount.detected,n.hasMissingChromeObject.detected,n.hasWebdriverIframe.detected,n.hasWebdriverWorker.detected,n.hasMismatchWebGLInWorker.detected,n.hasMismatchPlatformIframe.detected,n.hasMismatchPlatformWorker.detected,n.hasSwiftshaderRenderer.detected,n.hasUTCTimezone.detected,n.hasMismatchLanguages.detected,n.hasInconsistentEtsl.detected,n.hasBotUserAgent.detected,n.hasGPUMismatch.detected,n.hasPlatformMismatch.detected].map(u=>u?"1":"0").join(""),m=[e.automation.webdriver===!0,e.automation.webdriverWritable===!0,e.automation.selenium===!0,e.automation.cdp===!0,e.automation.playwright===!0].map(u=>u?"1":"0").join(""),w=p(String(e.automation.navigatorPropertyDescriptors)).slice(0,4),o=`${m}h${w}`,v=typeof e.device.screenResolution.width=="number"?e.device.screenResolution.width:0,y=typeof e.device.screenResolution.height=="number"?e.device.screenResolution.height:0,W=typeof e.device.cpuCount=="number"?String(e.device.cpuCount).padStart(2,"0"):"00",E=typeof e.device.memory=="number"?String(Math.round(e.device.memory)).padStart(2,"0"):"00",k=[e.device.screenResolution.hasMultipleDisplays===!0,e.device.mediaQueries.prefersReducedMotion===!0,e.device.mediaQueries.prefersReducedTransparency===!0,e.device.mediaQueries.hover===!0,e.device.mediaQueries.anyHover===!0].map(u=>u?"1":"0").join(""),D=[e.device.platform,e.device.screenResolution.pixelDepth,e.device.screenResolution.colorDepth,e.device.multimediaDevices.speakers,e.device.multimediaDevices.microphones,e.device.multimediaDevices.webcams,e.device.mediaQueries.prefersColorScheme,e.device.mediaQueries.colorGamut,e.device.mediaQueries.pointer,e.device.mediaQueries.anyPointer,e.device.mediaQueries.colorDepth].map(u=>String(u)).join("|"),_=p(D).slice(0,6),R=`${v}x${y}c${W}m${E}b${k}h${_}`,I=typeof e.browser.features.bitmask=="string"?e.browser.features.bitmask:"0000000000",T=typeof e.browser.extensions.bitmask=="string"?e.browser.extensions.bitmask:"00000000",L=[e.browser.plugins.isValidPluginArray===!0,e.browser.plugins.pluginConsistency1===!0,e.browser.plugins.pluginOverflow===!0,e.browser.toSourceError.hasToSource===!0].map(u=>u?"1":"0").join(""),O=[e.browser.userAgent,e.browser.etsl,e.browser.maths,e.browser.plugins.pluginCount,e.browser.plugins.pluginNamesHash,e.browser.toSourceError.toSourceError,e.browser.highEntropyValues.architecture,e.browser.highEntropyValues.bitness,e.browser.highEntropyValues.platform,e.browser.highEntropyValues.platformVersion,e.browser.highEntropyValues.uaFullVersion,e.browser.highEntropyValues.mobile].map(u=>String(u)).join("|"),H=p(O).slice(0,6),F=`f${I}e${T}p${L}h${H}`,U=[e.graphics.canvas.hasModifiedCanvas===!0].map(u=>u?"1":"0").join(""),V=[e.graphics.webGL.vendor,e.graphics.webGL.renderer,e.graphics.webgpu.vendor,e.graphics.webgpu.architecture,e.graphics.webgpu.device,e.graphics.webgpu.description,e.graphics.canvas.canvasFingerprint].map(u=>String(u)).join("|"),G=p(V).slice(0,6),j=`${U}h${G}`,B=[e.codecs.hasMediaSource===!0].map(u=>u?"1":"0").join(""),N=[e.codecs.audioCanPlayTypeHash,e.codecs.videoCanPlayTypeHash,e.codecs.audioMediaSourceHash,e.codecs.videoMediaSourceHash,e.codecs.rtcAudioCapabilitiesHash,e.codecs.rtcVideoCapabilitiesHash].map(u=>String(u)).join("|"),z=p(N).slice(0,6),$=`${B}h${z}`,Q=typeof e.locale.languages.language=="string"?e.locale.languages.language.slice(0,2).toLowerCase():"xx",q=Array.isArray(e.locale.languages.languages)?e.locale.languages.languages.length:0,K=(typeof e.locale.internationalization.timezone=="string"?e.locale.internationalization.timezone:"unknown").replace(/[\/\s]/g,"-"),J=[e.locale.internationalization.timezone,e.locale.internationalization.localeLanguage,Array.isArray(e.locale.languages.languages)?e.locale.languages.languages.join(","):e.locale.languages.languages,e.locale.languages.language].map(u=>String(u)).join("|"),Y=p(J).slice(0,4),Z=`${Q}${q}t${K}_h${Y}`,X=[x(this.fingerprint,"iframe"),x(this.fingerprint,"worker"),e.contexts.iframe.webdriver===!0,e.contexts.webWorker.webdriver===!0].map(u=>u?"1":"0").join(""),ee=[e.contexts.iframe.userAgent,e.contexts.iframe.platform,e.contexts.iframe.memory,e.contexts.iframe.cpuCount,e.contexts.iframe.language,e.contexts.webWorker.userAgent,e.contexts.webWorker.platform,e.contexts.webWorker.memory,e.contexts.webWorker.cpuCount,e.contexts.webWorker.language,e.contexts.webWorker.vendor,e.contexts.webWorker.renderer].map(u=>String(u)).join("|"),te=p(ee).slice(0,6),re=`${X}h${te}`;return[i,h,o,R,F,j,$,Z,re].join("_")}catch(e){return console.error("Error generating fingerprint scanner id",e),l}}async encryptFingerprint(e){const n="__DEFAULT_FPSCANNER_KEY__";return n.length>20&&n.indexOf("DEFAULT")>0&&n.indexOf("FPSCANNER")>0&&console.warn('[fpscanner] WARNING: Using default encryption key! Run "npx fpscanner build --key=your-secret-key" to inject your own key. See: https://github.com/antoinevastel/fpscanner#advanced-custom-builds'),await ut(JSON.stringify(e),n)}getDetectionRules(){return[{name:"headlessChromeScreenResolution",severity:d,test:Be},{name:"hasWebdriver",severity:d,test:Ne},{name:"hasWebdriverWritable",severity:d,test:rt},{name:"hasSeleniumProperty",severity:d,test:ze},{name:"hasCDP",severity:d,test:$e},{name:"hasPlaywright",severity:d,test:Qe},{name:"hasImpossibleDeviceMemory",severity:d,test:qe},{name:"hasHighCPUCount",severity:d,test:Ke},{name:"hasMissingChromeObject",severity:d,test:Je},{name:"hasWebdriverIframe",severity:d,test:Ye},{name:"hasWebdriverWorker",severity:d,test:Ze},{name:"hasMismatchWebGLInWorker",severity:d,test:Xe},{name:"hasMismatchPlatformIframe",severity:d,test:tt},{name:"hasMismatchPlatformWorker",severity:d,test:et},{name:"hasSwiftshaderRenderer",severity:b,test:nt},{name:"hasUTCTimezone",severity:oe,test:it},{name:"hasMismatchLanguages",severity:b,test:at},{name:"hasInconsistentEtsl",severity:d,test:ot},{name:"hasBotUserAgent",severity:d,test:st},{name:"hasGPUMismatch",severity:d,test:ct},{name:"hasPlatformMismatch",severity:d,test:lt}]}runDetectionRules(){const e=this.getDetectionRules(),n={headlessChromeScreenResolution:{detected:!1,severity:"high"},hasWebdriver:{detected:!1,severity:"high"},hasWebdriverWritable:{detected:!1,severity:"high"},hasSeleniumProperty:{detected:!1,severity:"high"},hasCDP:{detected:!1,severity:"high"},hasPlaywright:{detected:!1,severity:"high"},hasImpossibleDeviceMemory:{detected:!1,severity:"high"},hasHighCPUCount:{detected:!1,severity:"high"},hasMissingChromeObject:{detected:!1,severity:"high"},hasWebdriverIframe:{detected:!1,severity:"high"},hasWebdriverWorker:{detected:!1,severity:"high"},hasMismatchWebGLInWorker:{detected:!1,severity:"high"},hasMismatchPlatformIframe:{detected:!1,severity:"high"},hasMismatchPlatformWorker:{detected:!1,severity:"high"},hasSwiftshaderRenderer:{detected:!1,severity:"low"},hasUTCTimezone:{detected:!1,severity:"medium"},hasMismatchLanguages:{detected:!1,severity:"low"},hasInconsistentEtsl:{detected:!1,severity:"high"},hasBotUserAgent:{detected:!1,severity:"high"},hasGPUMismatch:{detected:!1,severity:"high"},hasPlatformMismatch:{detected:!1,severity:"high"}};for(const i of e)try{const a=i.test(this.fingerprint);n[i.name]={detected:a,severity:i.severity}}catch{n[i.name]={detected:!1,severity:i.severity}}return n}async collectFingerprint(e={encrypt:!0}){const{encrypt:n=!0,skipWorker:i=!1}=e,a=this.fingerprint.signals,h={webdriver:this.collectSignal(ne),webdriverWritable:this.collectSignal(be),selenium:this.collectSignal(ye),cdp:this.collectSignal(ce),playwright:this.collectSignal(ue),navigatorPropertyDescriptors:this.collectSignal(Oe),cpuCount:this.collectSignal(de),memory:this.collectSignal(he),platform:this.collectSignal(ae),screenResolution:this.collectSignal(fe),multimediaDevices:this.collectSignal(Ee),mediaQueries:this.collectSignal(je),userAgent:this.collectSignal(ie),browserFeatures:this.collectSignal(Ge),plugins:this.collectSignal(We),browserExtensions:this.collectSignal(Ve),highEntropyValues:this.collectSignal(Se),etsl:this.collectSignal(me),maths:this.collectSignal(ge),toSourceError:this.collectSignal(_e),webGL:this.collectSignal(le),webgpu:this.collectSignal(we),canvas:this.collectSignal(Le),mediaCodecs:this.collectSignal(Re),internationalization:this.collectSignal(pe),languages:this.collectSignal(ve),iframe:this.collectSignal(ke),webWorker:i?Promise.resolve({webdriver:f,userAgent:f,platform:f,memory:f,cpuCount:f,language:f,vendor:f,renderer:f}):this.collectSignal(De),nonce:this.collectSignal(He),time:this.collectSignal(Fe),url:this.collectSignal(Ue)},m=Object.keys(h),w=await Promise.all(Object.values(h)),o=Object.fromEntries(m.map((v,y)=>[v,w[y]]));return a.automation.webdriver=o.webdriver,a.automation.webdriverWritable=o.webdriverWritable,a.automation.selenium=o.selenium,a.automation.cdp=o.cdp,a.automation.playwright=o.playwright,a.automation.navigatorPropertyDescriptors=o.navigatorPropertyDescriptors,a.device.cpuCount=o.cpuCount,a.device.memory=o.memory,a.device.platform=o.platform,a.device.screenResolution=o.screenResolution,a.device.multimediaDevices=o.multimediaDevices,a.device.mediaQueries=o.mediaQueries,a.browser.userAgent=o.userAgent,a.browser.features=o.browserFeatures,a.browser.plugins=o.plugins,a.browser.extensions=o.browserExtensions,a.browser.highEntropyValues=o.highEntropyValues,a.browser.etsl=o.etsl,a.browser.maths=o.maths,a.browser.toSourceError=o.toSourceError,a.graphics.webGL=o.webGL,a.graphics.webgpu=o.webgpu,a.graphics.canvas=o.canvas,a.codecs=o.mediaCodecs,a.locale.internationalization=o.internationalization,a.locale.languages=o.languages,a.contexts.iframe=o.iframe,a.contexts.webWorker=o.webWorker,this.fingerprint.nonce=o.nonce,this.fingerprint.time=o.time,this.fingerprint.url=o.url,this.fingerprint.fastBotDetectionDetails=this.runDetectionRules(),this.fingerprint.fastBotDetection=Object.values(this.fingerprint.fastBotDetectionDetails).some(v=>v.detected),this.fingerprint.fsid=this.generateFingerprintScannerId(),n?await this.encryptFingerprint(JSON.stringify(this.fingerprint)):this.fingerprint}}exports.default=dt;
@@ -225,7 +225,7 @@ function Ae() {
225
225
  function Pe() {
226
226
  return navigator.plugins ? navigator.plugins.length : s;
227
227
  }
228
- function Ee() {
228
+ function xe() {
229
229
  if (!navigator.plugins) return s;
230
230
  try {
231
231
  return navigator.plugins[0] === navigator.plugins[0][0].enabledPlugin;
@@ -250,13 +250,13 @@ function Me() {
250
250
  pluginOverflow: r
251
251
  };
252
252
  try {
253
- t.isValidPluginArray = Ce(), t.pluginCount = Pe(), t.pluginNamesHash = Ae(), t.pluginConsistency1 = Ee(), t.pluginOverflow = We();
253
+ t.isValidPluginArray = Ce(), t.pluginCount = Pe(), t.pluginNamesHash = Ae(), t.pluginConsistency1 = xe(), t.pluginOverflow = We();
254
254
  } catch {
255
255
  h(t, l);
256
256
  }
257
257
  return t;
258
258
  }
259
- async function xe() {
259
+ async function Ee() {
260
260
  return new Promise(async function(t) {
261
261
  var e = {
262
262
  audiooutput: 0,
@@ -336,8 +336,9 @@ async function De() {
336
336
  fingerprintWorker.vendor = 'INIT';
337
337
  fingerprintWorker.renderer = 'INIT';
338
338
  var gl = canvas.getContext('webgl');
339
+ const isFirefox = navigator.userAgent.includes('Firefox');
339
340
  try {
340
- if (gl) {
341
+ if (gl && !isFirefox) {
341
342
  var glExt = gl.getExtension('WEBGL_debug_renderer_info');
342
343
  fingerprintWorker.vendor = gl.getParameter(glExt.UNMASKED_VENDOR_WEBGL);
343
344
  fingerprintWorker.renderer = gl.getParameter(glExt.UNMASKED_RENDERER_WEBGL);
@@ -446,7 +447,7 @@ function P(t) {
446
447
  }
447
448
  return e;
448
449
  }
449
- function E(t) {
450
+ function x(t) {
450
451
  try {
451
452
  const e = window.RTCRtpReceiver;
452
453
  if (e && typeof e.getCapabilities == "function") {
@@ -473,7 +474,7 @@ function Re() {
473
474
  const e = A(S, "audio"), n = A(C, "video");
474
475
  t.audioCanPlayTypeHash = p(JSON.stringify(e)), t.videoCanPlayTypeHash = p(JSON.stringify(n));
475
476
  const i = P(S), a = P(C);
476
- t.audioMediaSourceHash = p(JSON.stringify(i)), t.videoMediaSourceHash = p(JSON.stringify(a)), t.rtcAudioCapabilitiesHash = E("audio"), t.rtcVideoCapabilitiesHash = E("video");
477
+ t.audioMediaSourceHash = p(JSON.stringify(i)), t.videoMediaSourceHash = p(JSON.stringify(a)), t.rtcAudioCapabilitiesHash = x("audio"), t.rtcVideoCapabilitiesHash = x("video");
477
478
  } catch {
478
479
  h(t, l);
479
480
  }
@@ -493,7 +494,7 @@ async function Ie() {
493
494
  }
494
495
  });
495
496
  }
496
- function Te() {
497
+ function Le() {
497
498
  var t = document.createElement("canvas");
498
499
  t.width = 400, t.height = 200, t.style.display = "inline";
499
500
  var e = t.getContext("2d");
@@ -503,14 +504,14 @@ function Te() {
503
504
  return l;
504
505
  }
505
506
  }
506
- async function Le() {
507
+ async function Te() {
507
508
  const t = {
508
509
  hasModifiedCanvas: r,
509
510
  canvasFingerprint: r
510
511
  };
511
- return t.hasModifiedCanvas = await Ie(), t.canvasFingerprint = Te(), t;
512
+ return t.hasModifiedCanvas = await Ie(), t.canvasFingerprint = Le(), t;
512
513
  }
513
- function Oe() {
514
+ function He() {
514
515
  const t = ["deviceMemory", "hardwareConcurrency", "language", "languages", "platform"], e = [];
515
516
  for (const n of t) {
516
517
  const i = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(navigator), n);
@@ -518,20 +519,20 @@ function Oe() {
518
519
  }
519
520
  return e.join("");
520
521
  }
521
- function He() {
522
+ function Oe() {
522
523
  return Math.random().toString(36).substring(2, 15);
523
524
  }
524
- function Ue() {
525
+ function Fe() {
525
526
  return (/* @__PURE__ */ new Date()).getTime();
526
527
  }
527
- function Ve() {
528
+ function Ue() {
528
529
  return window.location.href;
529
530
  }
530
531
  function W(t, e) {
531
532
  const n = t.signals;
532
533
  return e === "iframe" ? n.contexts.iframe.webdriver !== n.automation.webdriver || n.contexts.iframe.userAgent !== n.browser.userAgent || n.contexts.iframe.platform !== n.device.platform || n.contexts.iframe.memory !== n.device.memory || n.contexts.iframe.cpuCount !== n.device.cpuCount : n.contexts.webWorker.webdriver !== n.automation.webdriver || n.contexts.webWorker.userAgent !== n.browser.userAgent || n.contexts.webWorker.platform !== n.device.platform || n.contexts.webWorker.memory !== n.device.memory || n.contexts.webWorker.cpuCount !== n.device.cpuCount;
533
534
  }
534
- function Fe() {
535
+ function Ve() {
535
536
  const t = {
536
537
  bitmask: r,
537
538
  extensions: []
@@ -682,7 +683,7 @@ function ct(t) {
682
683
  }
683
684
  function lt(t) {
684
685
  const e = t.signals.device.platform, n = t.signals.browser.userAgent, i = t.signals.browser.highEntropyValues.platform;
685
- return !!(n.includes("Mac") && !e.includes("Mac") || n.includes("Windows") && !e.includes("Win") || n.includes("Linux") && !e.includes("Linux") || i !== l && i !== s && (i.includes("Mac") && !e.includes("Mac") || i.includes("Windows") && !e.includes("Win") || i.includes("Linux") && !e.includes("Linux") || i.includes("Android") && !e.includes("Android") || i.includes("iOS") && !e.includes("iOS")));
686
+ return !!(n.includes("Mac") && (e.includes("Win") || e.includes("Linux")) || n.includes("Windows") && (e.includes("Mac") || e.includes("Linux")) || n.includes("Linux") && (e.includes("Mac") || e.includes("Win")) || i !== l && i !== s && (i.includes("Mac") && (e.includes("Win") || e.includes("Linux")) || i.includes("Windows") && (e.includes("Mac") || e.includes("Linux")) || i.includes("Linux") && (e.includes("Mac") || e.includes("Win"))));
686
687
  }
687
688
  async function ut(t, e) {
688
689
  const n = new TextEncoder().encode(e), i = new TextEncoder().encode(t), a = new Uint8Array(i.length);
@@ -949,7 +950,7 @@ class ht {
949
950
  e.automation.selenium === !0,
950
951
  e.automation.cdp === !0,
951
952
  e.automation.playwright === !0
952
- ].map((u) => u ? "1" : "0").join(""), w = p(String(e.automation.navigatorPropertyDescriptors)).slice(0, 4), o = `${m}h${w}`, v = typeof e.device.screenResolution.width == "number" ? e.device.screenResolution.width : 0, y = typeof e.device.screenResolution.height == "number" ? e.device.screenResolution.height : 0, M = typeof e.device.cpuCount == "number" ? String(e.device.cpuCount).padStart(2, "0") : "00", x = typeof e.device.memory == "number" ? String(Math.round(e.device.memory)).padStart(2, "0") : "00", k = [
953
+ ].map((u) => u ? "1" : "0").join(""), w = p(String(e.automation.navigatorPropertyDescriptors)).slice(0, 4), o = `${m}h${w}`, v = typeof e.device.screenResolution.width == "number" ? e.device.screenResolution.width : 0, y = typeof e.device.screenResolution.height == "number" ? e.device.screenResolution.height : 0, M = typeof e.device.cpuCount == "number" ? String(e.device.cpuCount).padStart(2, "0") : "00", E = typeof e.device.memory == "number" ? String(Math.round(e.device.memory)).padStart(2, "0") : "00", k = [
953
954
  e.device.screenResolution.hasMultipleDisplays === !0,
954
955
  e.device.mediaQueries.prefersReducedMotion === !0,
955
956
  e.device.mediaQueries.prefersReducedTransparency === !0,
@@ -967,12 +968,12 @@ class ht {
967
968
  e.device.mediaQueries.pointer,
968
969
  e.device.mediaQueries.anyPointer,
969
970
  e.device.mediaQueries.colorDepth
970
- ].map((u) => String(u)).join("|"), _ = p(D).slice(0, 6), R = `${v}x${y}c${M}m${x}b${k}h${_}`, I = typeof e.browser.features.bitmask == "string" ? e.browser.features.bitmask : "0000000000", T = typeof e.browser.extensions.bitmask == "string" ? e.browser.extensions.bitmask : "00000000", L = [
971
+ ].map((u) => String(u)).join("|"), _ = p(D).slice(0, 6), R = `${v}x${y}c${M}m${E}b${k}h${_}`, I = typeof e.browser.features.bitmask == "string" ? e.browser.features.bitmask : "0000000000", L = typeof e.browser.extensions.bitmask == "string" ? e.browser.extensions.bitmask : "00000000", T = [
971
972
  e.browser.plugins.isValidPluginArray === !0,
972
973
  e.browser.plugins.pluginConsistency1 === !0,
973
974
  e.browser.plugins.pluginOverflow === !0,
974
975
  e.browser.toSourceError.hasToSource === !0
975
- ].map((u) => u ? "1" : "0").join(""), O = [
976
+ ].map((u) => u ? "1" : "0").join(""), H = [
976
977
  e.browser.userAgent,
977
978
  e.browser.etsl,
978
979
  e.browser.maths,
@@ -985,9 +986,9 @@ class ht {
985
986
  e.browser.highEntropyValues.platformVersion,
986
987
  e.browser.highEntropyValues.uaFullVersion,
987
988
  e.browser.highEntropyValues.mobile
988
- ].map((u) => String(u)).join("|"), H = p(O).slice(0, 6), U = `f${I}e${T}p${L}h${H}`, V = [
989
+ ].map((u) => String(u)).join("|"), O = p(H).slice(0, 6), F = `f${I}e${L}p${T}h${O}`, U = [
989
990
  e.graphics.canvas.hasModifiedCanvas === !0
990
- ].map((u) => u ? "1" : "0").join(""), F = [
991
+ ].map((u) => u ? "1" : "0").join(""), V = [
991
992
  e.graphics.webGL.vendor,
992
993
  e.graphics.webGL.renderer,
993
994
  e.graphics.webgpu.vendor,
@@ -995,7 +996,7 @@ class ht {
995
996
  e.graphics.webgpu.device,
996
997
  e.graphics.webgpu.description,
997
998
  e.graphics.canvas.canvasFingerprint
998
- ].map((u) => String(u)).join("|"), G = p(F).slice(0, 6), B = `${V}h${G}`, j = [
999
+ ].map((u) => String(u)).join("|"), G = p(V).slice(0, 6), B = `${U}h${G}`, j = [
999
1000
  e.codecs.hasMediaSource === !0
1000
1001
  ].map((u) => u ? "1" : "0").join(""), N = [
1001
1002
  e.codecs.audioCanPlayTypeHash,
@@ -1033,7 +1034,7 @@ class ht {
1033
1034
  g,
1034
1035
  o,
1035
1036
  R,
1036
- U,
1037
+ F,
1037
1038
  B,
1038
1039
  $,
1039
1040
  Z,
@@ -1118,19 +1119,19 @@ class ht {
1118
1119
  selenium: this.collectSignal(ye),
1119
1120
  cdp: this.collectSignal(ce),
1120
1121
  playwright: this.collectSignal(ue),
1121
- navigatorPropertyDescriptors: this.collectSignal(Oe),
1122
+ navigatorPropertyDescriptors: this.collectSignal(He),
1122
1123
  // Device signals
1123
1124
  cpuCount: this.collectSignal(de),
1124
1125
  memory: this.collectSignal(ge),
1125
1126
  platform: this.collectSignal(ae),
1126
1127
  screenResolution: this.collectSignal(fe),
1127
- multimediaDevices: this.collectSignal(xe),
1128
+ multimediaDevices: this.collectSignal(Ee),
1128
1129
  mediaQueries: this.collectSignal(Be),
1129
1130
  // Browser signals
1130
1131
  userAgent: this.collectSignal(ie),
1131
1132
  browserFeatures: this.collectSignal(Ge),
1132
1133
  plugins: this.collectSignal(Me),
1133
- browserExtensions: this.collectSignal(Fe),
1134
+ browserExtensions: this.collectSignal(Ve),
1134
1135
  highEntropyValues: this.collectSignal(Se),
1135
1136
  etsl: this.collectSignal(me),
1136
1137
  maths: this.collectSignal(he),
@@ -1138,7 +1139,7 @@ class ht {
1138
1139
  // Graphics signals
1139
1140
  webGL: this.collectSignal(le),
1140
1141
  webgpu: this.collectSignal(we),
1141
- canvas: this.collectSignal(Le),
1142
+ canvas: this.collectSignal(Te),
1142
1143
  // Codecs
1143
1144
  mediaCodecs: this.collectSignal(Re),
1144
1145
  // Locale signals
@@ -1157,9 +1158,9 @@ class ht {
1157
1158
  renderer: f
1158
1159
  }) : this.collectSignal(De),
1159
1160
  // Meta signals
1160
- nonce: this.collectSignal(He),
1161
- time: this.collectSignal(Ue),
1162
- url: this.collectSignal(Ve)
1161
+ nonce: this.collectSignal(Oe),
1162
+ time: this.collectSignal(Fe),
1163
+ url: this.collectSignal(Ue)
1163
1164
  }, m = Object.keys(g), w = await Promise.all(Object.values(g)), o = Object.fromEntries(m.map((v, y) => [v, w[y]]));
1164
1165
  return a.automation.webdriver = o.webdriver, a.automation.webdriverWritable = o.webdriverWritable, a.automation.selenium = o.selenium, a.automation.cdp = o.cdp, a.automation.playwright = o.playwright, a.automation.navigatorPropertyDescriptors = o.navigatorPropertyDescriptors, a.device.cpuCount = o.cpuCount, a.device.memory = o.memory, a.device.platform = o.platform, a.device.screenResolution = o.screenResolution, a.device.multimediaDevices = o.multimediaDevices, a.device.mediaQueries = o.mediaQueries, a.browser.userAgent = o.userAgent, a.browser.features = o.browserFeatures, a.browser.plugins = o.plugins, a.browser.extensions = o.browserExtensions, a.browser.highEntropyValues = o.highEntropyValues, a.browser.etsl = o.etsl, a.browser.maths = o.maths, a.browser.toSourceError = o.toSourceError, a.graphics.webGL = o.webGL, a.graphics.webgpu = o.webgpu, a.graphics.canvas = o.canvas, a.codecs = o.mediaCodecs, a.locale.internationalization = o.internationalization, a.locale.languages = o.languages, a.contexts.iframe = o.iframe, a.contexts.webWorker = o.webWorker, this.fingerprint.nonce = o.nonce, this.fingerprint.time = o.time, this.fingerprint.url = o.url, this.fingerprint.fastBotDetectionDetails = this.runDetectionRules(), this.fingerprint.fastBotDetection = Object.values(this.fingerprint.fastBotDetectionDetails).some((v) => v.detected), this.fingerprint.fsid = this.generateFingerprintScannerId(), n ? await this.encryptFingerprint(JSON.stringify(this.fingerprint)) : this.fingerprint;
1165
1166
  }
@@ -1 +1 @@
1
- {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/signals/worker.ts"],"names":[],"mappings":"AAEA,wBAAsB,MAAM,qBAiG3B"}
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/signals/worker.ts"],"names":[],"mappings":"AAEA,wBAAsB,MAAM,qBAkG3B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fpscanner",
3
- "version": "0.9.5-beta.1",
3
+ "version": "1.0.0",
4
4
  "description": "A lightweight browser fingerprinting and bot detection library with encryption, obfuscation, and cross-context validation",
5
5
  "main": "dist/fpScanner.cjs.js",
6
6
  "module": "dist/fpScanner.es.js",
@@ -39,6 +39,35 @@ module.exports = async function build(args) {
39
39
  console.log(` Obfuscation: ${skipObfuscation ? 'disabled' : 'enabled'}`);
40
40
  console.log('');
41
41
 
42
+ // Step 0: Backup/Restore mechanism to ensure idempotent builds
43
+ // This allows running the build multiple times without re-obfuscating already obfuscated code
44
+ console.log('🔄 Step 0/6: Ensuring clean build state...');
45
+ let restoredFromBackup = false;
46
+
47
+ for (const file of files) {
48
+ const filePath = path.join(distDir, file);
49
+ const backupPath = filePath + '.original';
50
+
51
+ if (!fs.existsSync(filePath)) {
52
+ continue;
53
+ }
54
+
55
+ if (fs.existsSync(backupPath)) {
56
+ // Backup exists - restore from it to ensure clean state
57
+ fs.copyFileSync(backupPath, filePath);
58
+ restoredFromBackup = true;
59
+ } else {
60
+ // First run - create backup of pristine files
61
+ fs.copyFileSync(filePath, backupPath);
62
+ console.log(` 📦 Created backup: ${file}.original`);
63
+ }
64
+ }
65
+
66
+ if (restoredFromBackup) {
67
+ console.log(' ✓ Restored files from backups (clean state for build)');
68
+ }
69
+ console.log('');
70
+
42
71
  // Check if we can build from source (more reliable than string replacement)
43
72
  const viteConfigPath = path.join(packageDir, 'vite.config.ts');
44
73
  const canBuildFromSource = fs.existsSync(viteConfigPath);
@@ -46,7 +75,7 @@ module.exports = async function build(args) {
46
75
  if (canBuildFromSource) {
47
76
  // Preferred method: Build from source with key injected via environment variable
48
77
  // This is more reliable as Vite's define properly replaces the key during the build
49
- console.log('📦 Step 0/5: Building from source with injected key...');
78
+ console.log('📦 Step 1/6: Building from source with injected key...');
50
79
  console.log(' (This is more reliable than post-build string replacement)');
51
80
  try {
52
81
  execSync('npm run build:vite', {
@@ -64,14 +93,14 @@ module.exports = async function build(args) {
64
93
  stdio: 'inherit',
65
94
  });
66
95
  console.log('');
67
- console.log('📦 Step 1/5: Key injected during build');
96
+ console.log(' Key injected during build');
68
97
  } catch (err) {
69
98
  throw new Error('Build from source failed. Make sure vite is installed (npm install)');
70
99
  }
71
100
  } else {
72
101
  // Fallback method: String replacement in pre-built dist files
73
102
  // Used when vite.config.ts is not available (npm consumers without dev dependencies)
74
- console.log('📦 Step 1/5: Injecting encryption key via string replacement...');
103
+ console.log('📦 Step 1/6: Injecting encryption key via string replacement...');
75
104
  console.log(' (Fallback method - vite.config.ts not found)');
76
105
 
77
106
  let keyInjected = false;
@@ -120,12 +149,12 @@ module.exports = async function build(args) {
120
149
 
121
150
  // Step 2: Skip TypeScript declarations (already generated)
122
151
  console.log('');
123
- console.log('⏭️ Step 2/5: TypeScript declarations already present, skipping...');
152
+ console.log('⏭️ Step 2/6: TypeScript declarations already present, skipping...');
124
153
 
125
154
  // Step 3: Obfuscate (optional)
126
155
  if (!skipObfuscation) {
127
156
  console.log('');
128
- console.log('🔒 Step 3/5: Obfuscating output...');
157
+ console.log('🔒 Step 3/6: Obfuscating output...');
129
158
 
130
159
  let JavaScriptObfuscator;
131
160
  try {
@@ -171,7 +200,7 @@ module.exports = async function build(args) {
171
200
 
172
201
  // Step 4: Minify with Terser
173
202
  console.log('');
174
- console.log('📦 Step 4/5: Minifying with Terser...');
203
+ console.log('📦 Step 4/6: Minifying with Terser...');
175
204
 
176
205
  let terser;
177
206
  try {
@@ -215,7 +244,7 @@ module.exports = async function build(args) {
215
244
 
216
245
  // Step 5: Delete all source map files so DevTools can't show original source
217
246
  console.log('');
218
- console.log('🗑️ Step 5/5: Removing source maps...');
247
+ console.log('🗑️ Step 5/6: Removing source maps...');
219
248
 
220
249
  function deleteMapFiles(dir, prefix = '') {
221
250
  if (!fs.existsSync(dir)) {
@@ -239,9 +268,13 @@ module.exports = async function build(args) {
239
268
  }
240
269
  } else {
241
270
  console.log('');
242
- console.log('⏭️ Steps 3-5/5: Skipping obfuscation, minification, and source map removal (--no-obfuscate)');
271
+ console.log('⏭️ Steps 3-5/6: Skipping obfuscation, minification, and source map removal (--no-obfuscate)');
243
272
  }
244
273
 
274
+ // Step 6: Note about backups
275
+ console.log('');
276
+ console.log('💡 Note: Original files backed up as *.original for future rebuilds');
277
+
245
278
  console.log('');
246
279
  console.log('✅ Build complete!');
247
280
  console.log('');
@@ -6,40 +6,32 @@ export function hasPlatformMismatch(fingerprint: Fingerprint) {
6
6
  const userAgent = fingerprint.signals.browser.userAgent;
7
7
  const highEntropyPlatform = fingerprint.signals.browser.highEntropyValues.platform;
8
8
 
9
- if (userAgent.includes('Mac') && !platform.includes('Mac')) {
9
+ if (userAgent.includes('Mac') && (platform.includes('Win') || platform.includes('Linux'))) {
10
10
  return true;
11
11
  }
12
12
 
13
- if (userAgent.includes('Windows') && !platform.includes('Win')) {
13
+ if (userAgent.includes('Windows') && (platform.includes('Mac') || platform.includes('Linux'))) {
14
14
  return true;
15
15
  }
16
16
 
17
- if (userAgent.includes('Linux') && !platform.includes('Linux')) {
17
+ if (userAgent.includes('Linux') && (platform.includes('Mac') || platform.includes('Win'))) {
18
18
  return true;
19
19
  }
20
20
 
21
21
 
22
22
  // Check applied only if highEntropyPlatform is not ERROR or NA
23
23
  if (highEntropyPlatform !== ERROR && highEntropyPlatform !== NA) {
24
- if (highEntropyPlatform.includes('Mac') && !platform.includes('Mac')) {
24
+ if (highEntropyPlatform.includes('Mac') && (platform.includes('Win') || platform.includes('Linux'))) {
25
25
  return true;
26
26
  }
27
27
 
28
- if (highEntropyPlatform.includes('Windows') && !platform.includes('Win')) {
28
+ if (highEntropyPlatform.includes('Windows') && (platform.includes('Mac') || platform.includes('Linux'))) {
29
29
  return true;
30
30
  }
31
31
 
32
- if (highEntropyPlatform.includes('Linux') && !platform.includes('Linux')) {
32
+ if (highEntropyPlatform.includes('Linux') && (platform.includes('Mac') || platform.includes('Win'))) {
33
33
  return true;
34
34
  }
35
-
36
- if (highEntropyPlatform.includes('Android') && !platform.includes('Android')) {
37
- return true;
38
- }
39
-
40
- if (highEntropyPlatform.includes('iOS') && !platform.includes('iOS')) {
41
- return true;
42
- }
43
35
  }
44
36
 
45
37
  return false;
@@ -37,8 +37,9 @@ export async function worker() {
37
37
  fingerprintWorker.vendor = 'INIT';
38
38
  fingerprintWorker.renderer = 'INIT';
39
39
  var gl = canvas.getContext('webgl');
40
+ const isFirefox = navigator.userAgent.includes('Firefox');
40
41
  try {
41
- if (gl) {
42
+ if (gl && !isFirefox) {
42
43
  var glExt = gl.getExtension('WEBGL_debug_renderer_info');
43
44
  fingerprintWorker.vendor = gl.getParameter(glExt.UNMASKED_VENDOR_WEBGL);
44
45
  fingerprintWorker.renderer = gl.getParameter(glExt.UNMASKED_RENDERER_WEBGL);