arn-browser 0.0.11 → 0.0.13
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/package.json +2 -2
- package/src/utility/launchBrowser.d.ts +12 -0
- package/src/utility/launchBrowser.js +130 -26
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arn-browser",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "A lightweight, browser autmation helper.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@aws-sdk/client-ec2": "^3.946.0",
|
|
15
15
|
"@ghostery/adblocker": "^2.13.0",
|
|
16
|
-
"arn-knexjs": "^0.0.
|
|
16
|
+
"arn-knexjs": "^0.0.3",
|
|
17
17
|
"camoufox-js": "^0.8.4",
|
|
18
18
|
"dotenv": "^17.2.3",
|
|
19
19
|
"fingerprint-generator": "^2.1.78",
|
|
@@ -181,6 +181,18 @@ export interface LaunchOptions {
|
|
|
181
181
|
*/
|
|
182
182
|
maxWidth?: number;
|
|
183
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Whether to spoof browser fingerprint with FingerprintInjector.
|
|
186
|
+
* When true: Applies userAgent, viewport, locale from fingerprintData and uses FingerprintInjector.
|
|
187
|
+
* When false: Uses null viewport and applies stealth script only.
|
|
188
|
+
*
|
|
189
|
+
* **For persistent Brave profiles:** The value is locked on first launch.
|
|
190
|
+
* Subsequent launches will use the saved value, ignoring the current parameter.
|
|
191
|
+
*
|
|
192
|
+
* Default: false
|
|
193
|
+
*/
|
|
194
|
+
spoof_fingerprint?: boolean;
|
|
195
|
+
|
|
184
196
|
// ========================================================================
|
|
185
197
|
// 5. ENGINE SPECIFIC GROUPS
|
|
186
198
|
// ========================================================================
|
|
@@ -180,11 +180,15 @@ export async function launchBrowser({
|
|
|
180
180
|
|
|
181
181
|
which_browser = "chromium",
|
|
182
182
|
CapSolver = false,
|
|
183
|
+
humanize_options = {}, // { humanize, maxTime, minTime, showCursor } - defaults to enabled for non-camoufox
|
|
184
|
+
|
|
185
|
+
// Spoof Fingerprint
|
|
186
|
+
spoof_fingerprint = false,
|
|
183
187
|
|
|
184
188
|
// Browser Specific Grouped Options
|
|
185
189
|
camoufox_options = {}, // { geoip, humanize, ... }
|
|
186
190
|
multilogin_options = {}, // { profileId, os_type, canvas_noise, ... }
|
|
187
|
-
|
|
191
|
+
|
|
188
192
|
}) {
|
|
189
193
|
try {
|
|
190
194
|
if (custom_profile_path) throw new Error("Please use profile_path");
|
|
@@ -212,6 +216,7 @@ export async function launchBrowser({
|
|
|
212
216
|
CapSolver,
|
|
213
217
|
maxWidth,
|
|
214
218
|
humanize_options: effectiveHumanizeOptions,
|
|
219
|
+
spoof_fingerprint,
|
|
215
220
|
});
|
|
216
221
|
break;
|
|
217
222
|
case "firefox":
|
|
@@ -221,6 +226,7 @@ export async function launchBrowser({
|
|
|
221
226
|
timezoneId,
|
|
222
227
|
maxWidth,
|
|
223
228
|
humanize_options: effectiveHumanizeOptions,
|
|
229
|
+
spoof_fingerprint,
|
|
224
230
|
});
|
|
225
231
|
break;
|
|
226
232
|
case "brave":
|
|
@@ -232,6 +238,7 @@ export async function launchBrowser({
|
|
|
232
238
|
CapSolver,
|
|
233
239
|
maxWidth,
|
|
234
240
|
humanize_options: effectiveHumanizeOptions,
|
|
241
|
+
spoof_fingerprint,
|
|
235
242
|
});
|
|
236
243
|
break;
|
|
237
244
|
case "camoufox":
|
|
@@ -242,6 +249,7 @@ export async function launchBrowser({
|
|
|
242
249
|
timezoneId,
|
|
243
250
|
maxWidth,
|
|
244
251
|
camoufox_options,
|
|
252
|
+
// Spoof Fingerprint not needed for Camoufox
|
|
245
253
|
});
|
|
246
254
|
break;
|
|
247
255
|
case "multilogin":
|
|
@@ -249,6 +257,7 @@ export async function launchBrowser({
|
|
|
249
257
|
proxy,
|
|
250
258
|
multilogin_options,
|
|
251
259
|
humanize_options: effectiveHumanizeOptions,
|
|
260
|
+
// Spoof Fingerprint not needed for Multilogin
|
|
252
261
|
});
|
|
253
262
|
break;
|
|
254
263
|
default:
|
|
@@ -265,7 +274,9 @@ export async function launchBrowser({
|
|
|
265
274
|
// ==========================================================================
|
|
266
275
|
// 4. ENGINE: CHROMIUM
|
|
267
276
|
// ==========================================================================
|
|
268
|
-
async function chromiumLauncher({ profilePath, proxy, timezoneId, CapSolver, maxWidth, humanize_options
|
|
277
|
+
async function chromiumLauncher({ profilePath, proxy, timezoneId, CapSolver, maxWidth, humanize_options
|
|
278
|
+
, spoof_fingerprint
|
|
279
|
+
}) {
|
|
269
280
|
const isPersistent = !!profilePath;
|
|
270
281
|
|
|
271
282
|
// 1. Determine Path (Temp needs it for fingerprint storage, Persistent needs it for data)
|
|
@@ -278,6 +289,11 @@ async function chromiumLauncher({ profilePath, proxy, timezoneId, CapSolver, max
|
|
|
278
289
|
// --- Stealth & Anti-Detection ---
|
|
279
290
|
"--disable-blink-features=AutomationControlled",
|
|
280
291
|
// "--disable-features=UserAgentClientHint",
|
|
292
|
+
|
|
293
|
+
// --- Window Size ---
|
|
294
|
+
"--start-maximized",
|
|
295
|
+
|
|
296
|
+
|
|
281
297
|
// --- PREVENT EXTRA TABS ---
|
|
282
298
|
// "--homepage=about:blank",
|
|
283
299
|
"--disable-restore-session-state",
|
|
@@ -324,11 +340,20 @@ async function chromiumLauncher({ profilePath, proxy, timezoneId, CapSolver, max
|
|
|
324
340
|
ignoreDefaultArgs: ignoreDefaultArgs,
|
|
325
341
|
});
|
|
326
342
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
fingerprint
|
|
330
|
-
|
|
331
|
-
|
|
343
|
+
let context;
|
|
344
|
+
if (spoof_fingerprint) {
|
|
345
|
+
// Inject the fingerprint
|
|
346
|
+
context = await newInjectedContext(browser, {
|
|
347
|
+
fingerprint: fingerprintData,
|
|
348
|
+
timezoneId: tz,
|
|
349
|
+
});
|
|
350
|
+
} else {
|
|
351
|
+
context = await browser.newContext({
|
|
352
|
+
timezoneId: tz,
|
|
353
|
+
});
|
|
354
|
+
// Manual Stealth Script
|
|
355
|
+
await addStealthScript(context);
|
|
356
|
+
}
|
|
332
357
|
|
|
333
358
|
const page = context.pages()[0] || (await context.newPage());
|
|
334
359
|
|
|
@@ -343,6 +368,7 @@ async function chromiumLauncher({ profilePath, proxy, timezoneId, CapSolver, max
|
|
|
343
368
|
// BRANCH B: PERSISTENT PROFILE (launchPersistentContext + Manual Script)
|
|
344
369
|
// ==================================================================
|
|
345
370
|
else {
|
|
371
|
+
// spoof_fingerprint not needed for isPersistent in chromium
|
|
346
372
|
try {
|
|
347
373
|
if (!fs.existsSync(activePath)) fs.mkdirSync(activePath, { recursive: true });
|
|
348
374
|
|
|
@@ -372,7 +398,7 @@ async function chromiumLauncher({ profilePath, proxy, timezoneId, CapSolver, max
|
|
|
372
398
|
// ==========================================================================
|
|
373
399
|
// 5. ENGINE: FIREFOX
|
|
374
400
|
// ==========================================================================
|
|
375
|
-
async function firefoxLauncher({ profilePath, proxy, timezoneId, maxWidth, humanize_options }) {
|
|
401
|
+
async function firefoxLauncher({ profilePath, proxy, timezoneId, maxWidth, humanize_options, spoof_fingerprint }) {
|
|
376
402
|
const isPersistent = !!profilePath;
|
|
377
403
|
|
|
378
404
|
// 1. Determine Path
|
|
@@ -404,10 +430,21 @@ async function firefoxLauncher({ profilePath, proxy, timezoneId, maxWidth, human
|
|
|
404
430
|
firefoxUserPrefs: firefoxUserPrefs,
|
|
405
431
|
});
|
|
406
432
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
433
|
+
let context;
|
|
434
|
+
if (spoof_fingerprint) {
|
|
435
|
+
context = await newInjectedContext(browser, {
|
|
436
|
+
fingerprint: fingerprintData,
|
|
437
|
+
timezoneId: tz,
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
// Spoof Fingerprint not needed for Firefox
|
|
441
|
+
else {
|
|
442
|
+
context = await browser.newContext({
|
|
443
|
+
timezoneId: tz,
|
|
444
|
+
});
|
|
445
|
+
// Manual Stealth Script
|
|
446
|
+
await addStealthScript(context);
|
|
447
|
+
}
|
|
411
448
|
|
|
412
449
|
const page = context.pages()[0] || (await context.newPage());
|
|
413
450
|
|
|
@@ -422,6 +459,7 @@ async function firefoxLauncher({ profilePath, proxy, timezoneId, maxWidth, human
|
|
|
422
459
|
// BRANCH B: PERSISTENT PROFILE (launchPersistentContext + Manual Script)
|
|
423
460
|
// ==================================================================
|
|
424
461
|
else {
|
|
462
|
+
// spoof_fingerprint not needed for isPersistent in firefox
|
|
425
463
|
try {
|
|
426
464
|
if (!fs.existsSync(activePath)) fs.mkdirSync(activePath, { recursive: true });
|
|
427
465
|
|
|
@@ -450,13 +488,34 @@ async function firefoxLauncher({ profilePath, proxy, timezoneId, maxWidth, human
|
|
|
450
488
|
// ==========================================================================
|
|
451
489
|
// 6. ENGINE: BRAVE
|
|
452
490
|
// ==========================================================================
|
|
453
|
-
async function braveLauncher({ profilePath, proxy, CapSolver, timezoneId, maxWidth, humanize_options }) {
|
|
491
|
+
async function braveLauncher({ profilePath, proxy, CapSolver, timezoneId, maxWidth, humanize_options, spoof_fingerprint }) {
|
|
454
492
|
const isPersistent = !!profilePath;
|
|
455
493
|
const activePath = isPersistent ? profilePath : path.join(TEMP_DIR, crypto.randomUUID());
|
|
456
494
|
|
|
457
495
|
console.log(`🚀 Starting Brave: ${activePath}`);
|
|
458
496
|
fs.mkdirSync(activePath, { recursive: true });
|
|
459
497
|
|
|
498
|
+
// ======================================================
|
|
499
|
+
// Persist spoof_fingerprint setting for persistent profiles
|
|
500
|
+
// On first launch: save the setting. On subsequent launches: use saved value.
|
|
501
|
+
// ======================================================
|
|
502
|
+
let effectiveSpoofFingerprint = spoof_fingerprint;
|
|
503
|
+
const settingsFilePath = path.join(activePath, "settings.json");
|
|
504
|
+
|
|
505
|
+
if (isPersistent) {
|
|
506
|
+
if (fs.existsSync(settingsFilePath)) {
|
|
507
|
+
// Load saved settings from first launch
|
|
508
|
+
const savedSettings = JSON.parse(fs.readFileSync(settingsFilePath, "utf-8"));
|
|
509
|
+
effectiveSpoofFingerprint = savedSettings.spoof_fingerprint;
|
|
510
|
+
console.log(`📋 Using saved spoof_fingerprint: ${effectiveSpoofFingerprint} (ignoring current: ${spoof_fingerprint})`);
|
|
511
|
+
} else {
|
|
512
|
+
// First launch - save the current setting
|
|
513
|
+
const settings = { spoof_fingerprint: spoof_fingerprint };
|
|
514
|
+
fs.writeFileSync(settingsFilePath, JSON.stringify(settings, null, 2), "utf-8");
|
|
515
|
+
console.log(`📝 Saved spoof_fingerprint setting: ${spoof_fingerprint}`);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
460
519
|
let fingerprintData;
|
|
461
520
|
const fingerprintFilePath = path.join(activePath, "fingerprint.json");
|
|
462
521
|
|
|
@@ -474,17 +533,42 @@ async function braveLauncher({ profilePath, proxy, CapSolver, timezoneId, maxWid
|
|
|
474
533
|
|
|
475
534
|
const braveBin = getBinaryPath("brave");
|
|
476
535
|
|
|
536
|
+
// ======================================================
|
|
537
|
+
// Disable Brave Sidebar via Preferences
|
|
538
|
+
// ======================================================
|
|
539
|
+
const prefsFilePath = path.join(activePath, "Default", "Preferences");
|
|
540
|
+
const prefsDir = path.dirname(prefsFilePath);
|
|
541
|
+
if (!fs.existsSync(prefsDir)) fs.mkdirSync(prefsDir, { recursive: true });
|
|
542
|
+
|
|
543
|
+
try {
|
|
544
|
+
let prefs = {};
|
|
545
|
+
if (fs.existsSync(prefsFilePath)) {
|
|
546
|
+
prefs = JSON.parse(fs.readFileSync(prefsFilePath, "utf-8"));
|
|
547
|
+
}
|
|
548
|
+
// Set sidebar_show_option to 3 = Never show
|
|
549
|
+
if (!prefs.brave) prefs.brave = {};
|
|
550
|
+
if (!prefs.brave.sidebar) prefs.brave.sidebar = {};
|
|
551
|
+
prefs.brave.sidebar.sidebar_show_option = 3;
|
|
552
|
+
fs.writeFileSync(prefsFilePath, JSON.stringify(prefs, null, 2), "utf-8");
|
|
553
|
+
} catch (e) {
|
|
554
|
+
console.warn("⚠️ Could not modify Brave preferences:", e.message);
|
|
555
|
+
}
|
|
556
|
+
|
|
477
557
|
const args = [
|
|
478
558
|
"--test-type",
|
|
479
559
|
// --- Stealth & Anti-Detection ---
|
|
480
560
|
"--disable-blink-features=AutomationControlled",
|
|
481
561
|
//"--disable-features=UserAgentClientHint",
|
|
482
562
|
|
|
563
|
+
// --- Window Size ---
|
|
564
|
+
"--start-maximized",
|
|
565
|
+
|
|
483
566
|
// --- PREVENT EXTRA TABS (New Flags) ---
|
|
484
567
|
// "--no-startup-window",
|
|
485
568
|
"--homepage=about:blank",
|
|
486
569
|
"--disable-restore-session-state", // Prevents restoring old tabs
|
|
487
570
|
|
|
571
|
+
|
|
488
572
|
// --- Error Suppression ---
|
|
489
573
|
"--disable-session-crashed-bubble",
|
|
490
574
|
"--hide-crash-restore-bubble",
|
|
@@ -502,7 +586,7 @@ async function braveLauncher({ profilePath, proxy, CapSolver, timezoneId, maxWid
|
|
|
502
586
|
"--disable-client-side-phishing-detection",
|
|
503
587
|
|
|
504
588
|
// --- Brave Specific Silence ---
|
|
505
|
-
"--disable-features=Translate,BraveRewards,BraveWallet,BraveNews",
|
|
589
|
+
"--disable-features=Translate,BraveRewards,BraveWallet,BraveNews,Sidebar,SidePanel",
|
|
506
590
|
"--disable-infobars",
|
|
507
591
|
];
|
|
508
592
|
const ignoreDefaultArgs = ["--enable-automation", "--no-sandbox"];
|
|
@@ -514,19 +598,39 @@ async function braveLauncher({ profilePath, proxy, CapSolver, timezoneId, maxWid
|
|
|
514
598
|
const proxyObj = formatProxy(proxy);
|
|
515
599
|
const tz = timezoneId || undefined;
|
|
516
600
|
|
|
517
|
-
const context = await chromium.launchPersistentContext(activePath, {
|
|
518
|
-
headless: false,
|
|
519
|
-
executablePath: braveBin,
|
|
520
|
-
proxy: proxyObj,
|
|
521
|
-
timezoneId: tz,
|
|
522
|
-
ignoreDefaultArgs: ignoreDefaultArgs,
|
|
523
|
-
args: args,
|
|
524
|
-
userAgent: fingerprintData.fingerprint.navigator.userAgent,
|
|
525
|
-
viewport: fingerprintData.fingerprint.screen,
|
|
526
|
-
locale: fingerprintData.fingerprint.navigator.language,
|
|
527
|
-
});
|
|
528
601
|
|
|
529
|
-
|
|
602
|
+
let context;
|
|
603
|
+
if (effectiveSpoofFingerprint) {
|
|
604
|
+
context = await chromium.launchPersistentContext(activePath, {
|
|
605
|
+
headless: false,
|
|
606
|
+
executablePath: braveBin,
|
|
607
|
+
proxy: proxyObj,
|
|
608
|
+
timezoneId: tz,
|
|
609
|
+
ignoreDefaultArgs: ignoreDefaultArgs,
|
|
610
|
+
args: args,
|
|
611
|
+
userAgent: fingerprintData.fingerprint.navigator.userAgent,
|
|
612
|
+
viewport: fingerprintData.fingerprint.screen,
|
|
613
|
+
locale: fingerprintData.fingerprint.navigator.language,
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
await new FingerprintInjector().attachFingerprintToPlaywright(context, fingerprintData);
|
|
617
|
+
}
|
|
618
|
+
else {
|
|
619
|
+
context = await chromium.launchPersistentContext(activePath, {
|
|
620
|
+
headless: false,
|
|
621
|
+
executablePath: braveBin,
|
|
622
|
+
proxy: proxyObj,
|
|
623
|
+
timezoneId: tz,
|
|
624
|
+
ignoreDefaultArgs: ignoreDefaultArgs,
|
|
625
|
+
args: args,
|
|
626
|
+
viewport: null,
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
// Manual Stealth Script
|
|
630
|
+
await addStealthScript(context);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
|
|
530
634
|
|
|
531
635
|
// ======================================================
|
|
532
636
|
// 🛠️ FIX: Close Extra Tabs (Brave Dashboard / Restore)
|