jumpy-lion 0.0.41 → 0.0.43

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 (127) hide show
  1. package/dist/browser-controller.d.ts.map +1 -1
  2. package/dist/browser-controller.js +102 -16
  3. package/dist/browser-controller.js.map +1 -1
  4. package/dist/browser-plugin.d.ts +20 -1
  5. package/dist/browser-plugin.d.ts.map +1 -1
  6. package/dist/browser-plugin.js +21 -1
  7. package/dist/browser-plugin.js.map +1 -1
  8. package/dist/browser-process/browser.d.ts +22 -1
  9. package/dist/browser-process/browser.d.ts.map +1 -1
  10. package/dist/browser-process/browser.js +77 -5
  11. package/dist/browser-process/browser.js.map +1 -1
  12. package/dist/browser-profiles/chrome/default.d.ts +116 -0
  13. package/dist/browser-profiles/chrome/default.d.ts.map +1 -1
  14. package/dist/browser-profiles/chrome/default.js +118 -1
  15. package/dist/browser-profiles/chrome/default.js.map +1 -1
  16. package/dist/browser-profiles/chrome/populate-profile.d.ts +76 -0
  17. package/dist/browser-profiles/chrome/populate-profile.d.ts.map +1 -0
  18. package/dist/browser-profiles/chrome/populate-profile.js +300 -0
  19. package/dist/browser-profiles/chrome/populate-profile.js.map +1 -0
  20. package/dist/browser-profiles/index.d.ts +1 -0
  21. package/dist/browser-profiles/index.d.ts.map +1 -1
  22. package/dist/browser-profiles/index.js +2 -0
  23. package/dist/browser-profiles/index.js.map +1 -1
  24. package/dist/crawler.d.ts +32 -1
  25. package/dist/crawler.d.ts.map +1 -1
  26. package/dist/crawler.js +7 -0
  27. package/dist/crawler.js.map +1 -1
  28. package/dist/fingerprinting/custom-fingerprint-injector.d.ts +87 -0
  29. package/dist/fingerprinting/custom-fingerprint-injector.d.ts.map +1 -0
  30. package/dist/fingerprinting/custom-fingerprint-injector.js +342 -0
  31. package/dist/fingerprinting/custom-fingerprint-injector.js.map +1 -0
  32. package/dist/fingerprinting/fingerprint-injector.d.ts +40 -2
  33. package/dist/fingerprinting/fingerprint-injector.d.ts.map +1 -1
  34. package/dist/fingerprinting/fingerprint-injector.js +452 -44
  35. package/dist/fingerprinting/fingerprint-injector.js.map +1 -1
  36. package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.d.ts.map +1 -1
  37. package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.js +11 -1
  38. package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.js.map +1 -1
  39. package/dist/fingerprinting/fingerprint-overrides/canvas-protection.d.ts.map +1 -1
  40. package/dist/fingerprinting/fingerprint-overrides/canvas-protection.js +11 -1
  41. package/dist/fingerprinting/fingerprint-overrides/canvas-protection.js.map +1 -1
  42. package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.d.ts +14 -0
  43. package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.d.ts.map +1 -0
  44. package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.js +776 -0
  45. package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.js.map +1 -0
  46. package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.d.ts.map +1 -1
  47. package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.js +11 -1
  48. package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.js.map +1 -1
  49. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts +14 -0
  50. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts.map +1 -0
  51. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js +643 -0
  52. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js.map +1 -0
  53. package/dist/fingerprinting/fingerprint-overrides/font-spoofing.d.ts.map +1 -1
  54. package/dist/fingerprinting/fingerprint-overrides/font-spoofing.js +11 -1
  55. package/dist/fingerprinting/fingerprint-overrides/font-spoofing.js.map +1 -1
  56. package/dist/fingerprinting/fingerprint-overrides/index.d.ts +17 -1
  57. package/dist/fingerprinting/fingerprint-overrides/index.d.ts.map +1 -1
  58. package/dist/fingerprinting/fingerprint-overrides/index.js +21 -1
  59. package/dist/fingerprinting/fingerprint-overrides/index.js.map +1 -1
  60. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.d.ts +45 -0
  61. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.d.ts.map +1 -0
  62. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js +291 -0
  63. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js.map +1 -0
  64. package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.d.ts.map +1 -1
  65. package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.js +153 -90
  66. package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.js.map +1 -1
  67. package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.d.ts.map +1 -1
  68. package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.js +4 -5
  69. package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.js.map +1 -1
  70. package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.d.ts.map +1 -1
  71. package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.js +11 -1
  72. package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.js.map +1 -1
  73. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.d.ts +13 -0
  74. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.d.ts.map +1 -1
  75. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js +413 -70
  76. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js.map +1 -1
  77. package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.d.ts +13 -0
  78. package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.d.ts.map +1 -0
  79. package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.js +355 -0
  80. package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.js.map +1 -0
  81. package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.d.ts +12 -3
  82. package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.d.ts.map +1 -1
  83. package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.js +261 -71
  84. package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.js.map +1 -1
  85. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.d.ts +55 -0
  86. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.d.ts.map +1 -0
  87. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js +380 -0
  88. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js.map +1 -0
  89. package/dist/fingerprinting/fingerprint-overrides/stealth-script.d.ts +8 -0
  90. package/dist/fingerprinting/fingerprint-overrides/stealth-script.d.ts.map +1 -1
  91. package/dist/fingerprinting/fingerprint-overrides/stealth-script.js +756 -71
  92. package/dist/fingerprinting/fingerprint-overrides/stealth-script.js.map +1 -1
  93. package/dist/fingerprinting/fingerprint-overrides/storage-consistency.d.ts +13 -0
  94. package/dist/fingerprinting/fingerprint-overrides/storage-consistency.d.ts.map +1 -0
  95. package/dist/fingerprinting/fingerprint-overrides/storage-consistency.js +368 -0
  96. package/dist/fingerprinting/fingerprint-overrides/storage-consistency.js.map +1 -0
  97. package/dist/fingerprinting/fingerprint-overrides/timing-consistency.d.ts +13 -0
  98. package/dist/fingerprinting/fingerprint-overrides/timing-consistency.d.ts.map +1 -0
  99. package/dist/fingerprinting/fingerprint-overrides/timing-consistency.js +438 -0
  100. package/dist/fingerprinting/fingerprint-overrides/timing-consistency.js.map +1 -0
  101. package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts +7 -1
  102. package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts.map +1 -1
  103. package/dist/fingerprinting/fingerprint-overrides/ua-ch.js +158 -58
  104. package/dist/fingerprinting/fingerprint-overrides/ua-ch.js.map +1 -1
  105. package/dist/fingerprinting/fingerprint-overrides/utils.d.ts +12 -0
  106. package/dist/fingerprinting/fingerprint-overrides/utils.d.ts.map +1 -0
  107. package/dist/fingerprinting/fingerprint-overrides/utils.js +517 -0
  108. package/dist/fingerprinting/fingerprint-overrides/utils.js.map +1 -0
  109. package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.d.ts.map +1 -1
  110. package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js +51 -10
  111. package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js.map +1 -1
  112. package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.d.ts.map +1 -1
  113. package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.js +11 -1
  114. package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.js.map +1 -1
  115. package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.d.ts.map +1 -1
  116. package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.js +11 -1
  117. package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.js.map +1 -1
  118. package/dist/page.d.ts +12 -0
  119. package/dist/page.d.ts.map +1 -1
  120. package/dist/page.js +35 -3
  121. package/dist/page.js.map +1 -1
  122. package/dist/tsconfig.build.tsbuildinfo +1 -1
  123. package/package.json +4 -4
  124. package/dist/fingerprinting/canvas-fingerprint.d.ts +0 -4
  125. package/dist/fingerprinting/canvas-fingerprint.d.ts.map +0 -1
  126. package/dist/fingerprinting/canvas-fingerprint.js +0 -60
  127. package/dist/fingerprinting/canvas-fingerprint.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"fingerprint-injector.d.ts","sourceRoot":"","sources":["../../src/fingerprinting/fingerprint-injector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AAGH,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAI3E,OAAO,KAAK,OAAO,MAAM,YAAY,CAAC;AAoBtC,UAAU,QAAQ;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,aAAa;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAEpB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,cAAc,CAAC;IAEjD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,2BAA2B,CAAC,EAAE,OAAO,CAAC;IAEtC,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACpC;AAMD,qBAAa,sBAAsB;IAC/B,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,IAAI,CAAU;gBAEV,IAAI,EAAE,OAAO;IAKzB;;;;OAIG;IACH,MAAM,CAAC,2BAA2B,IAAI,aAAa;WAwBtC,iBAAiB,CAC1B,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,6BAA6B,EAC1C,OAAO,CAAC,EAAE,aAAa,GACxB,OAAO,CAAC,IAAI,CAAC;YAKF,WAAW;YAaX,mBAAmB;YAInB,iBAAiB;YAcjB,mBAAmB;YAMnB,wBAAwB;IAKtC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAqCjB,YAAY,CACrB,6BAA6B,EAAE,6BAA6B,EAC5D,OAAO,CAAC,EAAE,aAAa,GACxB,OAAO,CAAC,IAAI,CAAC;CAyHnB"}
1
+ {"version":3,"file":"fingerprint-injector.d.ts","sourceRoot":"","sources":["../../src/fingerprinting/fingerprint-injector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AAGH,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAG3E,OAAO,KAAK,OAAO,MAAM,YAAY,CAAC;AAkCtC,UAAU,QAAQ;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,UAAU,mBAAmB;IACzB,2FAA2F;IAC3F,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,aAAa;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAEpB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iDAAiD;IACjD,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,cAAc,CAAC;IAEjD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,2BAA2B,CAAC,EAAE,OAAO,CAAC;IAEtC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC,mEAAmE;IACnE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,sEAAsE;IACtE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sEAAsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qEAAqE;IACrE,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;OAIG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACtC;AAMD,qBAAa,sBAAsB;IAC/B,OAAO,CAAC,IAAI,CAAU;gBAEV,IAAI,EAAE,OAAO;IAIzB;;;;;;;OAOG;IACH,MAAM,CAAC,2BAA2B,IAAI,aAAa;IAmCnD;;;OAGG;IACH,MAAM,CAAC,mBAAmB,IAAI,aAAa;WAyB9B,iBAAiB,CAC1B,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,6BAA6B,EAC1C,OAAO,CAAC,EAAE,aAAa,GACxB,OAAO,CAAC,IAAI,CAAC;YAKF,WAAW;YAyDX,mBAAmB;YAInB,iBAAiB;YAcjB,mBAAmB;YAMnB,wBAAwB;IAKtC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAwHzB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA2CjB,YAAY,CACrB,6BAA6B,EAAE,6BAA6B,EAC5D,OAAO,CAAC,EAAE,aAAa,GACxB,OAAO,CAAC,IAAI,CAAC;CA4UnB"}
@@ -61,46 +61,59 @@
61
61
  * ```
62
62
  */
63
63
  import { log } from 'crawlee';
64
- import { FingerprintInjector } from 'fingerprint-injector';
65
64
  import { gotScraping } from 'got-scraping';
66
- import { createStealthScript, createWebGLSpoofingScript, createAudioFingerprintSpoofingScript, createAdvancedCanvasProtectionScript, createClientRectSpoofingScript, createWebRTCSpoofingScript, createWebGPUSpoofingScript, createPlatformConsistencyScript, setupMouseMovementHumanization, setupRuntimeEnableBypass, createFontSpoofingScript, createPerformanceSpoofingScript, createLocaleSpoofingScript, createUAClientHintsSpoofingScript, } from './fingerprint-overrides/index.js';
65
+ import { createCustomFingerprintInjection } from './custom-fingerprint-injector.js';
66
+ import { createStealthScript, createWebGLSpoofingScript, createAudioFingerprintSpoofingScript, createAdvancedCanvasProtectionScript, createClientRectSpoofingScript, createWebRTCSpoofingScript, createWebGPUSpoofingScript, createPlatformConsistencyScript, setupMouseMovementHumanization, createRuntimeEnableBypassScript, createFontSpoofingScript, createPerformanceSpoofingScript, createLocaleSpoofingScript, createUAClientHintsSpoofingScript,
67
+ // Stealth utilities (must be injected first)
68
+ createStealthUtilsScript,
69
+ // Prototype integrity (must be injected early)
70
+ createPrototypeIntegrityScript,
71
+ // 2024-2025 New modules
72
+ createCDPDetectionBypassScript, createStorageConsistencyScript, createTimingConsistencyScript, createKeyboardHumanizationScript, createScrollHumanizationScript, createDataDomeBypassScript, setupKeyboardHumanization, setupScrollHumanization, } from './fingerprint-overrides/index.js';
67
73
  export class CdpFingerprintInjector {
68
74
  constructor(page) {
69
- Object.defineProperty(this, "injector", {
70
- enumerable: true,
71
- configurable: true,
72
- writable: true,
73
- value: void 0
74
- });
75
75
  Object.defineProperty(this, "page", {
76
76
  enumerable: true,
77
77
  configurable: true,
78
78
  writable: true,
79
79
  value: void 0
80
80
  });
81
- this.injector = new FingerprintInjector();
82
81
  this.page = page;
83
82
  }
84
83
  /**
85
84
  * Get recommended settings for Apify platform
86
85
  * These settings are optimized for running headful Chrome on Apify (Linux)
87
- * but spoofed to appear as Windows for better anti-bot evasion
86
+ * but spoofed to appear as Windows for better anti-bot evasion.
87
+ *
88
+ * Note: Humanization is disabled by default for performance.
89
+ * Use getDataDomeSettings() or enable humanization manually for anti-bot sites.
88
90
  */
89
91
  static getApifyRecommendedSettings() {
90
92
  return {
93
+ debug: true, // Enable debug logging by default
91
94
  enableAdvancedStealth: true,
92
95
  bypassRuntimeEnable: true,
93
96
  platform: 'Win32', // Spoof as Windows instead of Linux for better evasion
94
97
  spoofWebGL: true,
95
98
  spoofAudioContext: true,
96
99
  spoofClientRects: true,
97
- humanizeInteractions: true,
98
100
  detectTimezone: true, // Auto-detect timezone from proxy
99
101
  // New advanced spoofing options for 2025
100
102
  spoofFonts: true,
101
103
  spoofPerformance: true,
102
104
  spoofLocale: true,
103
105
  useFingerprintDefaults: true, // Use fingerprint-generator Windows values
106
+ // 2024-2025 DataDome bypass options
107
+ bypassCDPDetection: true,
108
+ spoofStorage: true,
109
+ spoofTiming: true,
110
+ enableDataDomeBypass: false, // Enable only when needed
111
+ // Humanization disabled by default for performance
112
+ humanization: {
113
+ mouse: false,
114
+ keyboard: false,
115
+ scroll: false,
116
+ },
104
117
  viewport: {
105
118
  width: 1920,
106
119
  height: 1080,
@@ -109,20 +122,85 @@ export class CdpFingerprintInjector {
109
122
  },
110
123
  };
111
124
  }
125
+ /**
126
+ * Get settings specifically optimized for DataDome-protected sites.
127
+ * Enables all humanization features for maximum anti-bot evasion.
128
+ */
129
+ static getDataDomeSettings() {
130
+ return {
131
+ ...this.getApifyRecommendedSettings(),
132
+ debug: true, // Enable debug logging by default
133
+ // DataDome-specific optimizations
134
+ enableDataDomeBypass: true,
135
+ bypassCDPDetection: true,
136
+ spoofStorage: true,
137
+ spoofTiming: true,
138
+ // Enable all humanization for DataDome bypass
139
+ humanization: {
140
+ mouse: true,
141
+ keyboard: true,
142
+ scroll: true,
143
+ },
144
+ // Ensure all fingerprint attributes are consistent
145
+ spoofWebGL: true,
146
+ spoofAudioContext: true,
147
+ spoofClientRects: true,
148
+ spoofFonts: true,
149
+ spoofPerformance: true,
150
+ spoofLocale: true,
151
+ };
152
+ }
112
153
  static async injectFingerprint(page, fingerprint, options) {
113
154
  const handler = new CdpFingerprintInjector(page);
114
155
  return handler.attachToPage(fingerprint, options);
115
156
  }
116
- async setViewport(viewport) {
117
- const defaultViewport = {
157
+ async setViewport(viewport, fingerprint) {
158
+ // IMPORTANT: In headful mode, don't override viewport - it creates weird compressed layouts
159
+ // The browser window already has natural dimensions from the OS
160
+ // Only override viewport in headless mode where window size needs to be set
161
+ // Check if we're in headless mode
162
+ // In headful mode, we skip viewport override to avoid layout issues
163
+ const isHeadless = process.env.APIFY_HEADLESS === '1' ||
164
+ process.env.CRAWLEE_HEADLESS === '1' ||
165
+ process.env.HEADLESS === 'true';
166
+ if (!isHeadless) {
167
+ log.info('⚠️ Headful mode detected - SKIPPING viewport override to preserve natural window behavior');
168
+ log.info('✅ Browser will use OS window dimensions - scrolling will work naturally');
169
+ return; // Skip viewport override in headful mode
170
+ }
171
+ // Only apply viewport override in headless mode
172
+ log.info('Headless mode detected - applying viewport override');
173
+ let defaultViewport = {
118
174
  width: 1920,
119
175
  height: 1080,
120
176
  deviceScaleFactor: 1,
121
177
  mobile: false,
122
178
  };
179
+ // Extract from fingerprint if available
180
+ if (fingerprint?.screen) {
181
+ // IMPORTANT: Set viewport height SMALLER than screen height to allow scrolling
182
+ // Reserve 150px for browser chrome, URL bar, and overflow space
183
+ const screenHeight = fingerprint.screen.height || 1080;
184
+ const viewportHeight = screenHeight - 150;
185
+ defaultViewport = {
186
+ width: fingerprint.screen.width || 1920,
187
+ height: viewportHeight,
188
+ deviceScaleFactor: fingerprint.screen.devicePixelRatio || 1,
189
+ mobile: false,
190
+ };
191
+ log.info('Viewport configured for scrolling', {
192
+ screenHeight,
193
+ viewportHeight,
194
+ reservedSpace: 150,
195
+ width: defaultViewport.width,
196
+ deviceScaleFactor: defaultViewport.deviceScaleFactor,
197
+ });
198
+ }
123
199
  const finalViewport = Object.assign(defaultViewport, viewport);
124
- // CDP call to override device metrics
200
+ log.info('Final viewport settings (headless mode)', finalViewport);
201
+ // CDP call to override device metrics (headless mode only)
125
202
  await this.page.client.Emulation.setDeviceMetricsOverride(finalViewport);
203
+ log.info('setDeviceMetricsOverride completed (headless mode)');
126
204
  }
127
205
  async setExtraHTTPHeaders(headers) {
128
206
  await this.page.client.Network.setExtraHTTPHeaders({ headers });
@@ -150,18 +228,140 @@ export class CdpFingerprintInjector {
150
228
  const stealthScript = createStealthScript();
151
229
  await this.page.client.Page.addScriptToEvaluateOnNewDocument({ source: stealthScript });
152
230
  }
231
+ /**
232
+ * Create a debug script that logs fingerprint override status to the console
233
+ */
234
+ createDebugScript(options) {
235
+ return `
236
+ (() => {
237
+ // CDP Fingerprint Override Debug Logs
238
+ const DEBUG_PREFIX = '[CDP-FP-DEBUG]';
239
+
240
+ console.log(DEBUG_PREFIX, '=== Fingerprint Override Status ===');
241
+ console.log(DEBUG_PREFIX, 'Timestamp:', new Date().toISOString());
242
+
243
+ // Check navigator properties
244
+ console.log(DEBUG_PREFIX, 'Navigator Checks:');
245
+ console.log(DEBUG_PREFIX, ' - platform:', navigator.platform);
246
+ console.log(DEBUG_PREFIX, ' - userAgent:', navigator.userAgent.substring(0, 80) + '...');
247
+ console.log(DEBUG_PREFIX, ' - webdriver:', navigator.webdriver);
248
+ console.log(DEBUG_PREFIX, ' - hardwareConcurrency:', navigator.hardwareConcurrency);
249
+ console.log(DEBUG_PREFIX, ' - deviceMemory:', navigator.deviceMemory);
250
+ console.log(DEBUG_PREFIX, ' - language:', navigator.language);
251
+ console.log(DEBUG_PREFIX, ' - languages:', navigator.languages);
252
+ console.log(DEBUG_PREFIX, ' - maxTouchPoints:', navigator.maxTouchPoints);
253
+ console.log(DEBUG_PREFIX, ' - pdfViewerEnabled:', navigator.pdfViewerEnabled);
254
+ console.log(DEBUG_PREFIX, ' - plugins.length:', navigator.plugins?.length);
255
+
256
+ // Check screen properties
257
+ console.log(DEBUG_PREFIX, 'Screen Checks:');
258
+ console.log(DEBUG_PREFIX, ' - colorDepth:', screen.colorDepth);
259
+ console.log(DEBUG_PREFIX, ' - pixelDepth:', screen.pixelDepth);
260
+ console.log(DEBUG_PREFIX, ' - availWidth:', screen.availWidth);
261
+ console.log(DEBUG_PREFIX, ' - availHeight:', screen.availHeight);
262
+ console.log(DEBUG_PREFIX, ' - devicePixelRatio:', window.devicePixelRatio);
263
+
264
+ // Check window properties
265
+ console.log(DEBUG_PREFIX, 'Window Checks:');
266
+ console.log(DEBUG_PREFIX, ' - outerWidth:', window.outerWidth);
267
+ console.log(DEBUG_PREFIX, ' - outerHeight:', window.outerHeight);
268
+ console.log(DEBUG_PREFIX, ' - screenX:', window.screenX);
269
+ console.log(DEBUG_PREFIX, ' - screenY:', window.screenY);
270
+
271
+ // Check chrome object
272
+ console.log(DEBUG_PREFIX, 'Chrome Object:');
273
+ console.log(DEBUG_PREFIX, ' - chrome exists:', typeof window.chrome !== 'undefined');
274
+ console.log(DEBUG_PREFIX, ' - chrome.runtime exists:', typeof window.chrome?.runtime !== 'undefined');
275
+
276
+ // Check WebGL
277
+ try {
278
+ const canvas = document.createElement('canvas');
279
+ const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
280
+ if (gl) {
281
+ const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
282
+ if (debugInfo) {
283
+ console.log(DEBUG_PREFIX, 'WebGL Checks:');
284
+ console.log(DEBUG_PREFIX, ' - vendor:', gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL));
285
+ console.log(DEBUG_PREFIX, ' - renderer:', gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL));
286
+ } else {
287
+ console.log(DEBUG_PREFIX, 'WebGL debug extension not available');
288
+ }
289
+ } else {
290
+ console.log(DEBUG_PREFIX, 'WebGL context not available');
291
+ }
292
+ } catch (e) {
293
+ console.log(DEBUG_PREFIX, 'WebGL check failed:', e.message);
294
+ }
295
+
296
+ // Check automation markers
297
+ console.log(DEBUG_PREFIX, 'Automation Marker Checks:');
298
+ console.log(DEBUG_PREFIX, ' - $cdc_ properties:', Object.keys(window).filter(k => k.startsWith('$cdc_') || k.startsWith('cdc_')).length === 0 ? 'CLEAN' : 'DETECTED');
299
+ console.log(DEBUG_PREFIX, ' - webdriver properties:', Object.keys(window).filter(k => k.toLowerCase().includes('webdriver')).length === 0 ? 'CLEAN' : 'DETECTED');
300
+
301
+ // Check permissions API
302
+ if (navigator.permissions) {
303
+ navigator.permissions.query({ name: 'notifications' }).then(result => {
304
+ console.log(DEBUG_PREFIX, 'Permissions:');
305
+ console.log(DEBUG_PREFIX, ' - notifications:', result.state);
306
+ }).catch(e => {
307
+ console.log(DEBUG_PREFIX, 'Permissions check failed:', e.message);
308
+ });
309
+ }
310
+
311
+ // Check storage estimate
312
+ if (navigator.storage && navigator.storage.estimate) {
313
+ navigator.storage.estimate().then(estimate => {
314
+ console.log(DEBUG_PREFIX, 'Storage:');
315
+ console.log(DEBUG_PREFIX, ' - quota:', Math.round(estimate.quota / 1024 / 1024 / 1024) + ' GB');
316
+ console.log(DEBUG_PREFIX, ' - usage:', Math.round(estimate.usage / 1024) + ' KB');
317
+ }).catch(e => {
318
+ console.log(DEBUG_PREFIX, 'Storage check failed:', e.message);
319
+ });
320
+ }
321
+
322
+ // Log applied options
323
+ console.log(DEBUG_PREFIX, 'Applied Options:');
324
+ console.log(DEBUG_PREFIX, ' - platform:', '${options.platform || "auto"}');
325
+ console.log(DEBUG_PREFIX, ' - enableAdvancedStealth:', ${options.enableAdvancedStealth !== false});
326
+ console.log(DEBUG_PREFIX, ' - bypassCDPDetection:', ${options.bypassCDPDetection !== false});
327
+ console.log(DEBUG_PREFIX, ' - spoofStorage:', ${options.spoofStorage !== false});
328
+ console.log(DEBUG_PREFIX, ' - spoofTiming:', ${options.spoofTiming !== false});
329
+ console.log(DEBUG_PREFIX, ' - enableDataDomeBypass:', ${options.enableDataDomeBypass || false});
330
+ console.log(DEBUG_PREFIX, ' - humanization.mouse:', ${options.humanization?.mouse || false});
331
+ console.log(DEBUG_PREFIX, ' - humanization.keyboard:', ${options.humanization?.keyboard || false});
332
+ console.log(DEBUG_PREFIX, ' - humanization.scroll:', ${options.humanization?.scroll || false});
333
+
334
+ console.log(DEBUG_PREFIX, '=== End Fingerprint Override Status ===');
335
+
336
+ // Store debug info globally for later inspection
337
+ window.__CDP_FINGERPRINT_DEBUG__ = {
338
+ timestamp: new Date().toISOString(),
339
+ platform: navigator.platform,
340
+ webdriver: navigator.webdriver,
341
+ deviceMemory: navigator.deviceMemory,
342
+ hardwareConcurrency: navigator.hardwareConcurrency,
343
+ appliedOptions: {
344
+ platform: '${options.platform || "auto"}',
345
+ enableAdvancedStealth: ${options.enableAdvancedStealth !== false},
346
+ bypassCDPDetection: ${options.bypassCDPDetection !== false},
347
+ enableDataDomeBypass: ${options.enableDataDomeBypass || false},
348
+ }
349
+ };
350
+ })();
351
+ `;
352
+ }
153
353
  /**
154
354
  * Extract relevant data from fingerprint for overrides
155
355
  */
156
356
  extractFingerprintData(fingerprint) {
157
357
  const webglConfig = {};
158
358
  const platformConfig = {};
159
- // Extract WebGL data if available
160
- if (fingerprint.webgl) {
161
- webglConfig.vendor = fingerprint.webgl.vendor;
162
- webglConfig.renderer = fingerprint.webgl.renderer;
163
- webglConfig.vendorUnmasked = fingerprint.webgl.vendorUnmasked;
164
- webglConfig.rendererUnmasked = fingerprint.webgl.rendererUnmasked;
359
+ // Extract WebGL data from videoCard if available
360
+ if (fingerprint.videoCard) {
361
+ webglConfig.vendor = fingerprint.videoCard.vendor;
362
+ webglConfig.renderer = fingerprint.videoCard.renderer;
363
+ webglConfig.vendorUnmasked = fingerprint.videoCard.vendor;
364
+ webglConfig.rendererUnmasked = fingerprint.videoCard.renderer;
165
365
  }
166
366
  // Extract platform data if available
167
367
  if (fingerprint.navigator) {
@@ -174,6 +374,12 @@ export class CdpFingerprintInjector {
174
374
  platformConfig.language = fingerprint.navigator.language;
175
375
  platformConfig.languages = fingerprint.navigator.languages;
176
376
  platformConfig.oscpu = fingerprint.navigator.oscpu;
377
+ // Extract userAgent and related properties from generated fingerprint
378
+ platformConfig.userAgent = fingerprint.navigator.userAgent;
379
+ platformConfig.appVersion = fingerprint.navigator.appVersion;
380
+ platformConfig.appName = fingerprint.navigator.appName;
381
+ platformConfig.appCodeName = fingerprint.navigator.appCodeName;
382
+ platformConfig.product = fingerprint.navigator.product;
177
383
  }
178
384
  if (fingerprint.screen) {
179
385
  platformConfig.devicePixelRatio = fingerprint.screen.devicePixelRatio;
@@ -191,21 +397,37 @@ export class CdpFingerprintInjector {
191
397
  if (timezone) {
192
398
  await this.setTimezoneOverride(timezone);
193
399
  }
194
- // Enable the Page domain so we can attach scripts
195
- await this.page.client.Page.enable();
196
- // "Enhance" the fingerprint so we can inject it
197
- const enhancedFingerprint = this.injector._enhanceFingerprint(fingerprint);
198
- // Filter out only headers we can actually inject
199
- const filteredHeaders = this.injector.onlyInjectableHeaders(headers, 'chrome');
200
- // Main script from fingerprint-injector
201
- // @ts-expect-error Using private
202
- const fingerprintScript = this.injector.getInjectableFingerprintFunction(enhancedFingerprint);
203
- // Prepare all scripts to inject
204
- const scriptsToInject = [fingerprintScript];
400
+ // NOTE: Page.enable() is required for addScriptToEvaluateOnNewDocument to work
401
+ // We enable it lazily just before script injection to minimize detection surface
402
+ await this.page.ensurePageEnabled();
403
+ // Filter headers to only include those that can be injected via CDP
404
+ const filteredHeaders = {};
405
+ const allowedHeaders = ['accept', 'accept-encoding', 'accept-language', 'user-agent', 'referer', 'sec-ch-ua', 'sec-ch-ua-mobile', 'sec-ch-ua-platform'];
406
+ for (const [key, value] of Object.entries(headers)) {
407
+ if (allowedHeaders.includes(key.toLowerCase()) && typeof value === 'string') {
408
+ filteredHeaders[key] = value;
409
+ }
410
+ }
411
+ // Create custom fingerprint injection scripts
412
+ log.info('Creating custom fingerprint injection scripts');
413
+ const customFingerprintScripts = createCustomFingerprintInjection(fingerprint, {
414
+ debug: options?.debug !== false,
415
+ throwOnError: true
416
+ });
417
+ // Prepare all scripts to inject - stealth utils and runtime bypass MUST be first
418
+ // These scripts set up protections BEFORE page JavaScript runs
419
+ const scriptsToInject = [
420
+ createStealthUtilsScript(), // Must be first - provides guards and toString spoofing
421
+ createPrototypeIntegrityScript(), // Second - provides native-like property descriptor masking
422
+ createRuntimeEnableBypassScript(), // Third - protects against CDP detection via Error stack analysis
423
+ ...customFingerprintScripts, // Custom fingerprint injection replacing fingerprint-injector
424
+ ];
205
425
  // Always inject base stealth protections
206
426
  await this.injectStealthProtections();
207
427
  // Extract fingerprint data if we should use it
208
- const shouldUseFingerprintData = options?.useFingerprintDefaults !== false;
428
+ // When useFingerprintDefaults is true (or undefined), use hardcoded defaults
429
+ // When useFingerprintDefaults is false, use the generated fingerprint data
430
+ const shouldUseFingerprintData = options?.useFingerprintDefaults === false;
209
431
  const { webglConfig, platformConfig } = shouldUseFingerprintData
210
432
  ? this.extractFingerprintData(fingerprint)
211
433
  : { webglConfig: undefined, platformConfig: undefined };
@@ -243,34 +465,220 @@ export class CdpFingerprintInjector {
243
465
  if (options?.spoofLocale !== false) {
244
466
  scriptsToInject.push(createLocaleSpoofingScript());
245
467
  }
468
+ // 2024-2025 New protections
469
+ // CDP Detection Bypass
470
+ if (options?.bypassCDPDetection !== false) {
471
+ scriptsToInject.push(createCDPDetectionBypassScript());
472
+ }
473
+ // Storage consistency
474
+ if (options?.spoofStorage !== false) {
475
+ scriptsToInject.push(createStorageConsistencyScript());
476
+ }
477
+ // Timing consistency
478
+ if (options?.spoofTiming !== false) {
479
+ scriptsToInject.push(createTimingConsistencyScript());
480
+ }
481
+ // DataDome-specific bypass
482
+ if (options?.enableDataDomeBypass) {
483
+ scriptsToInject.push(createDataDomeBypassScript());
484
+ }
485
+ // Keyboard humanization (browser context) - disabled by default
486
+ if (options?.humanization?.keyboard) {
487
+ scriptsToInject.push(createKeyboardHumanizationScript());
488
+ }
489
+ // Scroll humanization (browser context) - disabled by default
490
+ if (options?.humanization?.scroll) {
491
+ scriptsToInject.push(createScrollHumanizationScript());
492
+ }
246
493
  }
247
494
  // Apply platform consistency script
248
495
  if (options?.platform) {
249
496
  scriptsToInject.push(createPlatformConsistencyScript(options.platform, shouldUseFingerprintData ? platformConfig : undefined));
250
497
  }
251
- // Inject all scripts
252
- await Promise.all([
253
- this.setViewport(options?.viewport),
254
- this.setExtraHTTPHeaders(filteredHeaders),
255
- ...scriptsToInject.map(async (script) => this.page.client.Page.addScriptToEvaluateOnNewDocument({ source: script })),
256
- ]);
257
- // Setup mouse movement humanization if requested
258
- if (options?.humanizeInteractions) {
498
+ // CRITICAL: Clean scripts to remove CDP detection patterns
499
+ // Remove sourceURL comments that reveal CDP injection
500
+ const cleanScript = (script) => {
501
+ return script
502
+ // Remove sourceURL patterns that reveal CDP injection
503
+ .replace(/\/\/# sourceURL=[^\n]*/g, '')
504
+ .replace(/\/\/@ sourceURL=[^\n]*/g, '')
505
+ // Remove sourceMappingURL patterns
506
+ .replace(/\/\/# sourceMappingURL=[^\n]*/g, '')
507
+ // Remove puppeteer/playwright markers
508
+ .replace(/__puppeteer_evaluation_script__/g, 'anonymous')
509
+ .replace(/__playwright_evaluation_script__/g, 'anonymous')
510
+ // Remove CDP-specific comments
511
+ .replace(/\/\*\s*__CDP_[A-Z_]+__\s*\*\//g, '');
512
+ };
513
+ // BUNDLE ALL SCRIPTS INTO ONE to minimize CDP interactions
514
+ // Each addScriptToEvaluateOnNewDocument call is a detection opportunity
515
+ log.info(`Bundling ${scriptsToInject.length} fingerprint scripts into single injection`);
516
+ const bundledScript = scriptsToInject
517
+ .map(script => cleanScript(script))
518
+ .join('\n\n// --- Next Module ---\n\n');
519
+ // Validate bundled script for syntax errors
520
+ try {
521
+ new Function(bundledScript);
522
+ log.info('✓ Bundled script passed syntax validation');
523
+ }
524
+ catch (error) {
525
+ log.error('✗ Bundled script has syntax error:', { error });
526
+ // Fall back to individual script validation to find the culprit
527
+ scriptsToInject.forEach((script, index) => {
528
+ try {
529
+ new Function(script);
530
+ }
531
+ catch (e) {
532
+ const scriptPreview = script.substring(0, 300);
533
+ log.error(`✗ Error in script ${index + 1}:`, { error: e, scriptPreview });
534
+ }
535
+ });
536
+ throw new Error(`Bundled script has syntax error: ${error}`);
537
+ }
538
+ // Inject SINGLE bundled script - reduces CDP detection surface
539
+ try {
540
+ log.info('Injecting single bundled fingerprint script (minimizes CDP detection)');
541
+ await Promise.all([
542
+ this.setViewport(options?.viewport, fingerprint),
543
+ this.setExtraHTTPHeaders(filteredHeaders),
544
+ // Single script injection instead of many - reduces CDP detection surface
545
+ (async () => {
546
+ try {
547
+ await this.page.client.Page.addScriptToEvaluateOnNewDocument({
548
+ source: bundledScript
549
+ });
550
+ log.info('✓ Bundled script injected successfully');
551
+ }
552
+ catch (error) {
553
+ const scriptPreview = bundledScript.substring(0, 200).split('\n')[0];
554
+ log.error('✗ Failed to inject bundled script:', {
555
+ error,
556
+ scriptPreview,
557
+ });
558
+ throw error; // Rethrow to fail the entire injection
559
+ }
560
+ })(),
561
+ ]);
562
+ log.info('✓ Fingerprint injection complete (single bundled script)');
563
+ }
564
+ catch (error) {
565
+ log.error('✗ Failed to inject fingerprint scripts:', { error });
566
+ throw error; // Rethrow to make injection failures visible
567
+ }
568
+ // Setup mouse movement humanization if requested (disabled by default)
569
+ // Support both legacy humanizeInteractions and new humanization.mouse
570
+ const enableMouseHumanization = options?.humanization?.mouse || options?.humanizeInteractions;
571
+ if (enableMouseHumanization) {
259
572
  await setupMouseMovementHumanization(this.page.client);
260
573
  }
261
- // Additional CDP-level protections
262
- if (options?.bypassRuntimeEnable) {
263
- await setupRuntimeEnableBypass(this.page.client);
574
+ // NOTE: setupRuntimeEnableBypass REMOVED - it uses Runtime.evaluate which is itself a detection vector!
575
+ // The bypass script is now included in the bundled stealth scripts injected via addScriptToEvaluateOnNewDocument
576
+ // This runs BEFORE page JavaScript, avoiding Runtime domain activation
577
+ // 2024-2025: CDP-level keyboard humanization (disabled by default)
578
+ if (options?.humanization?.keyboard) {
579
+ await setupKeyboardHumanization(this.page.client);
580
+ }
581
+ // 2024-2025: CDP-level scroll humanization (disabled by default)
582
+ if (options?.humanization?.scroll) {
583
+ await setupScrollHumanization(this.page.client);
584
+ }
585
+ // Inject debug script for browser console verification (always inject for debugging)
586
+ if (options?.debug !== false) {
587
+ const debugScript = this.createDebugScript(options || {});
588
+ await this.page.client.Page.addScriptToEvaluateOnNewDocument({ source: debugScript });
264
589
  }
265
590
  log.info('Enhanced fingerprint attached with settings:', {
266
591
  proxy: options?.proxyUrl,
267
592
  timezone,
268
593
  advancedStealth: options?.enableAdvancedStealth !== false,
269
- humanizeInteractions: options?.humanizeInteractions,
270
594
  bypassRuntimeEnable: options?.bypassRuntimeEnable,
271
595
  platform: options?.platform,
272
596
  useFingerprintDefaults: options?.useFingerprintDefaults,
597
+ // 2024-2025 new options
598
+ bypassCDPDetection: options?.bypassCDPDetection !== false,
599
+ spoofStorage: options?.spoofStorage !== false,
600
+ spoofTiming: options?.spoofTiming !== false,
601
+ enableDataDomeBypass: options?.enableDataDomeBypass,
602
+ // Humanization options
603
+ humanization: {
604
+ mouse: enableMouseHumanization || false,
605
+ keyboard: options?.humanization?.keyboard || false,
606
+ scroll: options?.humanization?.scroll || false,
607
+ },
608
+ // Viewport info
609
+ viewport: options?.viewport,
610
+ fingerprintScreen: fingerprint?.screen ? {
611
+ width: fingerprint.screen.width,
612
+ height: fingerprint.screen.height,
613
+ devicePixelRatio: fingerprint.screen.devicePixelRatio,
614
+ } : undefined,
273
615
  });
616
+ // Add a debug script to log viewport info in the browser console
617
+ const viewportDebugScript = `
618
+ (() => {
619
+ console.log('[VIEWPORT-DEBUG] Initial window dimensions:', {
620
+ innerWidth: window.innerWidth,
621
+ innerHeight: window.innerHeight,
622
+ outerWidth: window.outerWidth,
623
+ outerHeight: window.outerHeight,
624
+ screenWidth: screen.width,
625
+ screenHeight: screen.height,
626
+ availWidth: screen.availWidth,
627
+ availHeight: screen.availHeight,
628
+ devicePixelRatio: window.devicePixelRatio,
629
+ scrollY: window.scrollY,
630
+ scrollHeight: document.documentElement?.scrollHeight || 'N/A',
631
+ clientHeight: document.documentElement?.clientHeight || 'N/A'
632
+ });
633
+
634
+ // Check consistency
635
+ const inconsistencies = [];
636
+ if (window.innerWidth !== screen.width && Math.abs(window.innerWidth - screen.width) > 50) {
637
+ inconsistencies.push(\`innerWidth (\${window.innerWidth}) != screen.width (\${screen.width})\`);
638
+ }
639
+ if (window.innerHeight !== screen.height && Math.abs(window.innerHeight - screen.height) > 100) {
640
+ inconsistencies.push(\`innerHeight (\${window.innerHeight}) != screen.height (\${screen.height})\`);
641
+ }
642
+
643
+ if (inconsistencies.length > 0) {
644
+ console.warn('[VIEWPORT-DEBUG] ⚠️ INCONSISTENCIES DETECTED:', inconsistencies);
645
+ } else {
646
+ console.log('[VIEWPORT-DEBUG] ✅ Dimensions appear consistent');
647
+ }
648
+
649
+ // Test scrolling after DOM is ready
650
+ const checkScroll = () => {
651
+ if (document.documentElement) {
652
+ const scrollHeight = document.documentElement.scrollHeight;
653
+ const clientHeight = document.documentElement.clientHeight;
654
+ const canScroll = scrollHeight > clientHeight;
655
+
656
+ console.log('[VIEWPORT-DEBUG] After load:', {
657
+ scrollHeight,
658
+ clientHeight,
659
+ canScroll,
660
+ overflow: scrollHeight - clientHeight,
661
+ bodyHeight: document.body?.scrollHeight,
662
+ innerHeight: window.innerHeight,
663
+ screenHeight: screen.height
664
+ });
665
+
666
+ if (canScroll) {
667
+ console.log('[VIEWPORT-DEBUG] ✅ SCROLLING ENABLED - Page has', scrollHeight - clientHeight, 'px overflow');
668
+ } else {
669
+ console.log('[VIEWPORT-DEBUG] ⚠️ NO OVERFLOW - Cannot scroll (scrollHeight === clientHeight)');
670
+ }
671
+ }
672
+ };
673
+
674
+ if (document.readyState === 'loading') {
675
+ document.addEventListener('DOMContentLoaded', checkScroll);
676
+ } else {
677
+ setTimeout(checkScroll, 1000);
678
+ }
679
+ })();
680
+ `;
681
+ await this.page.client.Page.addScriptToEvaluateOnNewDocument({ source: viewportDebugScript });
274
682
  }
275
683
  }
276
684
  //# sourceMappingURL=fingerprint-injector.js.map