@fanboynz/network-scanner 2.0.10 → 2.0.12
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/fingerprint.js +81 -3
- package/nwss.js +18 -17
- package/package.json +1 -1
package/lib/fingerprint.js
CHANGED
|
@@ -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 || 'loading'),
|
|
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,15 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
251
268
|
|
|
252
269
|
if (forceDebug) console.log(`[debug] User agent spoofing: ${siteConfig.userAgent}`);
|
|
253
270
|
|
|
271
|
+
// Browser connection check
|
|
272
|
+
try {
|
|
273
|
+
if (!page.browser().isConnected() || page.isClosed()) return;
|
|
274
|
+
if (page.browser().process()?.killed) return;
|
|
275
|
+
} catch { return; }
|
|
276
|
+
|
|
277
|
+
// Validate page state before injection
|
|
278
|
+
if (!(await validatePageForInjection(page, currentUrl, forceDebug))) return;
|
|
279
|
+
|
|
254
280
|
const selectedUserAgents = USER_AGENT_COLLECTIONS[siteConfig.userAgent.toLowerCase()];
|
|
255
281
|
const ua = selectedUserAgents ? selectedUserAgents[Math.floor(Math.random() * selectedUserAgents.length)] : null;
|
|
256
282
|
|
|
@@ -660,6 +686,16 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
660
686
|
|
|
661
687
|
}, ua, forceDebug);
|
|
662
688
|
} catch (stealthErr) {
|
|
689
|
+
if (stealthErr.message.includes('Session closed') ||
|
|
690
|
+
stealthErr.message.includes('addScriptToEvaluateOnNewDocument timed out') ||
|
|
691
|
+
stealthErr.message.includes('Target closed') ||
|
|
692
|
+
stealthErr.message.includes('Protocol error') || stealthErr.name === 'ProtocolError' ||
|
|
693
|
+
stealthErr.message.includes('detached Frame') || stealthErr.message.includes('Navigating frame was detached') ||
|
|
694
|
+
stealthErr.message.includes('Cannot find context') ||
|
|
695
|
+
stealthErr.message.includes('Execution context was destroyed')) {
|
|
696
|
+
if (forceDebug) console.log(`[debug] Page closed during stealth injection: ${currentUrl}`);
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
663
699
|
console.warn(`[stealth protection failed] ${currentUrl}: ${stealthErr.message}`);
|
|
664
700
|
}
|
|
665
701
|
}
|
|
@@ -673,8 +709,18 @@ async function applyBraveSpoofing(page, siteConfig, forceDebug, currentUrl) {
|
|
|
673
709
|
|
|
674
710
|
if (forceDebug) console.log(`[debug] Brave spoofing enabled for ${currentUrl}`);
|
|
675
711
|
|
|
676
|
-
|
|
677
|
-
|
|
712
|
+
// Browser connection check
|
|
713
|
+
try {
|
|
714
|
+
if (!page.browser().isConnected() || page.isClosed()) return;
|
|
715
|
+
if (page.browser().process()?.killed) return;
|
|
716
|
+
} catch { return; }
|
|
717
|
+
|
|
718
|
+
// Validate page state before injection
|
|
719
|
+
if (!(await validatePageForInjection(page, currentUrl, forceDebug))) return;
|
|
720
|
+
|
|
721
|
+
try {
|
|
722
|
+
await page.evaluateOnNewDocument((debugEnabled) => {
|
|
723
|
+
try {
|
|
678
724
|
Object.defineProperty(navigator, 'brave', {
|
|
679
725
|
get: () => ({
|
|
680
726
|
isBrave: () => Promise.resolve(true),
|
|
@@ -695,7 +741,20 @@ async function applyBraveSpoofing(page, siteConfig, forceDebug, currentUrl) {
|
|
|
695
741
|
} catch (err) {
|
|
696
742
|
if (debugEnabled) console.log(`[fingerprint] Brave spoofing error: ${err.message}`);
|
|
697
743
|
}
|
|
698
|
-
|
|
744
|
+
}, forceDebug);
|
|
745
|
+
} catch (braveErr) {
|
|
746
|
+
if (braveErr.message.includes('Session closed') ||
|
|
747
|
+
braveErr.message.includes('addScriptToEvaluateOnNewDocument timed out') ||
|
|
748
|
+
braveErr.message.includes('Target closed') ||
|
|
749
|
+
braveErr.message.includes('Protocol error') || braveErr.name === 'ProtocolError' ||
|
|
750
|
+
braveErr.message.includes('detached Frame') || braveErr.message.includes('Navigating frame was detached') ||
|
|
751
|
+
braveErr.message.includes('Cannot find context') ||
|
|
752
|
+
braveErr.message.includes('Execution context was destroyed')) {
|
|
753
|
+
if (forceDebug) console.log(`[debug] Page closed during Brave injection: ${currentUrl}`);
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
if (forceDebug) console.log(`[debug] Brave spoofing failed: ${currentUrl} - ${braveErr.message}`);
|
|
757
|
+
}
|
|
699
758
|
}
|
|
700
759
|
|
|
701
760
|
/**
|
|
@@ -707,6 +766,15 @@ async function applyFingerprintProtection(page, siteConfig, forceDebug, currentU
|
|
|
707
766
|
|
|
708
767
|
if (forceDebug) console.log(`[debug] Fingerprint protection enabled for ${currentUrl}`);
|
|
709
768
|
|
|
769
|
+
// Browser connection check
|
|
770
|
+
try {
|
|
771
|
+
if (!page.browser().isConnected() || page.isClosed()) return;
|
|
772
|
+
if (page.browser().process()?.killed) return;
|
|
773
|
+
} catch { return; }
|
|
774
|
+
|
|
775
|
+
// Validate page state before injection
|
|
776
|
+
if (!(await validatePageForInjection(page, currentUrl, forceDebug))) return;
|
|
777
|
+
|
|
710
778
|
const spoof = fingerprintSetting === 'random' ? getRandomFingerprint() : {
|
|
711
779
|
deviceMemory: 8,
|
|
712
780
|
hardwareConcurrency: 4,
|
|
@@ -796,6 +864,16 @@ async function applyFingerprintProtection(page, siteConfig, forceDebug, currentU
|
|
|
796
864
|
|
|
797
865
|
}, { spoof, debugEnabled: forceDebug });
|
|
798
866
|
} catch (err) {
|
|
867
|
+
if (err.message.includes('Session closed') ||
|
|
868
|
+
err.message.includes('addScriptToEvaluateOnNewDocument timed out') ||
|
|
869
|
+
err.message.includes('Target closed') ||
|
|
870
|
+
err.message.includes('Protocol error') || err.name === 'ProtocolError' ||
|
|
871
|
+
err.message.includes('detached Frame') || err.message.includes('Navigating frame was detached') ||
|
|
872
|
+
err.message.includes('Cannot find context') ||
|
|
873
|
+
err.message.includes('Execution context was destroyed')) {
|
|
874
|
+
if (forceDebug) console.log(`[debug] Page closed during fingerprint injection: ${currentUrl}`);
|
|
875
|
+
return;
|
|
876
|
+
}
|
|
799
877
|
console.warn(`[fingerprint protection failed] ${currentUrl}: ${err.message}`);
|
|
800
878
|
}
|
|
801
879
|
}
|
package/nwss.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// === Network scanner script (nwss.js) v2.0.
|
|
1
|
+
// === Network scanner script (nwss.js) v2.0.12 ===
|
|
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:
|
|
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, //
|
|
62
|
-
FRAME_LOAD_WAIT: 2000,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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 = {
|
|
@@ -129,7 +130,7 @@ const { navigateWithRedirectHandling, handleRedirectTimeout } = require('./lib/r
|
|
|
129
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.
|
|
133
|
+
const VERSION = '2.0.12'; // Script version
|
|
133
134
|
|
|
134
135
|
// get startTime
|
|
135
136
|
const startTime = Date.now();
|
|
@@ -3140,7 +3141,7 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
3140
3141
|
await performPageInteraction(page, currentUrl, interactionConfig, forceDebug);
|
|
3141
3142
|
}
|
|
3142
3143
|
|
|
3143
|
-
const delayMs =
|
|
3144
|
+
const delayMs = DEFAULT_DELAY;
|
|
3144
3145
|
|
|
3145
3146
|
// Optimized delays for Puppeteer 23.x performance
|
|
3146
3147
|
const isFastSite = timeout <= TIMEOUTS.FAST_SITE_THRESHOLD;
|
|
@@ -3309,7 +3310,7 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
3309
3310
|
// Only add delay if we're continuing with more reloads
|
|
3310
3311
|
if (i < totalReloads) {
|
|
3311
3312
|
// Reduce delay for problematic sites
|
|
3312
|
-
const adjustedDelay = i > 1 ? Math.min(
|
|
3313
|
+
const adjustedDelay = i > 1 ? Math.min(DEFAULT_DELAY, 2000) : DEFAULT_DELAY;
|
|
3313
3314
|
await fastTimeout(adjustedDelay);
|
|
3314
3315
|
}
|
|
3315
3316
|
}
|
|
@@ -3992,4 +3993,4 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
3992
3993
|
if (forceDebug) console.log(formatLogMessage('debug', `About to exit process...`));
|
|
3993
3994
|
process.exit(0);
|
|
3994
3995
|
|
|
3995
|
-
})();
|
|
3996
|
+
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fanboynz/network-scanner",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.12",
|
|
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": {
|