@fanboynz/network-scanner 2.0.9 → 2.0.11

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.
@@ -970,6 +970,90 @@ async function isBrowserHealthy(browserInstance, includeNetworkTest = true) {
970
970
  }
971
971
  }
972
972
 
973
+ /**
974
+ * Performs comprehensive cleanup of page resources before operations that might cause detached frames
975
+ * Also attempts to stop any pending navigations that might interfere
976
+ * Used before reloads, navigations, and other operations that can trigger frame detachment
977
+ * @param {import('puppeteer').Page} page - Page to clean up
978
+ * @param {boolean} forceDebug - Debug logging flag
979
+ * @returns {Promise<boolean>} True if cleanup succeeded
980
+ */
981
+ async function cleanupPageBeforeReload(page, forceDebug = false) {
982
+ try {
983
+ if (page.isClosed()) {
984
+ return false;
985
+ }
986
+
987
+ // First, try to stop any pending navigation
988
+ try {
989
+ await page.evaluate(() => {
990
+ // Stop any ongoing navigation
991
+ if (window.stop) {
992
+ window.stop();
993
+ }
994
+ });
995
+ } catch (e) {
996
+ // Page might be mid-navigation, that's ok
997
+ }
998
+
999
+ // Wait a bit for navigation to stop
1000
+ await new Promise(resolve => setTimeout(resolve, 500));
1001
+
1002
+ // Now do the full cleanup
1003
+ await page.evaluate(() => {
1004
+ // Stop all media elements
1005
+ document.querySelectorAll('video, audio').forEach(media => {
1006
+ try {
1007
+ media.pause();
1008
+ media.src = '';
1009
+ media.load();
1010
+ } catch(e) {}
1011
+ });
1012
+
1013
+ // Clear all timers and intervals
1014
+ const highestId = setTimeout(() => {}, 0);
1015
+ for (let i = highestId; i >= 0; i--) {
1016
+ clearTimeout(i);
1017
+ clearInterval(i);
1018
+ }
1019
+
1020
+ // Stop all animations
1021
+ if (typeof cancelAnimationFrame !== 'undefined') {
1022
+ const highestRAF = requestAnimationFrame(() => {});
1023
+ for (let i = highestRAF; i >= 0; i--) {
1024
+ cancelAnimationFrame(i);
1025
+ }
1026
+ }
1027
+
1028
+ // Clear all iframes properly
1029
+ document.querySelectorAll('iframe').forEach(iframe => {
1030
+ try {
1031
+ // Stop iframe content first
1032
+ if (iframe.contentWindow) {
1033
+ iframe.contentWindow.stop();
1034
+ }
1035
+ iframe.src = 'about:blank';
1036
+ iframe.remove();
1037
+ } catch(e) {}
1038
+ });
1039
+
1040
+ // Force garbage collection if available
1041
+ if (window.gc) window.gc();
1042
+ });
1043
+
1044
+ if (forceDebug) {
1045
+ console.log(formatLogMessage('debug', 'Page resources cleaned before reload'));
1046
+ }
1047
+
1048
+ return true;
1049
+ } catch (err) {
1050
+ if (forceDebug) {
1051
+ console.log(formatLogMessage('debug', `Page cleanup error: ${err.message}`));
1052
+ }
1053
+ return false;
1054
+ }
1055
+ }
1056
+
973
1057
  module.exports = {
974
1058
  checkBrowserHealth,
975
1059
  checkBrowserMemory,
@@ -983,7 +1067,8 @@ module.exports = {
983
1067
  monitorBrowserHealth,
984
1068
  isBrowserHealthy,
985
1069
  isCriticalProtocolError,
986
- updatePageUsage
1070
+ updatePageUsage,
1071
+ cleanupPageBeforeReload
987
1072
  };
988
1073
 
989
1074
  // Clean up tracking maps when pages are closed
package/lib/cloudflare.js CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * Cloudflare bypass and challenge handling module - Optimized with smart detection and adaptive timeouts
3
+ * Version: 2.6.3 - Fixes Cannot read properties of undefined (reading 'hasIndicators')
3
4
  * Version: 2.6.2 - Further detached Frame fixes
4
5
  * Version: 2.6.1 - timeoutId is not defined & race condition fix
5
6
  * Version: 2.6.0 - Memory leak fixes and timeout cleanup
@@ -19,7 +20,7 @@ const { formatLogMessage } = require('./colorize');
19
20
  /**
20
21
  * Module version information
21
22
  */
22
- const CLOUDFLARE_MODULE_VERSION = '2.6.2';
23
+ const CLOUDFLARE_MODULE_VERSION = '2.6.3';
23
24
 
24
25
  /**
25
26
  * Timeout constants for various operations (in milliseconds)
@@ -1570,6 +1571,11 @@ async function handleCloudflareProtection(page, currentUrl, siteConfig, forceDeb
1570
1571
 
1571
1572
  // Quick detection first - exit early if no Cloudflare detected and no explicit config
1572
1573
  const quickDetection = await quickCloudflareDetection(page, forceDebug);
1574
+
1575
+ // Safety check: ensure quickDetection is valid
1576
+ if (!quickDetection) {
1577
+ return { phishingWarning: { attempted: false, success: true }, verificationChallenge: { attempted: false, success: true }, overallSuccess: true, errors: [], quickDetectionFailed: true };
1578
+ }
1573
1579
 
1574
1580
  // Early return structure when no Cloudflare indicators found
1575
1581
  // Sets attempted: false, success: true for both protection types
@@ -173,6 +173,23 @@ function generateCSIData() {
173
173
  };
174
174
  }
175
175
 
176
+ /**
177
+ * Validates page state before script injection to avoid timeouts
178
+ */
179
+ async function validatePageForInjection(page, currentUrl, forceDebug) {
180
+ try {
181
+ if (page.isClosed()) return false;
182
+ await Promise.race([
183
+ page.evaluate(() => document.readyState),
184
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Page unresponsive')), 3000))
185
+ ]);
186
+ return true;
187
+ } catch (validationErr) {
188
+ if (forceDebug) console.log(`[debug] Skipping fingerprint protection - page unresponsive: ${currentUrl}`);
189
+ return false;
190
+ }
191
+ }
192
+
176
193
  /**
177
194
  * Creates mock fingerprinting objects
178
195
  */
@@ -251,6 +268,9 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
251
268
 
252
269
  if (forceDebug) console.log(`[debug] User agent spoofing: ${siteConfig.userAgent}`);
253
270
 
271
+ // Validate page state before injection
272
+ if (!(await validatePageForInjection(page, currentUrl, forceDebug))) return;
273
+
254
274
  const selectedUserAgents = USER_AGENT_COLLECTIONS[siteConfig.userAgent.toLowerCase()];
255
275
  const ua = selectedUserAgents ? selectedUserAgents[Math.floor(Math.random() * selectedUserAgents.length)] : null;
256
276
 
@@ -660,6 +680,12 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
660
680
 
661
681
  }, ua, forceDebug);
662
682
  } catch (stealthErr) {
683
+ if (stealthErr.message.includes('Session closed') ||
684
+ stealthErr.message.includes('addScriptToEvaluateOnNewDocument timed out') ||
685
+ stealthErr.message.includes('Target closed')) {
686
+ if (forceDebug) console.log(`[debug] Page closed during stealth injection: ${currentUrl}`);
687
+ return;
688
+ }
663
689
  console.warn(`[stealth protection failed] ${currentUrl}: ${stealthErr.message}`);
664
690
  }
665
691
  }
@@ -672,8 +698,23 @@ async function applyBraveSpoofing(page, siteConfig, forceDebug, currentUrl) {
672
698
  if (!siteConfig.isBrave) return;
673
699
 
674
700
  if (forceDebug) console.log(`[debug] Brave spoofing enabled for ${currentUrl}`);
701
+
702
+ // Validate page state before injection
703
+ if (!(await validatePageForInjection(page, currentUrl, forceDebug))) return;
675
704
 
676
- await page.evaluateOnNewDocument((debugEnabled) => {
705
+ try {
706
+ await page.evaluateOnNewDocument((debugEnabled) => {
707
+ // ... existing Brave spoofing code ...
708
+ }, forceDebug);
709
+ } catch (braveErr) {
710
+ if (braveErr.message.includes('Session closed') ||
711
+ braveErr.message.includes('addScriptToEvaluateOnNewDocument timed out') ||
712
+ braveErr.message.includes('Target closed')) {
713
+ if (forceDebug) console.log(`[debug] Page closed during Brave injection: ${currentUrl}`);
714
+ return;
715
+ }
716
+ if (forceDebug) console.log(`[debug] Brave spoofing failed: ${currentUrl} - ${braveErr.message}`);
717
+ }
677
718
  try {
678
719
  Object.defineProperty(navigator, 'brave', {
679
720
  get: () => ({
@@ -695,7 +736,6 @@ async function applyBraveSpoofing(page, siteConfig, forceDebug, currentUrl) {
695
736
  } catch (err) {
696
737
  if (debugEnabled) console.log(`[fingerprint] Brave spoofing error: ${err.message}`);
697
738
  }
698
- }, forceDebug);
699
739
  }
700
740
 
701
741
  /**
@@ -707,6 +747,9 @@ async function applyFingerprintProtection(page, siteConfig, forceDebug, currentU
707
747
 
708
748
  if (forceDebug) console.log(`[debug] Fingerprint protection enabled for ${currentUrl}`);
709
749
 
750
+ // Validate page state before injection
751
+ if (!(await validatePageForInjection(page, currentUrl, forceDebug))) return;
752
+
710
753
  const spoof = fingerprintSetting === 'random' ? getRandomFingerprint() : {
711
754
  deviceMemory: 8,
712
755
  hardwareConcurrency: 4,
@@ -796,6 +839,12 @@ async function applyFingerprintProtection(page, siteConfig, forceDebug, currentU
796
839
 
797
840
  }, { spoof, debugEnabled: forceDebug });
798
841
  } catch (err) {
842
+ if (err.message.includes('Session closed') ||
843
+ err.message.includes('addScriptToEvaluateOnNewDocument timed out') ||
844
+ err.message.includes('Target closed')) {
845
+ if (forceDebug) console.log(`[debug] Page closed during fingerprint injection: ${currentUrl}`);
846
+ return;
847
+ }
799
848
  console.warn(`[fingerprint protection failed] ${currentUrl}: ${err.message}`);
800
849
  }
801
850
  }
package/nwss.js CHANGED
@@ -1,4 +1,4 @@
1
- // === Network scanner script (nwss.js) v2.0.9 ===
1
+ // === Network scanner script (nwss.js) v2.0.11 ===
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
@@ -55,19 +55,20 @@ function fastTimeout(ms) {
55
55
 
56
56
  // --- Configuration Constants ---
57
57
  const TIMEOUTS = {
58
- DEFAULT_PAGE: 30000,
59
- DEFAULT_NAVIGATION: 25000,
58
+ DEFAULT_PAGE: 35000, // Standard page load timeout (35s)
59
+ DEFAULT_NAVIGATION: 25000, // Navigation operation timeout
60
60
  DEFAULT_NAVIGATION_REDUCED: 20000, // Reduced timeout for faster failures
61
- DEFAULT_PAGE_REDUCED: 15000, // Reduced page timeout
62
- FRAME_LOAD_WAIT: 2000,
63
- NETWORK_IDLE: 2000,
64
- NETWORK_IDLE_MAX: 10000,
65
- FAST_SITE_THRESHOLD: 15000,
66
- EMERGENCY_RESTART_DELAY: 2000,
67
- BROWSER_STABILIZE_DELAY: 1000,
68
- CURL_HANDLER_DELAY: 3000,
69
- PROTOCOL_TIMEOUT: 120000,
70
- REDIRECT_JS_TIMEOUT: 5000
61
+ DEFAULT_PAGE_REDUCED: 15000, // Faster page timeout for quick failures
62
+ FRAME_LOAD_WAIT: 2000, // Wait time for iframes to load
63
+ DEFAULT_DELAY: 6000, // Default delay: after page load
64
+ NETWORK_IDLE: 2000, // Network idle detection time
65
+ NETWORK_IDLE_MAX: 10000, // Maximum network idle wait time
66
+ FAST_SITE_THRESHOLD: 15000, // Threshold for "fast site" optimizations
67
+ EMERGENCY_RESTART_DELAY: 2000, // Delay after emergency browser restart
68
+ BROWSER_STABILIZE_DELAY: 1000, // Browser stabilization after restart
69
+ CURL_HANDLER_DELAY: 3000, // Wait for async curl operations
70
+ PROTOCOL_TIMEOUT: 180000, // Chrome DevTools Protocol timeout
71
+ REDIRECT_JS_TIMEOUT: 5000 // JavaScript redirect detection timeout
71
72
  };
72
73
 
73
74
  const CACHE_LIMITS = {
@@ -126,10 +127,10 @@ function detectPuppeteerVersion() {
126
127
  // Enhanced redirect handling
127
128
  const { navigateWithRedirectHandling, handleRedirectTimeout } = require('./lib/redirect');
128
129
  // Ensure web browser is working correctly
129
- const { monitorBrowserHealth, isBrowserHealthy, isQuicklyResponsive, performGroupWindowCleanup, performRealtimeWindowCleanup, trackPageForRealtime, updatePageUsage } = require('./lib/browserhealth');
130
+ const { monitorBrowserHealth, isBrowserHealthy, isQuicklyResponsive, performGroupWindowCleanup, performRealtimeWindowCleanup, trackPageForRealtime, updatePageUsage, cleanupPageBeforeReload } = require('./lib/browserhealth');
130
131
 
131
132
  // --- Script Configuration & Constants ---
132
- const VERSION = '2.0.9'; // Script version
133
+ const VERSION = '2.0.11'; // Script version
133
134
 
134
135
  // get startTime
135
136
  const startTime = Date.now();
@@ -1087,7 +1088,7 @@ function matchesIgnoreDomain(domain, ignorePatterns) {
1087
1088
 
1088
1089
  function setupFrameHandling(page, forceDebug) {
1089
1090
  // Track active frames and clear on navigation to prevent detached frame access
1090
- let activeFrames = new Set();
1091
+ let activeFrames = new Map(); // Use Map to track frame state
1091
1092
 
1092
1093
  // Clear frame tracking on navigation to prevent stale references
1093
1094
  page.on('framenavigated', (frame) => {
@@ -1101,6 +1102,15 @@ function setupFrameHandling(page, forceDebug) {
1101
1102
  page.on('frameattached', async (frame) => {
1102
1103
  // Enhanced frame handling with detached frame protection
1103
1104
  try {
1105
+ // Test frame accessibility first with safe method
1106
+ let isFrameValid = false;
1107
+ try {
1108
+ frame.url(); // This will throw if frame is detached
1109
+ isFrameValid = true;
1110
+ } catch (e) {
1111
+ return; // Frame is already detached, skip
1112
+ }
1113
+
1104
1114
  // Multiple checks for frame validity to prevent detached frame errors
1105
1115
  if (!frame) {
1106
1116
  if (forceDebug) {
@@ -1136,7 +1146,10 @@ function setupFrameHandling(page, forceDebug) {
1136
1146
  return;
1137
1147
  }
1138
1148
 
1139
- if (frame.parentFrame()) { // Only handle child frames, not main frame
1149
+ // Store frame with timestamp for tracking
1150
+ activeFrames.set(frame, Date.now());
1151
+
1152
+ if (frame !== page.mainFrame() && frame.parentFrame()) { // Only handle child frames
1140
1153
  try {
1141
1154
  if (forceDebug) {
1142
1155
  console.log(formatLogMessage('debug', `New frame attached: ${frameUrl || 'about:blank'}`));
@@ -1979,7 +1992,17 @@ function setupFrameHandling(page, forceDebug) {
1979
1992
  }
1980
1993
 
1981
1994
  // --- Apply all fingerprint spoofing (user agent, Brave, fingerprint protection) ---
1982
- await applyAllFingerprintSpoofing(page, siteConfig, forceDebug, currentUrl);
1995
+ try {
1996
+ await applyAllFingerprintSpoofing(page, siteConfig, forceDebug, currentUrl);
1997
+ } catch (fingerprintErr) {
1998
+ if (fingerprintErr.message.includes('Session closed') ||
1999
+ fingerprintErr.message.includes('Protocol error') ||
2000
+ fingerprintErr.message.includes('addScriptToEvaluateOnNewDocument')) {
2001
+ console.warn(`[fingerprint protection failed] ${currentUrl}: ${fingerprintErr.message}`);
2002
+ } else {
2003
+ throw fingerprintErr;
2004
+ }
2005
+ }
1983
2006
 
1984
2007
  const regexes = Array.isArray(siteConfig.filterRegex)
1985
2008
  ? siteConfig.filterRegex.map(r => new RegExp(r.replace(/^\/(.*)\/$/, '$1')))
@@ -3082,6 +3105,18 @@ function setupFrameHandling(page, forceDebug) {
3082
3105
  // Page finished initial loading - mark as idle
3083
3106
  updatePageUsage(page, false);
3084
3107
  } catch (err) {
3108
+ // Handle detached frame errors during navigation
3109
+ if (err.message.includes('Navigating frame was detached') ||
3110
+ err.message.includes('Attempted to use detached')) {
3111
+ // Silent handling - this is expected for iframe-heavy sites
3112
+ if (forceDebug) {
3113
+ console.log(formatLogMessage('debug', `Frame detachment during navigation (expected): ${currentUrl}`));
3114
+ }
3115
+ // Continue with partial success - don't fail completely
3116
+ currentPageUrl = currentUrl;
3117
+ siteCounter++;
3118
+ // Skip to post-navigation processing
3119
+ } else {
3085
3120
  // Enhanced error handling for redirect timeouts using redirect module
3086
3121
  const timeoutResult = await handleRedirectTimeout(page, currentUrl, err, safeGetDomain, forceDebug, formatLogMessage);
3087
3122
 
@@ -3095,6 +3130,7 @@ function setupFrameHandling(page, forceDebug) {
3095
3130
  throw err;
3096
3131
  }
3097
3132
  }
3133
+ }
3098
3134
 
3099
3135
  if (interactEnabled && !disableInteract) {
3100
3136
  if (forceDebug) console.log(formatLogMessage('debug', `interaction simulation enabled for ${currentUrl}`));
@@ -3105,7 +3141,7 @@ function setupFrameHandling(page, forceDebug) {
3105
3141
  await performPageInteraction(page, currentUrl, interactionConfig, forceDebug);
3106
3142
  }
3107
3143
 
3108
- const delayMs = siteConfig.delay || 4000;
3144
+ const delayMs = DEFAULT_DELAY;
3109
3145
 
3110
3146
  // Optimized delays for Puppeteer 23.x performance
3111
3147
  const isFastSite = timeout <= TIMEOUTS.FAST_SITE_THRESHOLD;
@@ -3141,13 +3177,41 @@ function setupFrameHandling(page, forceDebug) {
3141
3177
  }
3142
3178
 
3143
3179
  for (let i = 1; i <= totalReloads; i++) {
3144
- // Clear any stale frame references before reload
3180
+ // Check browser health before attempting reload
3181
+ try {
3182
+ const browserHealthy = await isQuicklyResponsive(browser, 2000);
3183
+ if (!browserHealthy) {
3184
+ if (forceDebug) {
3185
+ console.log(formatLogMessage('debug', `Browser unresponsive before reload #${i}, skipping remaining reloads`));
3186
+ }
3187
+ console.warn(`Browser unresponsive before reload #${i}, skipping remaining reloads`);
3188
+ break;
3189
+ }
3190
+ } catch (healthErr) {
3191
+ console.warn(`Browser health check failed before reload #${i}: ${healthErr.message}`);
3192
+ break;
3193
+ }
3194
+ // Check if page is still valid before attempting reload
3195
+ let pageStillValid = false;
3145
3196
  try {
3146
- await page.evaluate(() => {
3147
- // Force cleanup of any pending frame operations
3148
- if (window.requestIdleCallback) window.requestIdleCallback(() => {});
3149
- });
3150
- } catch (cleanupErr) { /* ignore */ }
3197
+ // Add timeout to page validity check
3198
+ await Promise.race([
3199
+ page.evaluate(() => true),
3200
+ new Promise((_, reject) =>
3201
+ setTimeout(() => reject(new Error('Page validity check timeout')), 3000)
3202
+ )
3203
+ ]);
3204
+ pageStillValid = true;
3205
+ } catch (validityCheck) {
3206
+ console.warn(`Page invalid before reload #${i}, skipping remaining reloads`);
3207
+ break;
3208
+ }
3209
+
3210
+ // Use comprehensive cleanup from browserhealth module
3211
+ await cleanupPageBeforeReload(page, forceDebug);
3212
+
3213
+ // Add stabilization delay after cleanup
3214
+ await fastTimeout(1000);
3151
3215
 
3152
3216
  if (siteConfig.clear_sitedata === true) {
3153
3217
  try {
@@ -3159,8 +3223,11 @@ function setupFrameHandling(page, forceDebug) {
3159
3223
  }
3160
3224
 
3161
3225
  let reloadSuccess = false;
3226
+
3227
+ // Skip force reload if browser seems unhealthy
3228
+ const skipForceReload = i > 2; // After 2 attempts, skip force reload
3162
3229
 
3163
- if (useForceReload && !reloadSuccess) {
3230
+ if (useForceReload && !reloadSuccess && !skipForceReload) {
3164
3231
  // Attempt force reload: disable cache, reload, re-enable cache
3165
3232
  try {
3166
3233
  // Timeout-protected cache disable
@@ -3169,28 +3236,23 @@ function setupFrameHandling(page, forceDebug) {
3169
3236
  new Promise((_, reject) => setTimeout(() => reject(new Error('Cache disable timeout')), 8000))
3170
3237
  ]);
3171
3238
 
3172
- await page.reload({ waitUntil: 'domcontentloaded', timeout: Math.min(timeout, 12000) });
3239
+ // Use networkidle2 for force reload to better detect when page is actually loaded
3240
+ await page.reload({ waitUntil: 'networkidle2', timeout: Math.min(timeout, 15000) });
3173
3241
 
3174
3242
  // Timeout-protected cache enable
3175
3243
  await Promise.race([
3176
3244
  page.setCacheEnabled(true),
3177
3245
  new Promise((_, reject) => setTimeout(() => reject(new Error('Cache enable timeout')), 8000))
3178
3246
  ]);
3179
-
3180
- await page.reload({ waitUntil: 'domcontentloaded', timeout: Math.min(timeout, 12000) });
3181
-
3182
- await Promise.race([
3183
- page.setCacheEnabled(true),
3184
- new Promise((_, reject) =>
3185
- setTimeout(() => reject(new Error('setCacheEnabled(true) timeout')), 5000)
3186
- )
3187
- ]);
3188
-
3247
+
3189
3248
  reloadSuccess = true;
3190
3249
  if (forceDebug) console.log(formatLogMessage('debug', `Force reload #${i} completed for ${currentUrl}`));
3191
3250
 
3192
3251
  } catch (forceReloadErr) {
3193
- console.warn(messageColors.warn(`[force reload #${i} failed] ${currentUrl}: ${forceReloadErr.message} - falling back to standard reload`));
3252
+ // Don't warn for timeouts on problematic sites, just fall back silently
3253
+ if (forceDebug || !forceReloadErr.message.includes('timeout')) {
3254
+ console.warn(messageColors.warn(`[force reload #${i} failed] ${currentUrl}: ${forceReloadErr.message} - falling back to standard reload`));
3255
+ }
3194
3256
  reloadSuccess = false; // Ensure we try standard reload
3195
3257
  }
3196
3258
  }
@@ -3198,24 +3260,39 @@ function setupFrameHandling(page, forceDebug) {
3198
3260
  // Fallback to standard reload if force reload failed or wasn't attempted
3199
3261
  if (!reloadSuccess) {
3200
3262
  try {
3201
- // Reduced timeout for faster failure detection
3202
- const standardReloadTimeout = Math.min(timeout, 8000); // Reduced from 15000ms
3203
- await page.reload({ waitUntil: 'domcontentloaded', timeout: standardReloadTimeout });
3263
+ const canReload = await page.evaluate(() => {
3264
+ return !!(document && document.body);
3265
+ }).catch(() => false);
3266
+
3267
+ if (!canReload) {
3268
+ throw new Error('Page document invalid for reload');
3269
+ }
3270
+
3271
+ // Use networkidle2 with reasonable timeout
3272
+ // Use simpler reload for problematic pages
3273
+ const reloadOptions = i > 1
3274
+ ? { waitUntil: 'domcontentloaded', timeout: 10000 } // Simpler after failures
3275
+ : { waitUntil: 'networkidle2', timeout: 15000 }; // Full wait first time
3276
+
3277
+ await page.reload(reloadOptions);
3278
+
3204
3279
  if (forceDebug) console.log(formatLogMessage('debug', `Standard reload #${i} completed for ${currentUrl}`));
3205
3280
  } catch (standardReloadErr) {
3206
- console.warn(messageColors.warn(`[standard reload #${i} failed] ${currentUrl}: ${standardReloadErr.message}`));
3281
+ // Only warn for non-timeout errors
3282
+ if (!standardReloadErr.message.includes('timeout')) {
3283
+ console.warn(messageColors.warn(`[standard reload #${i} failed] ${currentUrl}: ${standardReloadErr.message}`));
3284
+ } else if (forceDebug) {
3285
+ console.log(formatLogMessage('debug', `Reload #${i} timed out for ${currentUrl}, continuing anyway`));
3286
+ }
3207
3287
 
3208
3288
  // Check if this is a persistent failure that should skip remaining reloads
3209
- const isPersistentFailure = standardReloadErr.message.includes('Navigation timeout') ||
3289
+ const isPersistentFailure = standardReloadErr.message.includes('detached Frame') ||
3290
+ standardReloadErr.message.includes('Attempted to use detached') ||
3291
+ standardReloadErr.message.includes('Navigating frame was detached') ||
3292
+ standardReloadErr.message.includes('document invalid') ||
3210
3293
  standardReloadErr.message.includes('net::ERR_') ||
3211
3294
  standardReloadErr.message.includes('Protocol error') ||
3212
- standardReloadErr.message.includes('Page crashed') ||
3213
- // CDP and injection failures
3214
- standardReloadErr.constructor.name === 'ProtocolError' ||
3215
- standardReloadErr.name === 'ProtocolError' ||
3216
- standardReloadErr.message.includes('addScriptToEvaluateOnNewDocument timed out') ||
3217
- standardReloadErr.message.includes('Runtime.callFunctionOn timed out') ||
3218
- standardReloadErr.message.includes('CDP injection timeout');
3295
+ standardReloadErr.message.includes('Page crashed');
3219
3296
 
3220
3297
  if (isPersistentFailure) {
3221
3298
  const remainingReloads = totalReloads - i;
@@ -3225,16 +3302,16 @@ function setupFrameHandling(page, forceDebug) {
3225
3302
  // Break out of reload loop to move to next URL faster
3226
3303
  break;
3227
3304
  }
3305
+ // For navigation timeouts, we can continue - the page might still be partially loaded
3306
+ // Don't break the loop for simple timeouts
3228
3307
  }
3229
- } else {
3230
- // Regular reload
3231
- await page.reload({ waitUntil: 'domcontentloaded', timeout: Math.min(timeout, 15000) });
3232
3308
  }
3233
3309
 
3234
3310
  // Only add delay if we're continuing with more reloads
3235
3311
  if (i < totalReloads) {
3236
-
3237
- await fastTimeout(delayMs);
3312
+ // Reduce delay for problematic sites
3313
+ const adjustedDelay = i > 1 ? Math.min(DEFAULT_DELAY, 2000) : DEFAULT_DELAY;
3314
+ await fastTimeout(adjustedDelay);
3238
3315
  }
3239
3316
  }
3240
3317
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanboynz/network-scanner",
3
- "version": "2.0.9",
3
+ "version": "2.0.11",
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": {