@fanboynz/network-scanner 2.0.14 → 2.0.15

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.
Files changed (3) hide show
  1. package/lib/fingerprint.js +234 -14
  2. package/nwss.js +31 -2
  3. package/package.json +1 -1
@@ -16,17 +16,17 @@ const BUILT_IN_PROPERTIES = new Set([
16
16
  // User agent collections with latest versions
17
17
  const USER_AGENT_COLLECTIONS = {
18
18
  chrome: [
19
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
20
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
21
- "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
19
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
20
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
21
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36"
22
22
  ],
23
23
  firefox: [
24
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0",
25
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:133.0) Gecko/20100101 Firefox/133.0",
26
- "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0"
24
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0",
25
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:143.0) Gecko/20100101 Firefox/143.0",
26
+ "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:143.0) Gecko/20100101 Firefox/143.0"
27
27
  ],
28
28
  safari: [
29
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Safari/605.1.15",
29
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15",
30
30
  "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Safari/605.1.15"
31
31
  ]
32
32
  };
@@ -387,6 +387,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
387
387
  }
388
388
 
389
389
  // Remove webdriver properties
390
+ //
390
391
  safeExecute(() => {
391
392
  try {
392
393
  delete navigator.webdriver;
@@ -395,6 +396,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
395
396
  }, 'webdriver removal');
396
397
 
397
398
  // Remove automation properties
399
+ //
398
400
  safeExecute(() => {
399
401
  const automationProps = [
400
402
  'callPhantom', '_phantom', '__nightmare', '_selenium', '__selenium_unwrapped',
@@ -417,6 +419,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
417
419
  }, 'automation properties removal');
418
420
 
419
421
  // Simulate Chrome runtime
422
+ //
420
423
  safeExecute(() => {
421
424
  if (!window.chrome?.runtime) {
422
425
  window.chrome = {
@@ -449,6 +452,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
449
452
  }, 'Chrome runtime simulation');
450
453
 
451
454
  // Spoof plugins based on user agent
455
+ //
452
456
  safeExecute(() => {
453
457
  let plugins = [];
454
458
  if (userAgent.includes('Chrome')) {
@@ -482,12 +486,25 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
482
486
  // Safari typically has no plugins in modern versions
483
487
  plugins = [];
484
488
  }
485
- // Create array-like object with length property
486
- const pluginsArray = Object.assign(plugins, { length: plugins.length });
489
+ // Create proper array-like object with enumerable indices and length
490
+ const pluginsArray = {};
491
+ plugins.forEach((plugin, index) => {
492
+ pluginsArray[index] = plugin;
493
+ });
494
+
495
+ // Ensure length property is properly defined
496
+ Object.defineProperty(pluginsArray, 'length', {
497
+ value: plugins.length,
498
+ writable: false,
499
+ enumerable: false,
500
+ configurable: false
501
+ });
502
+
487
503
  safeDefinePropertyLocal(navigator, 'plugins', { get: () => pluginsArray });
488
504
  }, 'plugins spoofing');
489
505
 
490
506
  // Spoof languages
507
+ //
491
508
  safeExecute(() => {
492
509
  const languages = ['en-US', 'en'];
493
510
  safeDefinePropertyLocal(navigator, 'languages', { get: () => languages });
@@ -495,6 +512,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
495
512
  }, 'language spoofing');
496
513
 
497
514
  // Spoof vendor information
515
+ //
498
516
  safeExecute(() => {
499
517
  let vendor = 'Google Inc.';
500
518
  let product = 'Gecko';
@@ -510,6 +528,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
510
528
  }, 'vendor/product spoofing');
511
529
 
512
530
  // Enhanced OS fingerprinting protection based on actual user agent content
531
+ //
513
532
  safeExecute(() => {
514
533
  let osType = 'windows';
515
534
  let browserType = 'chrome';
@@ -552,7 +571,15 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
552
571
  }
553
572
  }, 'enhanced OS fingerprinting protection');
554
573
 
574
+ // Hardware concurrency spoofing (universal coverage)
575
+ //
576
+ safeExecute(() => {
577
+ safeDefinePropertyLocal(navigator, 'hardwareConcurrency', { get: () => [4, 6, 8, 12][Math.floor(Math.random() * 4)] });
578
+ }, 'hardware concurrency spoofing');
579
+
580
+
555
581
  // Screen resolution fingerprinting protection
582
+ //
556
583
  safeExecute(() => {
557
584
  // Common realistic resolutions to avoid fingerprinting
558
585
  const commonResolutions = [
@@ -573,6 +600,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
573
600
  }, 'screen resolution protection');
574
601
 
575
602
  // Spoof MIME types
603
+ //
576
604
  safeExecute(() => {
577
605
  let mimeTypes = [];
578
606
  if (userAgent.includes('Chrome')) {
@@ -646,28 +674,118 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
646
674
  }, 'fingerprinting mocks');
647
675
 
648
676
  // WebGL spoofing
677
+ //
649
678
  safeExecute(() => {
679
+ // Enhanced WebGL fingerprinting protection
680
+ const webglParams = {
681
+ 37445: 'Intel Inc.', // VENDOR
682
+ 37446: 'Intel(R) UHD Graphics 630', // RENDERER (more realistic)
683
+ 7936: 'WebGL 1.0 (OpenGL ES 2.0 Chromium)', // VERSION
684
+ 35724: 'WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.00 Chromium)', // SHADING_LANGUAGE_VERSION
685
+ 34076: 16384, // MAX_TEXTURE_SIZE
686
+ 34024: 16384, // MAX_CUBE_MAP_TEXTURE_SIZE
687
+ 34930: new Float32Array([1, 1]), // ALIASED_LINE_WIDTH_RANGE
688
+ 33901: new Float32Array([0, 1]), // ALIASED_POINT_SIZE_RANGE
689
+ 35660: 16, // MAX_VERTEX_ATTRIBS
690
+ 35661: 16, // MAX_VERTEX_UNIFORM_VECTORS
691
+ 35659: 16, // MAX_VARYING_VECTORS
692
+ 35663: 16, // MAX_FRAGMENT_UNIFORM_VECTORS
693
+ 36347: 4096, // MAX_RENDERBUFFER_SIZE
694
+ 34852: 32, // MAX_COMBINED_TEXTURE_IMAGE_UNITS
695
+ 2978: new Int32Array([0, 0, 1920, 1080]), // VIEWPORT
696
+ 3379: new Int32Array([0, 0, 1920, 1080]) // SCISSOR_BOX
697
+ };
698
+
650
699
  if (window.WebGLRenderingContext) {
651
700
  const getParameter = WebGLRenderingContext.prototype.getParameter;
652
701
  WebGLRenderingContext.prototype.getParameter = function(parameter) {
653
- if (parameter === 37445) return 'Intel Inc.';
654
- if (parameter === 37446) return 'Intel Iris OpenGL Engine';
702
+ if (webglParams.hasOwnProperty(parameter)) {
703
+ return webglParams[parameter];
704
+ }
655
705
  return getParameter.call(this, parameter);
656
706
  };
707
+ // Spoof supported extensions
708
+ const getSupportedExtensions = WebGLRenderingContext.prototype.getSupportedExtensions;
709
+ WebGLRenderingContext.prototype.getSupportedExtensions = function() {
710
+ return [
711
+ 'ANGLE_instanced_arrays',
712
+ 'EXT_blend_minmax',
713
+ 'EXT_color_buffer_half_float',
714
+ 'EXT_disjoint_timer_query',
715
+ 'EXT_float_blend',
716
+ 'EXT_frag_depth',
717
+ 'EXT_shader_texture_lod',
718
+ 'EXT_texture_compression_rgtc',
719
+ 'EXT_texture_filter_anisotropic',
720
+ 'WEBKIT_EXT_texture_filter_anisotropic',
721
+ 'EXT_sRGB',
722
+ 'OES_element_index_uint',
723
+ 'OES_fbo_render_mipmap',
724
+ 'OES_standard_derivatives',
725
+ 'OES_texture_float',
726
+ 'OES_texture_float_linear',
727
+ 'OES_texture_half_float',
728
+ 'OES_texture_half_float_linear',
729
+ 'OES_vertex_array_object',
730
+ 'WEBGL_color_buffer_float',
731
+ 'WEBGL_compressed_texture_s3tc',
732
+ 'WEBGL_debug_renderer_info',
733
+ 'WEBGL_debug_shaders',
734
+ 'WEBGL_depth_texture',
735
+ 'WEBGL_draw_buffers',
736
+ 'WEBGL_lose_context'
737
+ ];
738
+ };
739
+ }
740
+ // Also handle WebGL2 context
741
+ if (window.WebGL2RenderingContext) {
742
+ const getParameter2 = WebGL2RenderingContext.prototype.getParameter;
743
+ WebGL2RenderingContext.prototype.getParameter = function(parameter) {
744
+ if (webglParams.hasOwnProperty(parameter)) {
745
+ return webglParams[parameter];
746
+ }
747
+ return getParameter2.call(this, parameter);
748
+ };
657
749
  }
658
750
  }, 'WebGL spoofing');
659
751
 
660
752
  // Permissions API spoofing
753
+ //
661
754
  safeExecute(() => {
662
755
  if (navigator.permissions?.query) {
663
756
  const originalQuery = navigator.permissions.query;
664
757
  navigator.permissions.query = function(descriptor) {
665
- return Promise.resolve({ state: Math.random() > 0.5 ? 'granted' : 'prompt' });
758
+ // More realistic permission states based on permission type
759
+ const permissionName = descriptor.name || descriptor;
760
+ let state = 'prompt'; // Default state
761
+
762
+ // Common permissions that are usually granted
763
+ if (['notifications', 'persistent-storage'].includes(permissionName)) {
764
+ state = Math.random() > 0.3 ? 'granted' : 'prompt';
765
+ }
766
+ // Privacy-sensitive permissions that are usually denied/prompt
767
+ else if (['camera', 'microphone', 'geolocation'].includes(permissionName)) {
768
+ state = Math.random() > 0.8 ? 'granted' : 'prompt';
769
+ }
770
+ // Other permissions random
771
+ else {
772
+ state = Math.random() > 0.5 ? 'granted' : 'prompt';
773
+ }
774
+
775
+ return Promise.resolve({
776
+ state: state,
777
+ onchange: null
778
+ });
666
779
  };
667
780
  }
781
+ // Block permission prompts from actually appearing
782
+ if (window.Notification && Notification.requestPermission) {
783
+ Notification.requestPermission = () => Promise.resolve('default');
784
+ }
668
785
  }, 'permissions API spoofing');
669
786
 
670
787
  // Media Device Spoofing
788
+ //
671
789
  safeExecute(() => {
672
790
  if (navigator.mediaDevices?.enumerateDevices) {
673
791
  navigator.mediaDevices.enumerateDevices = function() {
@@ -681,6 +799,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
681
799
  }, 'media device spoofing');
682
800
 
683
801
  // Fetch Request Headers Normalization
802
+ //
684
803
  safeExecute(() => {
685
804
  const originalFetch = window.fetch;
686
805
  window.fetch = function(url, options = {}) {
@@ -702,6 +821,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
702
821
  }, 'fetch headers normalization');
703
822
 
704
823
  // Image Loading Pattern Obfuscation
824
+ //
705
825
  safeExecute(() => {
706
826
  const originalImageSrc = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'src');
707
827
  if (originalImageSrc) {
@@ -719,6 +839,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
719
839
  }, 'image loading obfuscation');
720
840
 
721
841
  // CSS Media Query Spoofing
842
+ //
722
843
  safeExecute(() => {
723
844
  const originalMatchMedia = window.matchMedia;
724
845
  window.matchMedia = function(query) {
@@ -736,6 +857,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
736
857
  }, 'CSS media query spoofing');
737
858
 
738
859
  // Enhanced WebRTC Spoofing
860
+ //
739
861
  safeExecute(() => {
740
862
  if (window.RTCPeerConnection) {
741
863
  const OriginalRTC = window.RTCPeerConnection;
@@ -752,6 +874,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
752
874
  }, 'WebRTC spoofing');
753
875
 
754
876
  // Font fingerprinting protection
877
+ //
755
878
  safeExecute(() => {
756
879
  // Standardize available fonts to common system fonts
757
880
  const standardFonts = [
@@ -760,7 +883,100 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
760
883
  'Trebuchet MS', 'Arial Black', 'Impact', 'Tahoma', 'Lucida Console'
761
884
  ];
762
885
 
886
+ // Intercept font availability detection
887
+ if (document.fonts && document.fonts.check) {
888
+ const originalCheck = document.fonts.check;
889
+ document.fonts.check = function(fontSpec) {
890
+ // Always return true for standard fonts, false for others
891
+ const fontFamily = fontSpec.match(/['"]([^'"]+)['"]/)?.[1] || fontSpec.split(' ').pop();
892
+ return standardFonts.some(font => fontFamily.includes(font));
893
+ };
894
+ }
895
+
896
+ // Prevent font loading detection
897
+ if (document.fonts && document.fonts.load) {
898
+ document.fonts.load = function() {
899
+ return Promise.resolve([]);
900
+ };
901
+ }
902
+
903
+ // Canvas-based font fingerprinting protection
904
+ //
905
+ const originalFillText = CanvasRenderingContext2D.prototype.fillText;
906
+ const originalStrokeText = CanvasRenderingContext2D.prototype.strokeText;
907
+ const originalMeasureText = CanvasRenderingContext2D.prototype.measureText;
908
+
909
+ CanvasRenderingContext2D.prototype.fillText = function(text, x, y, maxWidth) {
910
+ // Normalize font to standard before drawing
911
+ const currentFont = this.font;
912
+ if (currentFont && !standardFonts.some(font => currentFont.includes(font))) {
913
+ this.font = currentFont.replace(/['"]?[^'"]*['"]?/, '"Arial"');
914
+ }
915
+ return originalFillText.call(this, text, x, y, maxWidth);
916
+ };
917
+
918
+ CanvasRenderingContext2D.prototype.strokeText = function(text, x, y, maxWidth) {
919
+ const currentFont = this.font;
920
+ if (currentFont && !standardFonts.some(font => currentFont.includes(font))) {
921
+ this.font = currentFont.replace(/['"]?[^'"]*['"]?/, '"Arial"');
922
+ }
923
+ return originalStrokeText.call(this, text, x, y, maxWidth);
924
+ };
925
+
926
+ CanvasRenderingContext2D.prototype.measureText = function(text) {
927
+ const result = originalMeasureText.call(this, text);
928
+ // Add slight noise to text measurements to prevent precise fingerprinting
929
+ result.width += (Math.random() - 0.5) * 0.1;
930
+ return result;
931
+ };
932
+
933
+ // Comprehensive canvas fingerprinting protection
934
+ //
935
+ const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
936
+ CanvasRenderingContext2D.prototype.getImageData = function(sx, sy, sw, sh) {
937
+ const imageData = originalGetImageData.call(this, sx, sy, sw, sh);
938
+ // Add subtle noise to pixel data
939
+ for (let i = 0; i < imageData.data.length; i += 4) {
940
+ if (Math.random() < 0.1) { // 10% chance to modify each pixel
941
+ imageData.data[i] = Math.max(0, Math.min(255, imageData.data[i] + Math.floor(Math.random() * 3) - 1));
942
+ imageData.data[i + 1] = Math.max(0, Math.min(255, imageData.data[i + 1] + Math.floor(Math.random() * 3) - 1));
943
+ imageData.data[i + 2] = Math.max(0, Math.min(255, imageData.data[i + 2] + Math.floor(Math.random() * 3) - 1));
944
+ }
945
+ }
946
+ return imageData;
947
+ };
948
+
949
+ // WebGL canvas context fingerprinting
950
+ const originalGetContext = HTMLCanvasElement.prototype.getContext;
951
+ HTMLCanvasElement.prototype.getContext = function(contextType, contextAttributes) {
952
+ const context = originalGetContext.call(this, contextType, contextAttributes);
953
+
954
+ if (contextType === 'webgl' || contextType === 'webgl2' || contextType === 'experimental-webgl') {
955
+ // Override WebGL-specific fingerprinting methods
956
+ const originalGetShaderPrecisionFormat = context.getShaderPrecisionFormat;
957
+ context.getShaderPrecisionFormat = function(shaderType, precisionType) {
958
+ return {
959
+ rangeMin: 127,
960
+ rangeMax: 127,
961
+ precision: 23
962
+ };
963
+ };
964
+
965
+ const originalGetExtension = context.getExtension;
966
+ context.getExtension = function(name) {
967
+ // Block access to fingerprinting-sensitive extensions
968
+ if (name === 'WEBGL_debug_renderer_info') {
969
+ return null;
970
+ }
971
+ return originalGetExtension.call(this, name);
972
+ };
973
+ }
974
+
975
+ return context;
976
+ };
977
+
763
978
  // Override font detection methods
979
+ //
764
980
  const originalOffsetWidth = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetWidth');
765
981
  const originalOffsetHeight = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetHeight');
766
982
 
@@ -778,6 +994,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
778
994
  }, 'font fingerprinting protection');
779
995
 
780
996
  // Performance timing obfuscation
997
+ //
781
998
  safeExecute(() => {
782
999
  const originalNow = performance.now;
783
1000
  performance.now = function() {
@@ -786,6 +1003,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
786
1003
  }, 'performance timing obfuscation');
787
1004
 
788
1005
  // Canvas fingerprinting protection
1006
+ //
789
1007
  safeExecute(() => {
790
1008
  const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
791
1009
  HTMLCanvasElement.prototype.toDataURL = function(...args) {
@@ -802,6 +1020,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
802
1020
  }, 'canvas fingerprinting protection');
803
1021
 
804
1022
  // Battery API spoofing
1023
+ //
805
1024
  safeExecute(() => {
806
1025
  if (navigator.getBattery) {
807
1026
  navigator.getBattery = function() {
@@ -815,9 +1034,8 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
815
1034
  }
816
1035
  }, 'battery API spoofing');
817
1036
 
818
- // Suppress common console errors
819
-
820
1037
  // Enhanced Mouse/Pointer Spoofing
1038
+ //
821
1039
  safeExecute(() => {
822
1040
  // Spoof pointer capabilities
823
1041
  if (navigator.maxTouchPoints !== undefined) {
@@ -841,6 +1059,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
841
1059
  };
842
1060
 
843
1061
  // Spoof PointerEvent if available
1062
+ //
844
1063
  if (window.PointerEvent) {
845
1064
  const OriginalPointerEvent = window.PointerEvent;
846
1065
  window.PointerEvent = function(type, eventInitDict = {}) {
@@ -870,6 +1089,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
870
1089
  }
871
1090
 
872
1091
  // Spoof mouse wheel behavior
1092
+ //
873
1093
  const originalWheelEvent = window.WheelEvent;
874
1094
  if (originalWheelEvent) {
875
1095
  window.WheelEvent = function(type, eventInitDict = {}) {
package/nwss.js CHANGED
@@ -1,4 +1,4 @@
1
- // === Network scanner script (nwss.js) v2.0.14 ===
1
+ // === Network scanner script (nwss.js) v2.0.15 ===
2
2
 
3
3
  // puppeteer for browser automation, fs for file system operations, psl for domain parsing.
4
4
  // const pLimit = require('p-limit'); // Will be dynamically imported
@@ -130,7 +130,7 @@ const { navigateWithRedirectHandling, handleRedirectTimeout } = require('./lib/r
130
130
  const { monitorBrowserHealth, isBrowserHealthy, isQuicklyResponsive, performGroupWindowCleanup, performRealtimeWindowCleanup, trackPageForRealtime, updatePageUsage, cleanupPageBeforeReload } = require('./lib/browserhealth');
131
131
 
132
132
  // --- Script Configuration & Constants ---
133
- const VERSION = '2.0.14'; // Script version
133
+ const VERSION = '2.0.15'; // Script version
134
134
 
135
135
  // get startTime
136
136
  const startTime = Date.now();
@@ -1335,6 +1335,7 @@ function setupFrameHandling(page, forceDebug) {
1335
1335
  '--memory-pressure-off',
1336
1336
  '--max_old_space_size=2048',
1337
1337
  '--no-first-run',
1338
+ '--disable-prompt-on-repost', // Fixes form popup on page reload
1338
1339
  '--disable-default-apps',
1339
1340
  '--disable-component-extensions-with-background-pages',
1340
1341
  '--disable-background-networking',
@@ -1994,6 +1995,34 @@ function setupFrameHandling(page, forceDebug) {
1994
1995
  // --- Apply all fingerprint spoofing (user agent, Brave, fingerprint protection) ---
1995
1996
  try {
1996
1997
  await applyAllFingerprintSpoofing(page, siteConfig, forceDebug, currentUrl);
1998
+
1999
+ // Client Hints protection for Chrome user agents
2000
+ if (siteConfig.userAgent && siteConfig.userAgent.toLowerCase().includes('chrome')) {
2001
+ let platform = 'Windows';
2002
+ let platformVersion = '15.0.0';
2003
+ let arch = 'x86';
2004
+
2005
+ if (siteConfig.userAgent.toLowerCase() === 'chrome_mac') {
2006
+ platform = 'macOS';
2007
+ platformVersion = '13.5.0';
2008
+ arch = 'arm';
2009
+ } else if (siteConfig.userAgent.toLowerCase() === 'chrome_linux') {
2010
+ platform = 'Linux';
2011
+ platformVersion = '6.5.0';
2012
+ arch = 'x86';
2013
+ }
2014
+
2015
+ await page.setExtraHTTPHeaders({
2016
+ 'Sec-CH-UA': '"Chromium";v="140", "Not=A?Brand";v="24", "Google Chrome";v="140"',
2017
+ 'Sec-CH-UA-Platform': `"${platform}"`,
2018
+ 'Sec-CH-UA-Platform-Version': `"${platformVersion}"`,
2019
+ 'Sec-CH-UA-Mobile': '?0',
2020
+ 'Sec-CH-UA-Arch': `"${arch}"`,
2021
+ 'Sec-CH-UA-Bitness': '"64"',
2022
+ 'Sec-CH-UA-Full-Version': '"140.0.7339.208"',
2023
+ 'Sec-CH-UA-Full-Version-List': '"Chromium";v="140.0.7339.208", "Not=A?Brand";v="24.0.0.0", "Google Chrome";v="140.0.7339.208"'
2024
+ });
2025
+ }
1997
2026
  } catch (fingerprintErr) {
1998
2027
  if (fingerprintErr.message.includes('Session closed') ||
1999
2028
  fingerprintErr.message.includes('Protocol error') ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanboynz/network-scanner",
3
- "version": "2.0.14",
3
+ "version": "2.0.15",
4
4
  "description": "A Puppeteer-based network scanner for analyzing web traffic, generating adblock filter rules, and identifying third-party requests. Features include fingerprint spoofing, Cloudflare bypass, content analysis with curl/grep, and multiple output formats.",
5
5
  "main": "nwss.js",
6
6
  "scripts": {