@fanboynz/network-scanner 1.0.37 → 1.0.38

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/lib/cloudflare.js CHANGED
@@ -1,8 +1,25 @@
1
1
  /**
2
- * Cloudflare bypass and challenge handling module - Enhanced with timeout handling
2
+ * Cloudflare bypass and challenge handling module - Optimized with smart detection and adaptive timeouts
3
+ * Version: 2.1.0 - Enhanced with quick detection, adaptive timeouts, and comprehensive debug logging
3
4
  * Handles phishing warnings, Turnstile challenges, and modern Cloudflare protections
4
5
  */
5
6
 
7
+ /**
8
+ * Module version information
9
+ */
10
+ const CLOUDFLARE_MODULE_VERSION = '2.1.0';
11
+
12
+ /**
13
+ * Gets module version information
14
+ * @returns {object} Version information object
15
+ */
16
+ function getModuleInfo() {
17
+ return {
18
+ version: CLOUDFLARE_MODULE_VERSION,
19
+ name: 'Cloudflare Protection Handler'
20
+ };
21
+ }
22
+
6
23
  /**
7
24
  * Cross-version compatible timeout function for Puppeteer with timeout protection
8
25
  */
@@ -86,7 +103,61 @@ async function safeWaitForNavigation(page, timeout = 15000) {
86
103
  }
87
104
 
88
105
  /**
89
- * Analyzes the current page to detect Cloudflare challenges - Enhanced with timeout protection
106
+ * Quick Cloudflare detection - faster initial check to avoid unnecessary waiting
107
+ */
108
+ async function quickCloudflareDetection(page, forceDebug = false) {
109
+ try {
110
+ const quickCheck = await safePageEvaluate(page, () => {
111
+ const title = document.title || '';
112
+ const bodyText = document.body ? document.body.textContent.substring(0, 500) : '';
113
+ const url = window.location.href;
114
+
115
+ // Quick indicators of Cloudflare presence
116
+ const hasCloudflareIndicators =
117
+ title.includes('Just a moment') ||
118
+ title.includes('Checking your browser') ||
119
+ title.includes('Attention Required') ||
120
+ bodyText.includes('Cloudflare') ||
121
+ bodyText.includes('cf-ray') ||
122
+ bodyText.includes('Verify you are human') ||
123
+ bodyText.includes('This website has been reported for potential phishing') ||
124
+ bodyText.includes('Please wait while we verify') ||
125
+ url.includes('/cdn-cgi/challenge-platform/') ||
126
+ url.includes('cloudflare.com') ||
127
+ document.querySelector('[data-ray]') ||
128
+ document.querySelector('[data-cf-challenge]') ||
129
+ document.querySelector('.cf-challenge-running') ||
130
+ document.querySelector('.cf-challenge-container') ||
131
+ document.querySelector('.cf-turnstile') ||
132
+ document.querySelector('.ctp-checkbox-container') ||
133
+ document.querySelector('iframe[src*="challenges.cloudflare.com"]') ||
134
+ document.querySelector('iframe[title*="Cloudflare security challenge"]') ||
135
+ document.querySelector('script[src*="/cdn-cgi/challenge-platform/"]') ||
136
+ document.querySelector('a[href*="continue"]');
137
+
138
+ return {
139
+ hasIndicators: hasCloudflareIndicators,
140
+ title,
141
+ url,
142
+ bodySnippet: bodyText.substring(0, 200)
143
+ };
144
+ }, 3000); // Quick 3-second timeout
145
+
146
+ if (forceDebug && quickCheck.hasIndicators) {
147
+ console.log(`[debug][cloudflare] Quick detection found Cloudflare indicators on ${quickCheck.url}`);
148
+ } else if (forceDebug && !quickCheck.hasIndicators) {
149
+ console.log(`[debug][cloudflare] Quick detection found no Cloudflare indicators on ${quickCheck.url}`);
150
+ }
151
+
152
+ return quickCheck;
153
+ } catch (error) {
154
+ if (forceDebug) console.log(`[debug][cloudflare] Quick detection failed: ${error.message}`);
155
+ return { hasIndicators: false, error: error.message };
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Analyzes the current page to detect Cloudflare challenges - Enhanced with timeout protection and detailed debug logging
90
161
  */
91
162
  async function analyzeCloudflareChallenge(page) {
92
163
  try {
@@ -161,7 +232,7 @@ async function analyzeCloudflareChallenge(page) {
161
232
  url: window.location.href,
162
233
  bodySnippet: bodyText.substring(0, 200)
163
234
  };
164
- }, 10000); // 10 second timeout for page evaluation
235
+ }, 8000); // Reduced from 10 to 8 seconds
165
236
  } catch (error) {
166
237
  return {
167
238
  isChallengePresent: false,
@@ -175,7 +246,7 @@ async function analyzeCloudflareChallenge(page) {
175
246
  }
176
247
 
177
248
  /**
178
- * Handles Cloudflare phishing warnings with timeout protection
249
+ * Handles Cloudflare phishing warnings with timeout protection and enhanced debug logging
179
250
  */
180
251
  async function handlePhishingWarning(page, currentUrl, forceDebug = false) {
181
252
  const result = {
@@ -198,13 +269,16 @@ async function handlePhishingWarning(page, currentUrl, forceDebug = false) {
198
269
  result.details = challengeInfo;
199
270
 
200
271
  if (forceDebug) {
201
- console.log(`[debug][cloudflare] Phishing warning detected on ${currentUrl}`);
272
+ console.log(`[debug][cloudflare] Phishing warning detected on ${currentUrl}:`);
273
+ console.log(`[debug][cloudflare] Page Title: "${challengeInfo.title}"`);
274
+ console.log(`[debug][cloudflare] Current URL: ${challengeInfo.url}`);
275
+ console.log(`[debug][cloudflare] Body snippet: ${challengeInfo.bodySnippet}`);
202
276
  }
203
277
 
204
278
  try {
205
279
  // Use safe click with shorter timeout
206
280
  await safeClick(page, 'a[href*="continue"]', 3000);
207
- await safeWaitForNavigation(page, 10000);
281
+ await safeWaitForNavigation(page, 8000);
208
282
 
209
283
  result.success = true;
210
284
  if (forceDebug) console.log(`[debug][cloudflare] Successfully bypassed phishing warning for ${currentUrl}`);
@@ -225,7 +299,7 @@ async function handlePhishingWarning(page, currentUrl, forceDebug = false) {
225
299
  }
226
300
 
227
301
  /**
228
- * Attempts to solve Cloudflare challenges with timeout protection
302
+ * Attempts to solve Cloudflare challenges with timeout protection and enhanced debug logging
229
303
  */
230
304
  async function handleVerificationChallenge(page, currentUrl, forceDebug = false) {
231
305
  const result = {
@@ -233,14 +307,15 @@ async function handleVerificationChallenge(page, currentUrl, forceDebug = false)
233
307
  attempted: false,
234
308
  error: null,
235
309
  details: null,
236
- requiresHuman: false
310
+ requiresHuman: false,
311
+ method: null
237
312
  };
238
313
 
239
314
  try {
240
315
  if (forceDebug) console.log(`[debug][cloudflare] Checking for verification challenge on ${currentUrl}`);
241
316
 
242
- // Shorter wait for challenges
243
- await waitForTimeout(page, 2000);
317
+ // Reduced wait time
318
+ await waitForTimeout(page, 1000);
244
319
 
245
320
  const challengeInfo = await analyzeCloudflareChallenge(page);
246
321
  result.details = challengeInfo;
@@ -249,7 +324,20 @@ async function handleVerificationChallenge(page, currentUrl, forceDebug = false)
249
324
  result.attempted = true;
250
325
 
251
326
  if (forceDebug) {
252
- console.log(`[debug][cloudflare] Challenge detected on ${currentUrl}`);
327
+ console.log(`[debug][cloudflare] Challenge detected on ${currentUrl}:`);
328
+ console.log(`[debug][cloudflare] Page Title: "${challengeInfo.title}"`);
329
+ console.log(`[debug][cloudflare] Current URL: ${challengeInfo.url}`);
330
+ console.log(`[debug][cloudflare] Is Turnstile: ${challengeInfo.isTurnstile}`);
331
+ console.log(`[debug][cloudflare] Is JS Challenge: ${challengeInfo.isJSChallenge}`);
332
+ console.log(`[debug][cloudflare] Has Legacy Checkbox: ${challengeInfo.hasLegacyCheckbox}`);
333
+ console.log(`[debug][cloudflare] Has Turnstile Iframe: ${challengeInfo.hasTurnstileIframe}`);
334
+ console.log(`[debug][cloudflare] Has Turnstile Container: ${challengeInfo.hasTurnstileContainer}`);
335
+ console.log(`[debug][cloudflare] Has Turnstile Checkbox: ${challengeInfo.hasTurnstileCheckbox}`);
336
+ console.log(`[debug][cloudflare] Has CAPTCHA: ${challengeInfo.hasCaptcha}`);
337
+ console.log(`[debug][cloudflare] Has Challenge Running: ${challengeInfo.hasChallengeRunning}`);
338
+ console.log(`[debug][cloudflare] Has Data Ray: ${challengeInfo.hasDataRay}`);
339
+ console.log(`[debug][cloudflare] Has Turnstile Response: ${challengeInfo.hasTurnstileResponse}`);
340
+ console.log(`[debug][cloudflare] Body snippet: ${challengeInfo.bodySnippet}`);
253
341
  }
254
342
 
255
343
  // Check for CAPTCHA that requires human intervention
@@ -264,6 +352,7 @@ async function handleVerificationChallenge(page, currentUrl, forceDebug = false)
264
352
  const solveResult = await attemptChallengeSolveWithTimeout(page, currentUrl, challengeInfo, forceDebug);
265
353
  result.success = solveResult.success;
266
354
  result.error = solveResult.error;
355
+ result.method = solveResult.method;
267
356
 
268
357
  } else {
269
358
  if (forceDebug) console.log(`[debug][cloudflare] No verification challenge detected on ${currentUrl}`);
@@ -288,11 +377,11 @@ async function attemptChallengeSolveWithTimeout(page, currentUrl, challengeInfo,
288
377
  };
289
378
 
290
379
  try {
291
- // Overall timeout for all challenge solving attempts
380
+ // Reduced timeout for challenge solving
292
381
  return await Promise.race([
293
382
  attemptChallengeSolve(page, currentUrl, challengeInfo, forceDebug),
294
383
  new Promise((_, reject) =>
295
- setTimeout(() => reject(new Error('Challenge solving timeout')), 30000)
384
+ setTimeout(() => reject(new Error('Challenge solving timeout')), 20000)
296
385
  )
297
386
  ]);
298
387
  } catch (error) {
@@ -303,7 +392,7 @@ async function attemptChallengeSolveWithTimeout(page, currentUrl, challengeInfo,
303
392
  }
304
393
 
305
394
  /**
306
- * Attempts to solve a Cloudflare challenge with modern techniques
395
+ * Attempts to solve a Cloudflare challenge with modern techniques and enhanced debug logging
307
396
  */
308
397
  async function attemptChallengeSolve(page, currentUrl, challengeInfo, forceDebug = false) {
309
398
  const result = {
@@ -325,7 +414,7 @@ async function attemptChallengeSolve(page, currentUrl, challengeInfo, forceDebug
325
414
  return result;
326
415
  }
327
416
  } catch (jsError) {
328
- if (forceDebug) console.log(`[debug][cloudflare] JS challenge wait error: ${jsError.message}`);
417
+ if (forceDebug) console.log(`[debug][cloudflare] JS challenge wait failed for ${currentUrl}: ${jsError.message}`);
329
418
  }
330
419
  }
331
420
 
@@ -342,7 +431,7 @@ async function attemptChallengeSolve(page, currentUrl, challengeInfo, forceDebug
342
431
  return result;
343
432
  }
344
433
  } catch (turnstileError) {
345
- if (forceDebug) console.log(`[debug][cloudflare] Turnstile method error: ${turnstileError.message}`);
434
+ if (forceDebug) console.log(`[debug][cloudflare] Turnstile method failed for ${currentUrl}: ${turnstileError.message}`);
346
435
  }
347
436
  }
348
437
 
@@ -359,7 +448,7 @@ async function attemptChallengeSolve(page, currentUrl, challengeInfo, forceDebug
359
448
  return result;
360
449
  }
361
450
  } catch (legacyError) {
362
- if (forceDebug) console.log(`[debug][cloudflare] Legacy checkbox method error: ${legacyError.message}`);
451
+ if (forceDebug) console.log(`[debug][cloudflare] Legacy checkbox method failed for ${currentUrl}: ${legacyError.message}`);
363
452
  }
364
453
  }
365
454
 
@@ -371,7 +460,7 @@ async function attemptChallengeSolve(page, currentUrl, challengeInfo, forceDebug
371
460
  }
372
461
 
373
462
  /**
374
- * Waits for JS challenge completion with timeout protection
463
+ * Waits for JS challenge completion with timeout protection and enhanced debug logging
375
464
  */
376
465
  async function waitForJSChallengeCompletion(page, forceDebug = false) {
377
466
  const result = {
@@ -382,7 +471,7 @@ async function waitForJSChallengeCompletion(page, forceDebug = false) {
382
471
  try {
383
472
  if (forceDebug) console.log(`[debug][cloudflare] Waiting for JS challenge completion`);
384
473
 
385
- // Wait for challenge to complete automatically with shorter timeout
474
+ // Reduced timeout for JS challenge completion
386
475
  await Promise.race([
387
476
  page.waitForFunction(
388
477
  () => {
@@ -391,23 +480,25 @@ async function waitForJSChallengeCompletion(page, forceDebug = false) {
391
480
  !document.querySelector('.cf-challenge-running') &&
392
481
  !document.querySelector('[data-cf-challenge]');
393
482
  },
394
- { timeout: 20000 }
483
+ { timeout: 15000 }
395
484
  ),
396
485
  new Promise((_, reject) =>
397
- setTimeout(() => reject(new Error('JS challenge timeout')), 25000)
486
+ setTimeout(() => reject(new Error('JS challenge timeout')), 18000)
398
487
  )
399
488
  ]);
400
489
 
401
490
  result.success = true;
491
+ if (forceDebug) console.log(`[debug][cloudflare] JS challenge completed automatically`);
402
492
  } catch (error) {
403
493
  result.error = `JS challenge timeout: ${error.message}`;
494
+ if (forceDebug) console.log(`[debug][cloudflare] JS challenge wait failed: ${error.message}`);
404
495
  }
405
496
 
406
497
  return result;
407
498
  }
408
499
 
409
500
  /**
410
- * Handles modern Turnstile challenges with timeout protection
501
+ * Handles modern Turnstile challenges with timeout protection and enhanced debug logging
411
502
  */
412
503
  async function handleTurnstileChallenge(page, forceDebug = false) {
413
504
  const result = {
@@ -416,8 +507,8 @@ async function handleTurnstileChallenge(page, forceDebug = false) {
416
507
  };
417
508
 
418
509
  try {
419
- // Much shorter timeout for Turnstile operations
420
- const turnstileTimeout = 10000; // 10 seconds
510
+ // Reduced timeout for Turnstile operations
511
+ const turnstileTimeout = 8000; // Reduced from 10 to 8 seconds
421
512
 
422
513
  const turnstileSelectors = [
423
514
  'iframe[src*="challenges.cloudflare.com"]',
@@ -429,8 +520,8 @@ async function handleTurnstileChallenge(page, forceDebug = false) {
429
520
  for (const selector of turnstileSelectors) {
430
521
  try {
431
522
  await Promise.race([
432
- page.waitForSelector(selector, { timeout: 3000 }),
433
- new Promise((_, reject) => setTimeout(() => reject(new Error('Selector timeout')), 4000))
523
+ page.waitForSelector(selector, { timeout: 2000 }),
524
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Selector timeout')), 2500))
434
525
  ]);
435
526
 
436
527
  const frames = await page.frames();
@@ -438,14 +529,20 @@ async function handleTurnstileChallenge(page, forceDebug = false) {
438
529
  frame.url().includes('challenges.cloudflare.com') ||
439
530
  frame.url().includes('turnstile')
440
531
  );
441
- if (turnstileFrame) break;
532
+ if (turnstileFrame) {
533
+ if (forceDebug) console.log(`[debug][cloudflare] Found Turnstile iframe using selector: ${selector}`);
534
+ break;
535
+ }
442
536
  } catch (e) {
537
+ if (forceDebug) console.log(`[debug][cloudflare] Selector ${selector} not found or timed out`);
443
538
  continue;
444
539
  }
445
540
  }
446
541
 
447
542
  if (turnstileFrame) {
448
- if (forceDebug) console.log(`[debug][cloudflare] Found Turnstile iframe`);
543
+ if (forceDebug) {
544
+ console.log(`[debug][cloudflare] Found Turnstile iframe with URL: ${turnstileFrame.url()}`);
545
+ }
449
546
 
450
547
  const checkboxSelectors = [
451
548
  'input[type="checkbox"].ctp-checkbox',
@@ -457,8 +554,8 @@ async function handleTurnstileChallenge(page, forceDebug = false) {
457
554
  for (const selector of checkboxSelectors) {
458
555
  try {
459
556
  await Promise.race([
460
- turnstileFrame.waitForSelector(selector, { timeout: 3000 }),
461
- new Promise((_, reject) => setTimeout(() => reject(new Error('Checkbox timeout')), 4000))
557
+ turnstileFrame.waitForSelector(selector, { timeout: 2000 }),
558
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Checkbox timeout')), 2500))
462
559
  ]);
463
560
 
464
561
  await waitForTimeout(page, 500);
@@ -467,36 +564,75 @@ async function handleTurnstileChallenge(page, forceDebug = false) {
467
564
  if (forceDebug) console.log(`[debug][cloudflare] Clicked Turnstile checkbox: ${selector}`);
468
565
  break;
469
566
  } catch (e) {
567
+ if (forceDebug) console.log(`[debug][cloudflare] Checkbox selector ${selector} not found or failed to click`);
470
568
  continue;
471
569
  }
472
570
  }
473
571
 
474
- // Wait for Turnstile completion with timeout
572
+ // Wait for Turnstile completion with reduced timeout
475
573
  await Promise.race([
476
574
  page.waitForFunction(
477
575
  () => {
478
576
  const responseInput = document.querySelector('input[name="cf-turnstile-response"]');
479
577
  return responseInput && responseInput.value && responseInput.value.length > 0;
480
578
  },
481
- { timeout: 15000 }
579
+ { timeout: 12000 }
482
580
  ),
483
- new Promise((_, reject) => setTimeout(() => reject(new Error('Turnstile completion timeout')), 20000))
581
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Turnstile completion timeout')), 15000))
484
582
  ]);
485
583
 
584
+ if (forceDebug) console.log(`[debug][cloudflare] Turnstile response token generated successfully`);
486
585
  result.success = true;
487
586
  } else {
488
- result.error = 'Turnstile iframe not found';
587
+ // Try container-based Turnstile (non-iframe)
588
+ if (forceDebug) console.log(`[debug][cloudflare] No Turnstile iframe found, trying container-based approach`);
589
+
590
+ const containerSelectors = [
591
+ '.cf-turnstile',
592
+ '.ctp-checkbox-container',
593
+ '.ctp-checkbox-label'
594
+ ];
595
+
596
+ for (const selector of containerSelectors) {
597
+ try {
598
+ await Promise.race([
599
+ page.waitForSelector(selector, { timeout: 2000 }),
600
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Container timeout')), 2500))
601
+ ]);
602
+
603
+ await waitForTimeout(page, 500);
604
+ await page.click(selector);
605
+
606
+ if (forceDebug) console.log(`[debug][cloudflare] Clicked Turnstile container: ${selector}`);
607
+
608
+ const completionCheck = await checkChallengeCompletion(page);
609
+ if (completionCheck.isCompleted) {
610
+ result.success = true;
611
+ if (forceDebug) console.log(`[debug][cloudflare] Container-based Turnstile completed successfully`);
612
+ break;
613
+ }
614
+ } catch (e) {
615
+ if (forceDebug) console.log(`[debug][cloudflare] Container selector ${selector} not found or failed`);
616
+ continue;
617
+ }
618
+ }
619
+
620
+ if (!result.success) {
621
+ result.error = 'Turnstile iframe/container not found or not interactive';
622
+ if (forceDebug) console.log(`[debug][cloudflare] ${result.error}`);
623
+ }
489
624
  }
490
625
 
491
626
  } catch (error) {
492
627
  result.error = `Turnstile handling failed: ${error.message}`;
628
+ if (forceDebug) console.log(`[debug][cloudflare] Turnstile handling error: ${error.message}`);
493
629
  }
494
630
 
495
631
  return result;
496
632
  }
497
633
 
498
634
  /**
499
- * Handles legacy checkbox challenges with timeout protection
635
+ * Handles legacy checkbox challenges with timeout protection and enhanced debug logging
500
636
  */
501
637
  async function handleLegacyCheckbox(page, forceDebug = false) {
502
638
  const result = {
@@ -505,6 +641,8 @@ async function handleLegacyCheckbox(page, forceDebug = false) {
505
641
  };
506
642
 
507
643
  try {
644
+ if (forceDebug) console.log(`[debug][cloudflare] Attempting legacy checkbox challenge`);
645
+
508
646
  const legacySelectors = [
509
647
  'input[type="checkbox"]#challenge-form',
510
648
  'input[type="checkbox"][name="cf_captcha_kind"]',
@@ -514,8 +652,8 @@ async function handleLegacyCheckbox(page, forceDebug = false) {
514
652
  for (const selector of legacySelectors) {
515
653
  try {
516
654
  await Promise.race([
517
- page.waitForSelector(selector, { timeout: 3000 }),
518
- new Promise((_, reject) => setTimeout(() => reject(new Error('Legacy selector timeout')), 4000))
655
+ page.waitForSelector(selector, { timeout: 2000 }),
656
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Legacy selector timeout')), 2500))
519
657
  ]);
520
658
 
521
659
  const checkbox = await page.$(selector);
@@ -526,27 +664,31 @@ async function handleLegacyCheckbox(page, forceDebug = false) {
526
664
  const completionCheck = await checkChallengeCompletion(page);
527
665
  if (completionCheck.isCompleted) {
528
666
  result.success = true;
667
+ if (forceDebug) console.log(`[debug][cloudflare] Legacy checkbox challenge completed successfully`);
529
668
  break;
530
669
  }
531
670
  }
532
671
  } catch (e) {
672
+ if (forceDebug) console.log(`[debug][cloudflare] Legacy selector ${selector} failed: ${e.message}`);
533
673
  continue;
534
674
  }
535
675
  }
536
676
 
537
677
  if (!result.success) {
538
678
  result.error = 'No interactive legacy checkbox found';
679
+ if (forceDebug) console.log(`[debug][cloudflare] ${result.error}`);
539
680
  }
540
681
 
541
682
  } catch (error) {
542
683
  result.error = `Legacy checkbox handling failed: ${error.message}`;
684
+ if (forceDebug) console.log(`[debug][cloudflare] Legacy checkbox error: ${error.message}`);
543
685
  }
544
686
 
545
687
  return result;
546
688
  }
547
689
 
548
690
  /**
549
- * Checks if challenge has been completed with timeout protection
691
+ * Checks if challenge has been completed with timeout protection and enhanced debug logging
550
692
  */
551
693
  async function checkChallengeCompletion(page) {
552
694
  try {
@@ -563,7 +705,7 @@ async function checkChallengeCompletion(page) {
563
705
  return (noChallengeRunning && noChallengeContainer && noChallengePage) ||
564
706
  hasClearanceCookie ||
565
707
  hasTurnstileResponse;
566
- }, 5000);
708
+ }, 3000); // Reduced timeout
567
709
 
568
710
  return { isCompleted };
569
711
  } catch (error) {
@@ -572,9 +714,28 @@ async function checkChallengeCompletion(page) {
572
714
  }
573
715
 
574
716
  /**
575
- * Main function to handle all Cloudflare challenges with comprehensive timeout protection
717
+ * Main function to handle all Cloudflare challenges with smart detection and adaptive timeouts
576
718
  */
577
719
  async function handleCloudflareProtection(page, currentUrl, siteConfig, forceDebug = false) {
720
+ if (forceDebug) {
721
+ console.log(`[debug][cloudflare] Using Cloudflare module v${CLOUDFLARE_MODULE_VERSION} for ${currentUrl}`);
722
+ }
723
+ // Quick detection first - exit early if no Cloudflare detected and no explicit config
724
+ const quickDetection = await quickCloudflareDetection(page, forceDebug);
725
+
726
+ // Only proceed if we have indicators OR explicit config enables Cloudflare handling
727
+ if (!quickDetection.hasIndicators && !siteConfig.cloudflare_phish && !siteConfig.cloudflare_bypass) {
728
+ if (forceDebug) console.log(`[debug][cloudflare] No Cloudflare indicators found and no explicit config, skipping protection handling for ${currentUrl}`);
729
+ if (forceDebug) console.log(`[debug][cloudflare] Quick detection details: title="${quickDetection.title}", bodySnippet="${quickDetection.bodySnippet}"`);
730
+ return {
731
+ phishingWarning: { attempted: false, success: true },
732
+ verificationChallenge: { attempted: false, success: true },
733
+ overallSuccess: true,
734
+ errors: [],
735
+ skippedNoIndicators: true
736
+ };
737
+ }
738
+
578
739
  const result = {
579
740
  phishingWarning: { attempted: false, success: false },
580
741
  verificationChallenge: { attempted: false, success: false },
@@ -583,30 +744,45 @@ async function handleCloudflareProtection(page, currentUrl, siteConfig, forceDeb
583
744
  };
584
745
 
585
746
  try {
586
- // Overall timeout for all Cloudflare operations
747
+ // Adaptive timeout based on detection results and explicit config
748
+ let adaptiveTimeout;
749
+ if (siteConfig.cloudflare_phish || siteConfig.cloudflare_bypass) {
750
+ // Explicit config - give more time
751
+ adaptiveTimeout = quickDetection.hasIndicators ? 25000 : 20000;
752
+ } else {
753
+ // Auto-detected only - shorter timeout
754
+ adaptiveTimeout = quickDetection.hasIndicators ? 15000 : 10000;
755
+ }
756
+
757
+ if (forceDebug) {
758
+ console.log(`[debug][cloudflare] Using adaptive timeout of ${adaptiveTimeout}ms for ${currentUrl} (indicators: ${quickDetection.hasIndicators}, explicit config: ${!!(siteConfig.cloudflare_phish || siteConfig.cloudflare_bypass)})`);
759
+ }
760
+
587
761
  return await Promise.race([
588
762
  performCloudflareHandling(page, currentUrl, siteConfig, forceDebug),
589
763
  new Promise((resolve) => {
590
764
  setTimeout(() => {
591
- console.warn(`[cloudflare] Overall timeout for ${currentUrl} - continuing with scan`);
765
+ console.warn(`[cloudflare] Adaptive timeout (${adaptiveTimeout}ms) for ${currentUrl} - continuing with scan`);
592
766
  resolve({
593
767
  phishingWarning: { attempted: false, success: true },
594
768
  verificationChallenge: { attempted: false, success: true },
595
769
  overallSuccess: true,
596
- errors: ['Cloudflare handling timed out']
770
+ errors: ['Cloudflare handling timed out'],
771
+ timedOut: true
597
772
  });
598
- }, 45000); // 45 second overall timeout
773
+ }, adaptiveTimeout);
599
774
  })
600
775
  ]);
601
776
  } catch (error) {
602
777
  result.overallSuccess = false;
603
778
  result.errors.push(`Cloudflare handling failed: ${error.message}`);
779
+ if (forceDebug) console.log(`[debug][cloudflare] Overall handling failed: ${error.message}`);
604
780
  return result;
605
781
  }
606
782
  }
607
783
 
608
784
  /**
609
- * Performs the actual Cloudflare handling
785
+ * Performs the actual Cloudflare handling with enhanced debug logging
610
786
  */
611
787
  async function performCloudflareHandling(page, currentUrl, siteConfig, forceDebug = false) {
612
788
  const result = {
@@ -616,19 +792,30 @@ async function performCloudflareHandling(page, currentUrl, siteConfig, forceDebu
616
792
  errors: []
617
793
  };
618
794
 
795
+ if (forceDebug) console.log(`[debug][cloudflare] Starting Cloudflare protection handling for ${currentUrl}`);
796
+
619
797
  // Handle phishing warnings if enabled
620
798
  if (siteConfig.cloudflare_phish === true) {
799
+ if (forceDebug) console.log(`[debug][cloudflare] Phishing warning bypass enabled for ${currentUrl}`);
800
+
621
801
  const phishingResult = await handlePhishingWarning(page, currentUrl, forceDebug);
622
802
  result.phishingWarning = phishingResult;
623
803
 
624
804
  if (phishingResult.attempted && !phishingResult.success) {
625
805
  result.overallSuccess = false;
626
806
  result.errors.push(`Phishing warning bypass failed: ${phishingResult.error}`);
807
+ if (forceDebug) console.log(`[debug][cloudflare] Phishing warning handling failed: ${phishingResult.error}`);
808
+ } else if (phishingResult.attempted && phishingResult.success) {
809
+ if (forceDebug) console.log(`[debug][cloudflare] Phishing warning handled successfully`);
627
810
  }
811
+ } else if (forceDebug) {
812
+ console.log(`[debug][cloudflare] Phishing warning bypass disabled for ${currentUrl}`);
628
813
  }
629
814
 
630
815
  // Handle verification challenges if enabled
631
816
  if (siteConfig.cloudflare_bypass === true) {
817
+ if (forceDebug) console.log(`[debug][cloudflare] Challenge bypass enabled for ${currentUrl}`);
818
+
632
819
  const challengeResult = await handleVerificationChallenge(page, currentUrl, forceDebug);
633
820
  result.verificationChallenge = challengeResult;
634
821
 
@@ -636,12 +823,19 @@ async function performCloudflareHandling(page, currentUrl, siteConfig, forceDebu
636
823
  result.overallSuccess = false;
637
824
  if (challengeResult.requiresHuman) {
638
825
  result.errors.push(`Human intervention required: ${challengeResult.error}`);
826
+ if (forceDebug) console.log(`[debug][cloudflare] Human intervention required: ${challengeResult.error}`);
639
827
  } else {
640
828
  result.errors.push(`Challenge bypass failed: ${challengeResult.error}`);
829
+ if (forceDebug) console.log(`[debug][cloudflare] Challenge bypass failed: ${challengeResult.error}`);
641
830
  }
831
+ } else if (challengeResult.attempted && challengeResult.success) {
832
+ if (forceDebug) console.log(`[debug][cloudflare] Challenge handled successfully using method: ${challengeResult.method || 'unknown'}`);
642
833
  }
834
+ } else if (forceDebug) {
835
+ console.log(`[debug][cloudflare] Challenge bypass disabled for ${currentUrl}`);
643
836
  }
644
837
 
838
+ // Log overall result
645
839
  if (!result.overallSuccess && forceDebug) {
646
840
  console.log(`[debug][cloudflare] Overall Cloudflare handling failed for ${currentUrl}:`);
647
841
  result.errors.forEach(error => {
@@ -649,6 +843,8 @@ async function performCloudflareHandling(page, currentUrl, siteConfig, forceDebu
649
843
  });
650
844
  } else if ((result.phishingWarning.attempted || result.verificationChallenge.attempted) && forceDebug) {
651
845
  console.log(`[debug][cloudflare] Successfully handled Cloudflare protections for ${currentUrl}`);
846
+ } else if (forceDebug) {
847
+ console.log(`[debug][cloudflare] No Cloudflare protections detected or enabled for ${currentUrl}`);
652
848
  }
653
849
 
654
850
  return result;
@@ -663,5 +859,8 @@ module.exports = {
663
859
  handleTurnstileChallenge,
664
860
  waitForJSChallengeCompletion,
665
861
  handleLegacyCheckbox,
666
- checkChallengeCompletion
862
+ checkChallengeCompletion,
863
+ quickCloudflareDetection,
864
+ getModuleInfo,
865
+ CLOUDFLARE_MODULE_VERSION
667
866
  };
package/nwss.js CHANGED
@@ -1,4 +1,4 @@
1
- // === Network scanner script (nwss.js) v1.0.37 ===
1
+ // === Network scanner script (nwss.js) v1.0.38 ===
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
@@ -33,9 +33,9 @@ const { navigateWithRedirectHandling, handleRedirectTimeout } = require('./lib/r
33
33
  const { monitorBrowserHealth, isBrowserHealthy } = require('./lib/browserhealth');
34
34
 
35
35
  // --- Script Configuration & Constants ---
36
- const VERSION = '1.0.37'; // Script version
37
- const MAX_CONCURRENT_SITES = 5;
38
- const RESOURCE_CLEANUP_INTERVAL = 80; // Close browser and restart every N sites to free resources
36
+ const VERSION = '1.0.38'; // Script version
37
+ const MAX_CONCURRENT_SITES = 12;
38
+ const RESOURCE_CLEANUP_INTERVAL = 180; // Close browser and restart every N sites to free resources
39
39
 
40
40
  // get startTime
41
41
  const startTime = Date.now();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanboynz/network-scanner",
3
- "version": "1.0.37",
3
+ "version": "1.0.38",
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": {