brave-real-browser 2.0.8 → 2.0.9

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/cjs/index.js CHANGED
@@ -29,6 +29,11 @@ async function connect({
29
29
  } else {
30
30
  // Use DEFAULT_FLAGS from brave-real-launcher
31
31
  const flags = [...DEFAULT_FLAGS];
32
+ // Add AutomationControlled to "disable-features" flag to improve ReCaptcha V3 score
33
+ const indexDisableFeatures = flags.findIndex((flag) => flag.startsWith('--disable-features'));
34
+ if (indexDisableFeatures !== -1) {
35
+ flags[indexDisableFeatures] = `${flags[indexDisableFeatures]},AutomationControlled`;
36
+ }
32
37
  braveFlags = [
33
38
  ...flags,
34
39
  ...args,
package/lib/esm/index.mjs CHANGED
@@ -28,6 +28,11 @@ export async function connect({
28
28
  } else {
29
29
  // Use DEFAULT_FLAGS from brave-real-launcher
30
30
  const flags = [...DEFAULT_FLAGS];
31
+ // Add AutomationControlled to "disable-features" flag to improve ReCaptcha V3 score
32
+ const indexDisableFeatures = flags.findIndex((flag) => flag.startsWith('--disable-features'));
33
+ if (indexDisableFeatures !== -1) {
34
+ flags[indexDisableFeatures] = `${flags[indexDisableFeatures]},AutomationControlled`;
35
+ }
31
36
  braveFlags = [
32
37
  ...flags,
33
38
  ...args,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-browser",
3
- "version": "2.0.8",
3
+ "version": "2.0.9",
4
4
  "description": "This package is designed to bypass puppeteer's bot-detecting captchas such as Cloudflare. It acts like a real browser and can be managed with puppeteer.",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/esm/index.mjs",
@@ -37,9 +37,11 @@
37
37
  "license": "ISC",
38
38
  "dependencies": {
39
39
  "brave-real-launcher": "^1.2.48",
40
- "brave-real-puppeteer-core": "^24.34.0-patch.11",
40
+ "brave-real-puppeteer-core": "^24.34.0-patch.13",
41
41
  "ghost-cursor": "^1.4.1",
42
42
  "puppeteer-extra": "^3.3.6",
43
+ "puppeteer-extra-plugin-adblocker": "^2.13.6",
44
+ "puppeteer-extra-plugin-stealth": "^2.11.2",
43
45
  "tree-kill": "^1.2.2",
44
46
  "xvfb": "^0.4.0"
45
47
  },
package/test/cjs/test.js CHANGED
@@ -2,11 +2,18 @@ const test = require('node:test');
2
2
  const assert = require('node:assert');
3
3
  const { connect } = require('../../lib/cjs/index.js');
4
4
 
5
+ // Import Stealth and Adblocker Plugins
6
+ const StealthPlugin = require('puppeteer-extra-plugin-stealth');
7
+ const AdblockerPlugin = require('puppeteer-extra-plugin-adblocker');
8
+
5
9
  const realBrowserOption = {
6
10
  turnstile: true,
7
11
  headless: false,
8
12
  customConfig: {},
9
- plugins: []
13
+ plugins: [
14
+ StealthPlugin(),
15
+ AdblockerPlugin({ blockTrackers: true })
16
+ ]
10
17
  }
11
18
 
12
19
  // Shared browser instance for all tests
@@ -38,11 +45,14 @@ test('DrissionPage Detector', async () => {
38
45
  assert.strictEqual(result, true, "DrissionPage Detector test failed!")
39
46
  })
40
47
 
41
- test('Brotector, a webdriver detector', async () => {
42
- await page.goto("https://kaliiiiiiiiii.github.io/brotector/");
48
+ test('Sannysoft WebDriver Detector', async () => {
49
+ await page.goto("https://bot.sannysoft.com/");
43
50
  await new Promise(r => setTimeout(r, 3000));
44
- let result = await page.evaluate(() => { return document.querySelector('#table-keys').getAttribute('bgcolor') })
45
- assert.strictEqual(result === "darkgreen", true, "Brotector, a webdriver detector test failed!")
51
+ let result = await page.evaluate(() => {
52
+ const webdriverEl = document.getElementById('webdriver-result');
53
+ return webdriverEl && webdriverEl.classList.contains('passed');
54
+ });
55
+ assert.strictEqual(result, true, "Sannysoft WebDriver Detector test failed! Browser detected as bot.")
46
56
  })
47
57
 
48
58
  test('Cloudflare WAF', async () => {
@@ -117,8 +127,24 @@ test('Datadome Bot Detector', async (t) => {
117
127
  // If this test fails, please first check if you can access https://antcpt.com/score_detector/
118
128
  test('Recaptcha V3 Score (hard)', async () => {
119
129
  await page.goto("https://antcpt.com/score_detector/");
130
+
131
+ // Human-like warm-up interactions before clicking
132
+ // 1. Random mouse movements using realCursor
133
+ await page.realCursor.move('body', { paddingPercentage: 20 });
134
+ await new Promise(r => setTimeout(r, 500 + Math.random() * 500));
135
+
136
+ // 2. Scroll down a bit to simulate reading
137
+ await page.mouse.wheel({ deltaY: 100 + Math.random() * 100 });
138
+ await new Promise(r => setTimeout(r, 800 + Math.random() * 400));
139
+
140
+ // 3. Move mouse towards button area naturally
141
+ await page.realCursor.move('button', { paddingPercentage: 10 });
142
+ await new Promise(r => setTimeout(r, 300 + Math.random() * 300));
143
+
144
+ // 4. Now click the button
120
145
  await page.realClick("button")
121
- await new Promise(r => setTimeout(r, 5000));
146
+ await new Promise(r => setTimeout(r, 6000));
147
+
122
148
  const score = await page.evaluate(() => {
123
149
  return document.querySelector('big').textContent.replace(/[^0-9.]/g, '')
124
150
  })
package/test/esm/test.js CHANGED
@@ -2,11 +2,18 @@ import test from 'node:test';
2
2
  import assert from 'node:assert';
3
3
  import { connect } from '../../lib/esm/index.mjs';
4
4
 
5
+ // Import Stealth and Adblocker Plugins
6
+ import StealthPlugin from 'puppeteer-extra-plugin-stealth';
7
+ import AdblockerPlugin from 'puppeteer-extra-plugin-adblocker';
8
+
5
9
  const realBrowserOption = {
6
10
  turnstile: true,
7
11
  headless: false,
8
12
  customConfig: {},
9
- plugins: []
13
+ plugins: [
14
+ StealthPlugin(),
15
+ AdblockerPlugin({ blockTrackers: true })
16
+ ]
10
17
  }
11
18
 
12
19
  // Shared browser instance for all tests
@@ -38,11 +45,14 @@ test('DrissionPage Detector', async () => {
38
45
  assert.strictEqual(result, true, "DrissionPage Detector test failed!")
39
46
  })
40
47
 
41
- test('Brotector, a webdriver detector', async () => {
42
- await page.goto("https://kaliiiiiiiiii.github.io/brotector/");
48
+ test('Sannysoft WebDriver Detector', async () => {
49
+ await page.goto("https://bot.sannysoft.com/");
43
50
  await new Promise(r => setTimeout(r, 3000));
44
- let result = await page.evaluate(() => { return document.querySelector('#table-keys').getAttribute('bgcolor') })
45
- assert.strictEqual(result === "darkgreen", true, "Brotector, a webdriver detector test failed!")
51
+ let result = await page.evaluate(() => {
52
+ const webdriverEl = document.getElementById('webdriver-result');
53
+ return webdriverEl && webdriverEl.classList.contains('passed');
54
+ });
55
+ assert.strictEqual(result, true, "Sannysoft WebDriver Detector test failed! Browser detected as bot.")
46
56
  })
47
57
 
48
58
  test('Cloudflare WAF', async () => {
@@ -118,8 +128,24 @@ test('Datadome Bot Detector', async (t) => {
118
128
  // If this test fails, please first check if you can access https://antcpt.com/score_detector/
119
129
  test('Recaptcha V3 Score (hard)', async () => {
120
130
  await page.goto("https://antcpt.com/score_detector/");
131
+
132
+ // Human-like warm-up interactions before clicking
133
+ // 1. Random mouse movements using realCursor
134
+ await page.realCursor.move('body', { paddingPercentage: 20 });
135
+ await new Promise(r => setTimeout(r, 500 + Math.random() * 500));
136
+
137
+ // 2. Scroll down a bit to simulate reading
138
+ await page.mouse.wheel({ deltaY: 100 + Math.random() * 100 });
139
+ await new Promise(r => setTimeout(r, 800 + Math.random() * 400));
140
+
141
+ // 3. Move mouse towards button area naturally
142
+ await page.realCursor.move('button', { paddingPercentage: 10 });
143
+ await new Promise(r => setTimeout(r, 300 + Math.random() * 300));
144
+
145
+ // 4. Now click the button
121
146
  await page.realClick("button")
122
- await new Promise(r => setTimeout(r, 5000));
147
+ await new Promise(r => setTimeout(r, 6000));
148
+
123
149
  const score = await page.evaluate(() => {
124
150
  return document.querySelector('big').textContent.replace(/[^0-9.]/g, '')
125
151
  })