real-browser-plus 1.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 real-browser-plus contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # real-browser-plus
2
+
3
+ A modernized, more capable successor to `puppeteer-real-browser` (which stopped receiving updates in Feb 2026). Built on current Puppeteer + `puppeteer-extra-plugin-stealth`, with a richer evasion and humanization toolkit.
4
+
5
+ ## Features
6
+
7
+ - **Self-consistent fingerprint randomization** — UA, platform, WebGL vendor/renderer, hardware concurrency, timezone, locale, and screen/viewport resolution are generated together so nothing mismatches (a common tell for detection scripts).
8
+ - **Client Hints spoofing** — `Sec-CH-UA` / `Sec-CH-UA-Platform` / `Sec-CH-UA-Full-Version-List` headers and `navigator.userAgentData` are overridden at the CDP network layer to match the spoofed Chrome version, not just the JS-visible User-Agent string.
9
+ - **Screen & viewport consistency** — `screen.width/height`, `availWidth/availHeight`, `window.outerWidth/outerHeight`, and `devicePixelRatio` are all patched together so window geometry checks can't catch a mismatch.
10
+ - **Canvas, AudioContext, WebGL & WebGL2 noise/spoof** — defeats canvas/audio hashing and GPU vendor fingerprinting on both WebGL contexts without breaking rendering.
11
+ - **Deep stealth evasions** — `navigator.webdriver`, CDP artifacts, `window.chrome`, plugins array, permissions.query, iframe.contentWindow leaks, Battery API, Network Information API, and `Function.prototype.toString` proxy detection.
12
+ - **Ghost cursor** — bezier-curve mouse movement with easing, variable speed, and randomized landing points inside target elements.
13
+ - **Human typing** — variable per-key delay, occasional realistic typos with correction, mid-sentence pauses.
14
+ - **Human scrolling** — incremental wheel events with reading pauses instead of one jump.
15
+ - **Automatic Cloudflare Turnstile handling** — detects the challenge iframe and clicks the checkbox like a real visitor, on load and on every navigation.
16
+ - **WebRTC IP leak protection** — strips ICE servers so the real local/public IP can't be extracted through WebRTC.
17
+ - **Session persistence** — save and restore cookies, localStorage, and sessionStorage across runs.
18
+ - **Proxy support with rotation** — pass one proxy or an array to rotate across launches, with auth handled automatically.
19
+ - **Retry helper** — exponential backoff with jitter for flaky network/page actions.
20
+ - **Plugin system** — hook into browser/page lifecycle events.
21
+ - **TypeScript-native**, ships both CJS and ESM builds.
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ npm install real-browser-plus
27
+ ```
28
+
29
+ On Linux, install `xvfb` if you plan to run with `headless: false` on a machine without a display:
30
+
31
+ ```bash
32
+ sudo apt-get install xvfb
33
+ ```
34
+
35
+ ## Quick start
36
+
37
+ ```ts
38
+ import { connect } from "real-browser-plus";
39
+
40
+ const { browser, page, humanClick, humanType } = await connect({
41
+ headless: false,
42
+ turnstile: true,
43
+ });
44
+
45
+ await page.goto("https://example.com/login");
46
+ await humanType(page, "#username", "myUsername");
47
+ await humanType(page, "#password", "myPassword123");
48
+ await humanClick(page, "#submit");
49
+
50
+ await browser.close();
51
+ ```
52
+
53
+ ## Using a proxy (with rotation)
54
+
55
+ ```ts
56
+ const { page } = await connect({
57
+ proxy: [
58
+ { server: "1.2.3.4:8080", username: "user1", password: "pass1" },
59
+ { server: "5.6.7.8:8080", username: "user2", password: "pass2" },
60
+ ],
61
+ });
62
+ ```
63
+
64
+ A proxy is chosen at random from the array on each `connect()` call.
65
+
66
+ ## Forcing a specific fingerprint
67
+
68
+ ```ts
69
+ const { page } = await connect({
70
+ fingerprint: {
71
+ platform: "MacIntel",
72
+ timezone: "Asia/Jakarta",
73
+ locale: "id-ID",
74
+ },
75
+ });
76
+ ```
77
+
78
+ Any field you don't specify is still randomized (consistently) around the rest.
79
+
80
+ ## API
81
+
82
+ ### `connect(options?: ConnectOptions): Promise<ConnectResult>`
83
+
84
+ | Option | Type | Default | Description |
85
+ |---|---|---|---|
86
+ | `headless` | `boolean` | `false` | Run without a visible window |
87
+ | `args` | `string[]` | `[]` | Extra Chromium flags |
88
+ | `executablePath` | `string` | — | Use a specific Chrome/Chromium binary |
89
+ | `proxy` | `ProxyConfig \| ProxyConfig[]` | — | Proxy or pool to rotate |
90
+ | `turnstile` | `boolean` | `true` | Auto-solve Cloudflare Turnstile checkboxes |
91
+ | `fingerprint` | `Partial<FingerprintProfile>` | — | Pin specific fingerprint fields |
92
+ | `disableFingerprinting` | `boolean` | `false` | Skip fingerprint randomization |
93
+ | `ghostCursor` | `boolean` | `true` | Use human-like mouse movement for `humanClick` |
94
+ | `connectToExisting` | `{ browserWSEndpoint }` \| `{ browserURL }` | — | Attach to an already-running Chrome |
95
+ | `customConfig` | `LaunchOptions` | `{}` | Passed straight through to `puppeteer.launch` |
96
+ | `ignoreAllFlags` | `boolean` | `false` | Disable every evasion patch (debugging only) |
97
+
98
+ ### `ConnectResult`
99
+
100
+ - `browser`, `page` — standard Puppeteer objects
101
+ - `fingerprint` — the resolved `FingerprintProfile` actually applied
102
+ - `humanClick(page, selector)`
103
+ - `humanType(page, selector, text)`
104
+ - `humanScroll(page, distance)`
105
+ - `solveTurnstile(page)` — manually trigger a solve attempt
106
+
107
+ ## Scope & limitations
108
+
109
+ This handles the same class of problem as `puppeteer-real-browser`: making an automated browser look and act like a real one for checkbox-style challenges (Turnstile) and general bot-detection scripts. It does **not** solve interactive image/audio CAPTCHAs (reCAPTCHA v2 puzzles, hCaptcha image grids) — those require a separate solving service.
110
+
111
+ Be aware this can never be a 100% guarantee against every detection technique — some vectors sit below what any JS/CDP-level patch can fully hide, such as TLS/JA3 handshake fingerprinting, font-enumeration fingerprinting, or CDP protocol timing signatures. Sophisticated anti-bot services combine dozens of signals, so treat this as raising the bar significantly, not as an absolute guarantee. Always check the target site's Terms of Service and applicable law before automating access to it.
112
+
113
+ ## Build from source
114
+
115
+ ```bash
116
+ npm install
117
+ npm run typecheck
118
+ npm run build
119
+ npm test
120
+ ```
121
+
122
+ ## Publishing to npm
123
+
124
+ 1. Check the name is still free: `npm view real-browser-plus` (should return a 404 / "not found").
125
+ 2. Update `"author"`, `"repository"`, `"bugs"`, and `"homepage"` in `package.json` with your own GitHub username.
126
+ 3. Log in: `npm login`
127
+ 4. Bump the version if needed: `npm version patch` (or `minor`/`major`)
128
+ 5. Publish: `npm publish`
129
+
130
+ `prepublishOnly` already runs `typecheck` → `build` → `test` automatically, so a broken package can't be published by accident.
131
+
132
+ ## License
133
+
134
+ MIT
@@ -0,0 +1,123 @@
1
+ import { LaunchOptions, Browser, Page } from 'puppeteer';
2
+
3
+ interface ProxyConfig {
4
+ server: string;
5
+ username?: string;
6
+ password?: string;
7
+ }
8
+ interface FingerprintProfile {
9
+ userAgent: string;
10
+ chromeVersion: string;
11
+ chromeMajorVersion: string;
12
+ platform: string;
13
+ viewport: {
14
+ width: number;
15
+ height: number;
16
+ deviceScaleFactor: number;
17
+ };
18
+ screen: {
19
+ width: number;
20
+ height: number;
21
+ };
22
+ hardwareConcurrency: number;
23
+ deviceMemory: number;
24
+ timezone: string;
25
+ locale: string;
26
+ webglVendor: string;
27
+ webglRenderer: string;
28
+ languages: string[];
29
+ }
30
+ interface SessionData {
31
+ cookies: unknown[];
32
+ localStorage: Record<string, string>;
33
+ sessionStorage: Record<string, string>;
34
+ origin: string;
35
+ }
36
+ type LogLevel = "silent" | "error" | "warn" | "info" | "debug";
37
+ interface RetryOptions {
38
+ retries?: number;
39
+ minDelayMs?: number;
40
+ maxDelayMs?: number;
41
+ onRetry?: (attempt: number, error: unknown) => void;
42
+ }
43
+ interface RealBrowserPlugin {
44
+ name: string;
45
+ onBrowserLaunched?: (browser: Browser) => void | Promise<void>;
46
+ onPageCreated?: (page: Page) => void | Promise<void>;
47
+ onBeforeClose?: (browser: Browser) => void | Promise<void>;
48
+ }
49
+ interface ConnectOptions {
50
+ headless?: boolean;
51
+ args?: string[];
52
+ executablePath?: string;
53
+ proxy?: ProxyConfig | ProxyConfig[];
54
+ turnstile?: boolean;
55
+ fingerprint?: Partial<FingerprintProfile>;
56
+ disableFingerprinting?: boolean;
57
+ ghostCursor?: boolean;
58
+ blockWebRTCLeak?: boolean;
59
+ connectToExisting?: {
60
+ browserWSEndpoint: string;
61
+ } | {
62
+ browserURL: string;
63
+ };
64
+ customConfig?: LaunchOptions;
65
+ ignoreAllFlags?: boolean;
66
+ plugins?: RealBrowserPlugin[];
67
+ logLevel?: LogLevel;
68
+ session?: SessionData;
69
+ }
70
+ interface ConnectResult {
71
+ browser: Browser;
72
+ page: Page;
73
+ fingerprint: FingerprintProfile;
74
+ humanClick: (page: Page, selector: string) => Promise<void>;
75
+ humanType: (page: Page, selector: string, text: string) => Promise<void>;
76
+ humanScroll: (page: Page, distance: number) => Promise<void>;
77
+ solveTurnstile: (page: Page) => Promise<boolean>;
78
+ saveSession: (page: Page) => Promise<SessionData>;
79
+ restoreSession: (page: Page, session: SessionData) => Promise<void>;
80
+ withRetry: <T>(fn: () => Promise<T>, options?: RetryOptions) => Promise<T>;
81
+ use: (plugin: RealBrowserPlugin) => Promise<void>;
82
+ }
83
+
84
+ declare function generateFingerprint(overrides?: Partial<FingerprintProfile>): FingerprintProfile;
85
+
86
+ interface Point {
87
+ x: number;
88
+ y: number;
89
+ }
90
+ declare function moveMouseHuman(page: Page, target: Point): Promise<void>;
91
+ declare function ghostClick(page: Page, selector: string): Promise<void>;
92
+
93
+ declare function humanType(page: Page, selector: string, text: string): Promise<void>;
94
+
95
+ declare function humanScroll(page: Page, distance: number): Promise<void>;
96
+
97
+ declare function solveTurnstile(page: Page): Promise<boolean>;
98
+
99
+ declare function saveSession(page: Page): Promise<SessionData>;
100
+ declare function restoreSession(page: Page, session: SessionData): Promise<void>;
101
+
102
+ declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
103
+
104
+ declare class Logger {
105
+ private level;
106
+ constructor(level?: LogLevel);
107
+ setLevel(level: LogLevel): void;
108
+ private shouldLog;
109
+ error(...args: unknown[]): void;
110
+ warn(...args: unknown[]): void;
111
+ info(...args: unknown[]): void;
112
+ debug(...args: unknown[]): void;
113
+ }
114
+ declare const logger: Logger;
115
+
116
+ declare function blockWebRTCLeak(page: Page): Promise<void>;
117
+
118
+ declare function connect(options?: ConnectOptions): Promise<ConnectResult>;
119
+ declare const _default: {
120
+ connect: typeof connect;
121
+ };
122
+
123
+ export { type ConnectOptions, type ConnectResult, type FingerprintProfile, type LogLevel, Logger, type ProxyConfig, type RealBrowserPlugin, type RetryOptions, type SessionData, blockWebRTCLeak, connect, _default as default, generateFingerprint, ghostClick, humanScroll, humanType, logger, moveMouseHuman, restoreSession, saveSession, solveTurnstile, withRetry };
@@ -0,0 +1,123 @@
1
+ import { LaunchOptions, Browser, Page } from 'puppeteer';
2
+
3
+ interface ProxyConfig {
4
+ server: string;
5
+ username?: string;
6
+ password?: string;
7
+ }
8
+ interface FingerprintProfile {
9
+ userAgent: string;
10
+ chromeVersion: string;
11
+ chromeMajorVersion: string;
12
+ platform: string;
13
+ viewport: {
14
+ width: number;
15
+ height: number;
16
+ deviceScaleFactor: number;
17
+ };
18
+ screen: {
19
+ width: number;
20
+ height: number;
21
+ };
22
+ hardwareConcurrency: number;
23
+ deviceMemory: number;
24
+ timezone: string;
25
+ locale: string;
26
+ webglVendor: string;
27
+ webglRenderer: string;
28
+ languages: string[];
29
+ }
30
+ interface SessionData {
31
+ cookies: unknown[];
32
+ localStorage: Record<string, string>;
33
+ sessionStorage: Record<string, string>;
34
+ origin: string;
35
+ }
36
+ type LogLevel = "silent" | "error" | "warn" | "info" | "debug";
37
+ interface RetryOptions {
38
+ retries?: number;
39
+ minDelayMs?: number;
40
+ maxDelayMs?: number;
41
+ onRetry?: (attempt: number, error: unknown) => void;
42
+ }
43
+ interface RealBrowserPlugin {
44
+ name: string;
45
+ onBrowserLaunched?: (browser: Browser) => void | Promise<void>;
46
+ onPageCreated?: (page: Page) => void | Promise<void>;
47
+ onBeforeClose?: (browser: Browser) => void | Promise<void>;
48
+ }
49
+ interface ConnectOptions {
50
+ headless?: boolean;
51
+ args?: string[];
52
+ executablePath?: string;
53
+ proxy?: ProxyConfig | ProxyConfig[];
54
+ turnstile?: boolean;
55
+ fingerprint?: Partial<FingerprintProfile>;
56
+ disableFingerprinting?: boolean;
57
+ ghostCursor?: boolean;
58
+ blockWebRTCLeak?: boolean;
59
+ connectToExisting?: {
60
+ browserWSEndpoint: string;
61
+ } | {
62
+ browserURL: string;
63
+ };
64
+ customConfig?: LaunchOptions;
65
+ ignoreAllFlags?: boolean;
66
+ plugins?: RealBrowserPlugin[];
67
+ logLevel?: LogLevel;
68
+ session?: SessionData;
69
+ }
70
+ interface ConnectResult {
71
+ browser: Browser;
72
+ page: Page;
73
+ fingerprint: FingerprintProfile;
74
+ humanClick: (page: Page, selector: string) => Promise<void>;
75
+ humanType: (page: Page, selector: string, text: string) => Promise<void>;
76
+ humanScroll: (page: Page, distance: number) => Promise<void>;
77
+ solveTurnstile: (page: Page) => Promise<boolean>;
78
+ saveSession: (page: Page) => Promise<SessionData>;
79
+ restoreSession: (page: Page, session: SessionData) => Promise<void>;
80
+ withRetry: <T>(fn: () => Promise<T>, options?: RetryOptions) => Promise<T>;
81
+ use: (plugin: RealBrowserPlugin) => Promise<void>;
82
+ }
83
+
84
+ declare function generateFingerprint(overrides?: Partial<FingerprintProfile>): FingerprintProfile;
85
+
86
+ interface Point {
87
+ x: number;
88
+ y: number;
89
+ }
90
+ declare function moveMouseHuman(page: Page, target: Point): Promise<void>;
91
+ declare function ghostClick(page: Page, selector: string): Promise<void>;
92
+
93
+ declare function humanType(page: Page, selector: string, text: string): Promise<void>;
94
+
95
+ declare function humanScroll(page: Page, distance: number): Promise<void>;
96
+
97
+ declare function solveTurnstile(page: Page): Promise<boolean>;
98
+
99
+ declare function saveSession(page: Page): Promise<SessionData>;
100
+ declare function restoreSession(page: Page, session: SessionData): Promise<void>;
101
+
102
+ declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
103
+
104
+ declare class Logger {
105
+ private level;
106
+ constructor(level?: LogLevel);
107
+ setLevel(level: LogLevel): void;
108
+ private shouldLog;
109
+ error(...args: unknown[]): void;
110
+ warn(...args: unknown[]): void;
111
+ info(...args: unknown[]): void;
112
+ debug(...args: unknown[]): void;
113
+ }
114
+ declare const logger: Logger;
115
+
116
+ declare function blockWebRTCLeak(page: Page): Promise<void>;
117
+
118
+ declare function connect(options?: ConnectOptions): Promise<ConnectResult>;
119
+ declare const _default: {
120
+ connect: typeof connect;
121
+ };
122
+
123
+ export { type ConnectOptions, type ConnectResult, type FingerprintProfile, type LogLevel, Logger, type ProxyConfig, type RealBrowserPlugin, type RetryOptions, type SessionData, blockWebRTCLeak, connect, _default as default, generateFingerprint, ghostClick, humanScroll, humanType, logger, moveMouseHuman, restoreSession, saveSession, solveTurnstile, withRetry };