@fanboynz/network-scanner 2.0.22 → 2.0.24

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.
@@ -7,6 +7,81 @@
7
7
  const DEFAULT_PLATFORM = 'Win32';
8
8
  const DEFAULT_TIMEZONE = 'America/New_York';
9
9
 
10
+ // Cached property descriptors for V8 optimization
11
+ const CACHED_DESCRIPTORS = {
12
+ readOnlyValue: (value) => ({ value, writable: false, enumerable: true, configurable: true }),
13
+ getter: (fn) => ({ get: fn, enumerable: true, configurable: true }),
14
+ hiddenValue: (value) => ({ value, writable: false, enumerable: false, configurable: true })
15
+ };
16
+
17
+ // Type-specific property spoofing functions for monomorphic optimization
18
+ function spoofNavigatorProperties(navigator, properties, options = {}) {
19
+ if (!navigator || typeof navigator !== 'object') return false;
20
+
21
+ for (const [prop, descriptor] of Object.entries(properties)) {
22
+ if (!safeDefineProperty(navigator, prop, descriptor, options)) {
23
+ if (options.debug) console.log(`[fingerprint] Failed to spoof navigator.${prop}`);
24
+ }
25
+ }
26
+ return true;
27
+ }
28
+
29
+ function spoofScreenProperties(screen, properties, options = {}) {
30
+ if (!screen || typeof screen !== 'object') return false;
31
+
32
+ for (const [prop, descriptor] of Object.entries(properties)) {
33
+ if (!safeDefineProperty(screen, prop, descriptor, options)) {
34
+ if (options.debug) console.log(`[fingerprint] Failed to spoof screen.${prop}`);
35
+ }
36
+ }
37
+ return true;
38
+ }
39
+
40
+ function spoofWindowProperties(window, properties, options = {}) {
41
+ if (!window || typeof window !== 'object') return false;
42
+
43
+ for (const [prop, descriptor] of Object.entries(properties)) {
44
+ if (!safeDefineProperty(window, prop, descriptor, options)) {
45
+ if (options.debug) console.log(`[fingerprint] Failed to spoof window.${prop}`);
46
+ }
47
+ }
48
+ return true;
49
+ }
50
+
51
+ // Pre-compiled mock objects for V8 optimization
52
+ const PRECOMPILED_MOCKS = Object.freeze({
53
+ chromeRuntime: Object.freeze({
54
+ onConnect: Object.freeze({ addListener: () => {}, removeListener: () => {} }),
55
+ onMessage: Object.freeze({ addListener: () => {}, removeListener: () => {} }),
56
+ sendMessage: () => {},
57
+ connect: () => Object.freeze({
58
+ onMessage: Object.freeze({ addListener: () => {}, removeListener: () => {} }),
59
+ postMessage: () => {},
60
+ disconnect: () => {}
61
+ }),
62
+ getManifest: () => Object.freeze({ name: "Chrome", version: "140.0.0.0" }),
63
+ getURL: (path) => `chrome-extension://invalid/${path}`,
64
+ id: undefined
65
+ }),
66
+
67
+ fingerprintResult: Object.freeze({
68
+ visitorId: 'mock_visitor_' + Math.random().toString(36).substr(2, 9),
69
+ confidence: Object.freeze({ score: 0.99 }),
70
+ components: Object.freeze({
71
+ screen: Object.freeze({ value: Object.freeze({ width: 1920, height: 1080 }) }),
72
+ timezone: Object.freeze({ value: 'America/New_York' }),
73
+ language: Object.freeze({ value: 'en-US' })
74
+ })
75
+ }),
76
+
77
+ loadTimes: Object.freeze({
78
+ commitLoadTime: performance.now() - Math.random() * 1000,
79
+ connectionInfo: 'http/1.1',
80
+ finishDocumentLoadTime: performance.now() - Math.random() * 500,
81
+ navigationType: 'Navigation'
82
+ })
83
+ });
84
+
10
85
  // Built-in properties that should not be modified
11
86
  const BUILT_IN_PROPERTIES = new Set([
12
87
  'href', 'origin', 'protocol', 'host', 'hostname', 'port', 'pathname', 'search', 'hash',
@@ -55,10 +130,7 @@ function safeDefineProperty(target, property, descriptor, options = {}) {
55
130
  return false;
56
131
  }
57
132
 
58
- Object.defineProperty(target, property, {
59
- ...descriptor,
60
- configurable: true
61
- });
133
+ Object.defineProperty(target, property, descriptor);
62
134
  return true;
63
135
  } catch (err) {
64
136
  if (options.debug) console.log(`[fingerprint] Failed to define ${property}: ${err.message}`);
@@ -99,11 +171,61 @@ function getRealisticScreenResolution() {
99
171
  /**
100
172
  * Generates randomized but realistic browser fingerprint values
101
173
  */
102
- function getRandomFingerprint() {
103
- const resolution = getRealisticScreenResolution();
174
+ function generateRealisticFingerprint(userAgent) {
175
+ // Determine OS from user agent
176
+ let osType = 'windows';
177
+ if (userAgent.includes('Macintosh') || userAgent.includes('Mac OS X')) {
178
+ osType = 'mac';
179
+ } else if (userAgent.includes('X11; Linux') || userAgent.includes('Ubuntu')) {
180
+ osType = 'linux';
181
+ }
182
+
183
+ // Generate OS-appropriate hardware specs
184
+ const profiles = {
185
+ windows: {
186
+ deviceMemory: [8, 16], // Common Windows configurations
187
+ hardwareConcurrency: [4, 6, 8], // Typical consumer CPUs
188
+ platform: 'Win32',
189
+ timezone: 'America/New_York',
190
+ language: 'en-US',
191
+ resolutions: [
192
+ { width: 1920, height: 1080 },
193
+ { width: 2560, height: 1440 },
194
+ { width: 1366, height: 768 }
195
+ ]
196
+ },
197
+ mac: {
198
+ deviceMemory: [8, 16], // MacBook/iMac typical configs
199
+ hardwareConcurrency: [8, 10], // Apple Silicon M1/M2 cores
200
+ platform: 'MacIntel',
201
+ timezone: 'America/Los_Angeles',
202
+ language: 'en-US',
203
+ resolutions: [
204
+ { width: 2560, height: 1600 }, // MacBook Pro
205
+ { width: 3840, height: 2160 }, // iMac 4K
206
+ { width: 1440, height: 900 } // MacBook Air
207
+ ]
208
+ },
209
+ linux: {
210
+ deviceMemory: [8, 16],
211
+ hardwareConcurrency: [4, 8, 12], // Wide variety on Linux
212
+ platform: 'Linux x86_64',
213
+ timezone: 'America/New_York',
214
+ language: 'en-US',
215
+ resolutions: [
216
+ { width: 1920, height: 1080 },
217
+ { width: 2560, height: 1440 },
218
+ { width: 1600, height: 900 }
219
+ ]
220
+ }
221
+ };
222
+
223
+ const profile = profiles[osType];
224
+ const resolution = profile.resolutions[Math.floor(Math.random() * profile.resolutions.length)];
225
+
104
226
  return {
105
- deviceMemory: [4, 8, 16, 32][Math.floor(Math.random() * 4)],
106
- hardwareConcurrency: [2, 4, 6, 8, 12, 16][Math.floor(Math.random() * 6)],
227
+ deviceMemory: profile.deviceMemory[Math.floor(Math.random() * profile.deviceMemory.length)],
228
+ hardwareConcurrency: profile.hardwareConcurrency[Math.floor(Math.random() * profile.hardwareConcurrency.length)],
107
229
  screen: {
108
230
  width: resolution.width,
109
231
  height: resolution.height,
@@ -112,11 +234,11 @@ function getRandomFingerprint() {
112
234
  colorDepth: 24,
113
235
  pixelDepth: 24
114
236
  },
115
- platform: Math.random() > 0.3 ? 'Win32' : 'MacIntel',
116
- timezone: ['America/New_York', 'America/Los_Angeles', 'Europe/London', 'America/Chicago'][Math.floor(Math.random() * 4)],
117
- language: ['en-US', 'en-GB', 'en-CA'][Math.floor(Math.random() * 3)],
237
+ platform: profile.platform,
238
+ timezone: profile.timezone,
239
+ language: profile.language,
118
240
  cookieEnabled: true,
119
- doNotTrack: Math.random() > 0.7 ? '1' : null
241
+ doNotTrack: null // Most users don't enable DNT
120
242
  };
121
243
  }
122
244
 
@@ -124,19 +246,7 @@ function getRandomFingerprint() {
124
246
  * Creates mock Chrome runtime objects
125
247
  */
126
248
  function createMockChromeRuntime() {
127
- return {
128
- onConnect: { addListener: () => {}, removeListener: () => {} },
129
- onMessage: { addListener: () => {}, removeListener: () => {} },
130
- sendMessage: () => {},
131
- connect: () => ({
132
- onMessage: { addListener: () => {}, removeListener: () => {} },
133
- postMessage: () => {},
134
- disconnect: () => {}
135
- }),
136
- getManifest: () => ({ name: "Chrome", version: "131.0.0.0" }),
137
- getURL: (path) => `chrome-extension://invalid/${path}`,
138
- id: undefined
139
- };
249
+ return PRECOMPILED_MOCKS.chromeRuntime;
140
250
  }
141
251
 
142
252
  /**
@@ -144,21 +254,8 @@ function createMockChromeRuntime() {
144
254
  */
145
255
  function generateRealisticLoadTimes() {
146
256
  const now = performance.now();
147
- return {
148
- commitLoadTime: now - Math.random() * 1000,
149
- connectionInfo: 'http/1.1',
150
- finishDocumentLoadTime: now - Math.random() * 500,
151
- finishLoadTime: now - Math.random() * 100,
152
- firstPaintAfterLoadTime: now - Math.random() * 50,
153
- firstPaintTime: now - Math.random() * 200,
154
- navigationType: 'Navigation',
155
- npnNegotiatedProtocol: 'unknown',
156
- requestTime: now - Math.random() * 2000,
157
- startLoadTime: now - Math.random() * 1500,
158
- wasAlternateProtocolAvailable: false,
159
- wasFetchedViaSpdy: false,
160
- wasNpnNegotiated: false
161
- };
257
+ // Return a copy with updated timing values
258
+ return { ...PRECOMPILED_MOCKS.loadTimes, commitLoadTime: now - Math.random() * 1000 };
162
259
  }
163
260
 
164
261
  /**
@@ -194,22 +291,14 @@ async function validatePageForInjection(page, currentUrl, forceDebug) {
194
291
  * Creates mock fingerprinting objects
195
292
  */
196
293
  function createFingerprintMocks() {
197
- const mockResult = {
198
- visitorId: 'mock_visitor_' + Math.random().toString(36).substr(2, 9),
199
- confidence: { score: 0.99 },
200
- components: {
201
- screen: { value: { width: 1920, height: 1080 } },
202
- timezone: { value: DEFAULT_TIMEZONE },
203
- language: { value: 'en-US' }
204
- }
205
- };
294
+ const mockResult = PRECOMPILED_MOCKS.fingerprintResult;
206
295
 
207
296
  return {
208
297
  fp: {
209
298
  getResult: (callback) => callback ? setTimeout(() => callback(mockResult), 0) : mockResult,
210
299
  get: (callback) => Promise.resolve(mockResult),
211
300
  load: () => Promise.resolve(window.fp),
212
- components: { screen: { value: { width: 1920, height: 1080 } } },
301
+ components: mockResult.components,
213
302
  x64hash128: () => 'mock_hash',
214
303
  tz: DEFAULT_TIMEZONE,
215
304
  timezone: DEFAULT_TIMEZONE
@@ -351,7 +440,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
351
440
  // Create safe property definition helper
352
441
  function safeDefinePropertyLocal(target, property, descriptor) {
353
442
  const builtInProps = new Set(['href', 'origin', 'protocol', 'host', 'hostname', 'port', 'pathname', 'search', 'hash', 'constructor', 'prototype', '__proto__', 'toString', 'valueOf', 'assign', 'reload', 'replace']);
354
-
443
+
355
444
  if (builtInProps.has(property)) {
356
445
  if (debugEnabled) console.log(`[fingerprint] Skipping built-in property: ${property}`);
357
446
  return false;
@@ -374,6 +463,24 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
374
463
  return false;
375
464
  }
376
465
  }
466
+
467
+ // Add cached descriptors helper for page context
468
+ const CACHED_DESCRIPTORS = {
469
+ getter: (fn) => ({ get: fn, enumerable: true, configurable: true })
470
+ };
471
+
472
+ // Add monomorphic spoofing functions for page context
473
+ function spoofNavigatorProperties(navigator, properties) {
474
+ for (const [prop, descriptor] of Object.entries(properties)) {
475
+ safeDefinePropertyLocal(navigator, prop, descriptor);
476
+ }
477
+ }
478
+
479
+ function spoofScreenProperties(screen, properties) {
480
+ for (const [prop, descriptor] of Object.entries(properties)) {
481
+ safeDefinePropertyLocal(screen, prop, descriptor);
482
+ }
483
+ }
377
484
 
378
485
  // Safe execution wrapper
379
486
  function safeExecute(fn, description) {
@@ -428,7 +535,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
428
535
  onMessage: { addListener: () => {}, removeListener: () => {} },
429
536
  sendMessage: () => {},
430
537
  connect: () => ({ onMessage: { addListener: () => {}, removeListener: () => {} }, postMessage: () => {}, disconnect: () => {} }),
431
- getManifest: () => ({ name: "Chrome", version: "131.0.0.0" }),
538
+ getManifest: () => ({ name: "Chrome", version: "140.0.0.0" }),
432
539
  getURL: (path) => `chrome-extension://invalid/${path}`,
433
540
  id: undefined
434
541
  },
@@ -507,8 +614,11 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
507
614
  //
508
615
  safeExecute(() => {
509
616
  const languages = ['en-US', 'en'];
510
- safeDefinePropertyLocal(navigator, 'languages', { get: () => languages });
511
- safeDefinePropertyLocal(navigator, 'language', { get: () => languages[0] });
617
+ const languageProps = {
618
+ languages: { get: () => languages },
619
+ language: { get: () => languages[0] }
620
+ };
621
+ spoofNavigatorProperties(navigator, languageProps);
512
622
  }, 'language spoofing');
513
623
 
514
624
  // Spoof vendor information
@@ -523,8 +633,11 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
523
633
  vendor = 'Apple Computer, Inc.';
524
634
  }
525
635
 
526
- safeDefinePropertyLocal(navigator, 'vendor', { get: () => vendor });
527
- safeDefinePropertyLocal(navigator, 'product', { get: () => product });
636
+ const vendorProps = {
637
+ vendor: { get: () => vendor },
638
+ product: { get: () => product }
639
+ };
640
+ spoofNavigatorProperties(navigator, vendorProps);
528
641
  }, 'vendor/product spoofing');
529
642
 
530
643
  // Enhanced OS fingerprinting protection based on actual user agent content
@@ -574,7 +687,10 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
574
687
  // Hardware concurrency spoofing (universal coverage)
575
688
  //
576
689
  safeExecute(() => {
577
- safeDefinePropertyLocal(navigator, 'hardwareConcurrency', { get: () => [4, 6, 8, 12][Math.floor(Math.random() * 4)] });
690
+ const hardwareProps = {
691
+ hardwareConcurrency: { get: () => [4, 6, 8, 12][Math.floor(Math.random() * 4)] }
692
+ };
693
+ spoofNavigatorProperties(navigator, hardwareProps);
578
694
  }, 'hardware concurrency spoofing');
579
695
 
580
696
 
@@ -593,10 +709,13 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
593
709
  ];
594
710
  const resolution = commonResolutions[Math.floor(Math.random() * commonResolutions.length)];
595
711
 
596
- safeDefinePropertyLocal(window.screen, 'width', { get: () => resolution.width });
597
- safeDefinePropertyLocal(window.screen, 'height', { get: () => resolution.height });
598
- safeDefinePropertyLocal(window.screen, 'availWidth', { get: () => resolution.width });
599
- safeDefinePropertyLocal(window.screen, 'availHeight', { get: () => resolution.height - 40 });
712
+ const screenProps = {
713
+ width: { get: () => resolution.width },
714
+ height: { get: () => resolution.height },
715
+ availWidth: { get: () => resolution.width },
716
+ availHeight: { get: () => resolution.height - 40 }
717
+ };
718
+ spoofScreenProperties(window.screen, screenProps);
600
719
  }, 'screen resolution protection');
601
720
 
602
721
  // Spoof MIME types
@@ -1213,7 +1332,9 @@ async function applyFingerprintProtection(page, siteConfig, forceDebug, currentU
1213
1332
  // Validate page state before injection
1214
1333
  if (!(await validatePageForInjection(page, currentUrl, forceDebug))) return;
1215
1334
 
1216
- const spoof = fingerprintSetting === 'random' ? getRandomFingerprint() : {
1335
+ const currentUserAgent = await page.evaluate(() => navigator.userAgent);
1336
+
1337
+ const spoof = fingerprintSetting === 'random' ? generateRealisticFingerprint(currentUserAgent) : {
1217
1338
  deviceMemory: 8,
1218
1339
  hardwareConcurrency: 4,
1219
1340
  screen: { width: 1920, height: 1080, availWidth: 1920, availHeight: 1040, colorDepth: 24, pixelDepth: 24 },
@@ -1244,11 +1365,15 @@ async function applyFingerprintProtection(page, siteConfig, forceDebug, currentU
1244
1365
  }
1245
1366
 
1246
1367
  // Platform spoofing
1247
- safeDefinePropertyLocal(navigator, 'platform', { get: () => spoof.platform });
1368
+ const navigatorProps = {
1369
+ platform: { get: () => spoof.platform },
1370
+ deviceMemory: { get: () => spoof.deviceMemory },
1371
+ hardwareConcurrency: { get: () => spoof.hardwareConcurrency }
1372
+ };
1373
+ spoofNavigatorProperties(navigator, navigatorProps);
1248
1374
 
1249
- // Memory spoofing
1250
- safeDefinePropertyLocal(navigator, 'deviceMemory', { get: () => spoof.deviceMemory });
1251
- safeDefinePropertyLocal(navigator, 'hardwareConcurrency', { get: () => spoof.hardwareConcurrency });
1375
+ // Platform, memory, and hardware spoofing combined for better V8 optimization
1376
+ // (moved into navigatorProps above);
1252
1377
 
1253
1378
  // Connection type spoofing
1254
1379
  safeDefinePropertyLocal(navigator, 'connection', {
@@ -1262,16 +1387,21 @@ async function applyFingerprintProtection(page, siteConfig, forceDebug, currentU
1262
1387
  });
1263
1388
 
1264
1389
  // Screen properties spoofing
1390
+ const screenSpoofProps = {};
1265
1391
  ['width', 'height', 'availWidth', 'availHeight', 'colorDepth', 'pixelDepth'].forEach(prop => {
1266
1392
  if (spoof.screen[prop] !== undefined) {
1267
- safeDefinePropertyLocal(window.screen, prop, { get: () => spoof.screen[prop] });
1393
+ screenSpoofProps[prop] = { get: () => spoof.screen[prop] };
1268
1394
  }
1269
1395
  });
1396
+ spoofScreenProperties(window.screen, screenSpoofProps);
1270
1397
 
1271
1398
  // Language spoofing
1272
1399
  const languages = Array.isArray(spoof.language) ? spoof.language : [spoof.language, spoof.language.split('-')[0]];
1273
- safeDefinePropertyLocal(navigator, 'languages', { get: () => languages });
1274
- safeDefinePropertyLocal(navigator, 'language', { get: () => languages[0] });
1400
+ const languageSpoofProps = {
1401
+ languages: { get: () => languages },
1402
+ language: { get: () => languages[0] }
1403
+ };
1404
+ spoofNavigatorProperties(navigator, languageSpoofProps);
1275
1405
 
1276
1406
  // Timezone spoofing
1277
1407
  if (spoof.timezone && window.Intl?.DateTimeFormat) {
@@ -1480,7 +1610,7 @@ function safeExecuteSpoofing(spoofFunction, description, forceDebug = false) {
1480
1610
 
1481
1611
 
1482
1612
  module.exports = {
1483
- getRandomFingerprint,
1613
+ generateRealisticFingerprint,
1484
1614
  getRealisticScreenResolution,
1485
1615
  applyUserAgentSpoofing,
1486
1616
  applyBraveSpoofing,
package/lib/nettools.js CHANGED
@@ -357,13 +357,13 @@ async function whoisLookup(domain, timeout = 10000, whoisServer = null, debugMod
357
357
  * @param {number} whoisDelay - Delay in milliseconds before whois requests (default: 2000)
358
358
  * @returns {Promise<Object>} Object with success status and output/error
359
359
  */
360
- async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null, debugMode = false, retryOptions = {}, whoisDelay = 2000, logFunc = null) {
360
+ async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null, debugMode = false, retryOptions = {}, whoisDelay = 4000, logFunc = null) {
361
361
  const {
362
- maxRetries = 2,
362
+ maxRetries = 3,
363
363
  timeoutMultiplier = 1.5,
364
364
  useFallbackServers = true,
365
365
  retryOnTimeout = true,
366
- retryOnError = false
366
+ retryOnError = true
367
367
  } = retryOptions;
368
368
 
369
369
  let serversToTry = [];
@@ -709,7 +709,7 @@ function createNetToolsHandler(config) {
709
709
  const {
710
710
  whoisTerms,
711
711
  whoisOrTerms,
712
- whoisDelay = 2000,
712
+ whoisDelay = 4000,
713
713
  whoisServer,
714
714
  whoisServerMode = 'random',
715
715
  debugLogFile = null,
@@ -941,7 +941,7 @@ function createNetToolsHandler(config) {
941
941
 
942
942
  // Configure retry options based on site config or use defaults
943
943
  const retryOptions = {
944
- maxRetries: siteConfig.whois_max_retries || 2,
944
+ maxRetries: siteConfig.whois_max_retries || 3,
945
945
  timeoutMultiplier: siteConfig.whois_timeout_multiplier || 1.5,
946
946
  useFallbackServers: siteConfig.whois_use_fallback !== false, // Default true
947
947
  retryOnTimeout: siteConfig.whois_retry_on_timeout !== false, // Default true
package/nwss.1 CHANGED
@@ -383,7 +383,7 @@ Boolean. Retry on timeout errors (default: true).
383
383
 
384
384
  .TP
385
385
  .B whois_retry_on_error
386
- Boolean. Retry on connection/other errors (default: false).
386
+ Boolean. Retry on connection/other errors (default: true).
387
387
 
388
388
  .TP
389
389
  .B whois_delay
package/nwss.js CHANGED
@@ -1,4 +1,4 @@
1
- // === Network scanner script (nwss.js) v2.0.22 ===
1
+ // === Network scanner script (nwss.js) v2.0.24 ===
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
@@ -132,7 +132,7 @@ const { navigateWithRedirectHandling, handleRedirectTimeout } = require('./lib/r
132
132
  const { monitorBrowserHealth, isBrowserHealthy, isQuicklyResponsive, performGroupWindowCleanup, performRealtimeWindowCleanup, trackPageForRealtime, updatePageUsage, cleanupPageBeforeReload } = require('./lib/browserhealth');
133
133
 
134
134
  // --- Script Configuration & Constants ---
135
- const VERSION = '2.0.22'; // Script version
135
+ const VERSION = '2.0.24'; // Script version
136
136
 
137
137
  // get startTime
138
138
  const startTime = Date.now();
@@ -575,7 +575,7 @@ Advanced Options:
575
575
  whois_timeout_multiplier: 1.5 Timeout increase multiplier per retry (default: 1.5)
576
576
  whois_use_fallback: true Add TLD-specific fallback servers (default: true)
577
577
  whois_retry_on_timeout: true Retry on timeout errors (default: true)
578
- whois_retry_on_error: false Retry on connection/other errors (default: false)
578
+ whois_retry_on_error: true Retry on connection/other errors (default: true)
579
579
  whois_delay: <milliseconds> Delay between whois requests for this site (default: global whois_delay)
580
580
  dig: ["term1", "term2"] Check dig output for ALL specified terms (AND logic)
581
581
  dig-or: ["term1", "term2"] Check dig output for ANY specified term (OR logic)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanboynz/network-scanner",
3
- "version": "2.0.22",
3
+ "version": "2.0.24",
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": {