human-browser 3.0.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/README.md +218 -0
- package/SKILL.md +271 -0
- package/package.json +40 -0
- package/references/brightdata-setup.md +57 -0
- package/scripts/browser-human.js +240 -0
package/README.md
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# π Human Browser β Cloud Stealth Browser for AI Agents
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@al1enjesus/human-browser)
|
|
4
|
+
[](https://clawhub.ai/al1enjesus/human-browser)
|
|
5
|
+
[](https://skills.sh/al1enjesus/human-browser)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
> **No Mac Mini. No local machine. Your agent runs it anywhere.**
|
|
9
|
+
> Residential IPs from 10+ countries. Bypasses Cloudflare, DataDome, PerimeterX.
|
|
10
|
+
|
|
11
|
+
π **Product page + pricing:** [humanbrowser.dev](https://humanbrowser.dev)
|
|
12
|
+
π¬ **Support:** [@virixlabs](https://t.me/virixlabs)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Why your agent needs this
|
|
17
|
+
|
|
18
|
+
Regular Playwright on a VPS gets blocked **immediately** by:
|
|
19
|
+
|
|
20
|
+
- **Cloudflare** β bot score detection via data-center IP fingerprint
|
|
21
|
+
- **DataDome** β fingerprint and behavioral analysis
|
|
22
|
+
- **PerimeterX** β mouse movement and timing analysis
|
|
23
|
+
- **Instagram, LinkedIn, TikTok** β residential IP requirement
|
|
24
|
+
|
|
25
|
+
Human Browser solves this with:
|
|
26
|
+
|
|
27
|
+
1. **Residential IP** β real ISP address from target country (not a data center)
|
|
28
|
+
2. **Real device fingerprint** β iPhone 15 Pro or Windows Chrome, canvas + WebGL + fonts
|
|
29
|
+
3. **Human-like behavior** β Bezier mouse curves, 60β220ms typing, natural scroll with jitter
|
|
30
|
+
4. **Full anti-detection** β `webdriver=false`, no automation flags, correct timezone + geolocation
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# OpenClaw agents (recommended)
|
|
38
|
+
clawhub install al1enjesus/human-browser
|
|
39
|
+
|
|
40
|
+
# skild.sh (multi-platform)
|
|
41
|
+
skild install al1enjesus/human-browser
|
|
42
|
+
|
|
43
|
+
# npm
|
|
44
|
+
npm install @al1enjesus/human-browser
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
const { launchHuman } = require('./scripts/browser-human');
|
|
53
|
+
|
|
54
|
+
// Default: iPhone 15 Pro + Romania residential IP
|
|
55
|
+
const { browser, page, humanType, humanClick, humanScroll, sleep } = await launchHuman();
|
|
56
|
+
|
|
57
|
+
// Specific country
|
|
58
|
+
const { page } = await launchHuman({ country: 'us' }); // US residential IP
|
|
59
|
+
const { page } = await launchHuman({ country: 'gb' }); // UK residential IP
|
|
60
|
+
const { page } = await launchHuman({ country: 'jp' }); // Japan
|
|
61
|
+
|
|
62
|
+
// Desktop Chrome (Windows fingerprint)
|
|
63
|
+
const { page } = await launchHuman({ mobile: false, country: 'us' });
|
|
64
|
+
|
|
65
|
+
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
|
|
66
|
+
await humanScroll(page, 'down');
|
|
67
|
+
await humanType(page, 'input[type="email"]', 'user@example.com');
|
|
68
|
+
await humanClick(page, 760, 400);
|
|
69
|
+
await browser.close();
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Country β Service Compatibility
|
|
75
|
+
|
|
76
|
+
| Country | β
Works great | β Blocked |
|
|
77
|
+
|---------|--------------|-----------|
|
|
78
|
+
| π·π΄ Romania `ro` | Polymarket, Instagram, Binance, Cloudflare | US Banks, Netflix US |
|
|
79
|
+
| πΊπΈ United States `us` | Netflix, DoorDash, US Banks, Amazon US | Polymarket, Binance |
|
|
80
|
+
| π¬π§ United Kingdom `gb` | Polymarket, Binance, BBC iPlayer | US-only apps |
|
|
81
|
+
| π©πͺ Germany `de` | EU services, Binance, German e-commerce | US-only |
|
|
82
|
+
| π³π± Netherlands `nl` | Crypto, privacy, Polymarket, Web3 | US Banks |
|
|
83
|
+
| π―π΅ Japan `jp` | Japanese e-commerce, Line, localized prices | β |
|
|
84
|
+
| π«π· France `fr` | EU services, luxury brands | US-only |
|
|
85
|
+
| π¨π¦ Canada `ca` | North American services | Some US-only |
|
|
86
|
+
| πΈπ¬ Singapore `sg` | APAC/SEA e-commerce | US-only |
|
|
87
|
+
| π¦πΊ Australia `au` | Oceania content | β |
|
|
88
|
+
|
|
89
|
+
**β Interactive country selector + service matrix:** [humanbrowser.dev](https://humanbrowser.dev)
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Recipes
|
|
94
|
+
|
|
95
|
+
### Scrape Instagram without getting blocked
|
|
96
|
+
```js
|
|
97
|
+
const { page } = await launchHuman({ country: 'ro' });
|
|
98
|
+
await page.goto('https://www.instagram.com/username/');
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Polymarket / crypto platforms (EU IP required)
|
|
102
|
+
```js
|
|
103
|
+
const { page } = await launchHuman({ country: 'ro' }); // or 'gb', 'nl'
|
|
104
|
+
await page.goto('https://polymarket.com');
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### US-only services (Netflix, DoorDash)
|
|
108
|
+
```js
|
|
109
|
+
const { page } = await launchHuman({ country: 'us', mobile: false });
|
|
110
|
+
await page.goto('https://doordash.com');
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### React input fields
|
|
114
|
+
```js
|
|
115
|
+
// page.fill() fails silently on React inputs β use humanType instead
|
|
116
|
+
await humanType(page, 'input[name="email"]', 'user@example.com');
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Bypass animated button detection
|
|
120
|
+
```js
|
|
121
|
+
await page.evaluate((text) => {
|
|
122
|
+
[...document.querySelectorAll('button')]
|
|
123
|
+
.find(b => b.offsetParent && b.textContent.includes(text))?.click();
|
|
124
|
+
}, 'Continue');
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Verify your IP
|
|
128
|
+
```js
|
|
129
|
+
await page.goto('https://api.ipify.org?format=json');
|
|
130
|
+
const { ip } = JSON.parse(await page.textContent('body'));
|
|
131
|
+
console.log('IP:', ip); // Residential IP from your target country
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Get Credentials
|
|
137
|
+
|
|
138
|
+
Proxy credentials (residential IP) are required. The script itself is free and open source.
|
|
139
|
+
|
|
140
|
+
**β Purchase at: [humanbrowser.dev](https://humanbrowser.dev)**
|
|
141
|
+
|
|
142
|
+
| Plan | Price | Countries | Bandwidth |
|
|
143
|
+
|------|-------|-----------|-----------|
|
|
144
|
+
| Starter π·π΄ | $13.99/mo | Romania | 2 GB |
|
|
145
|
+
| Pro π | $49.99/mo | All 10+ countries | 20 GB |
|
|
146
|
+
| Enterprise | $199/mo | All + dedicated zone | Unlimited |
|
|
147
|
+
|
|
148
|
+
Payment: **Card** (Stripe + Apple Pay + Google Pay) or **Crypto** (USDT, BTC, ETH, SOL).
|
|
149
|
+
Credentials are delivered automatically after payment.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Agent-Native Purchase API
|
|
154
|
+
|
|
155
|
+
Your agent can buy credentials without human involvement:
|
|
156
|
+
|
|
157
|
+
```js
|
|
158
|
+
const res = await fetch('https://humanbrowser.dev/api/buy', {
|
|
159
|
+
method: 'POST',
|
|
160
|
+
headers: { 'Content-Type': 'application/json' },
|
|
161
|
+
body: JSON.stringify({
|
|
162
|
+
plan: 'starter', // 'starter' | 'pro' | 'enterprise'
|
|
163
|
+
currency: 'USDT', // 'card' | 'USDT' | 'BTC' | 'ETH' | 'SOL'
|
|
164
|
+
email: 'agent@example.com'
|
|
165
|
+
})
|
|
166
|
+
});
|
|
167
|
+
const { payment_url, order_id } = await res.json();
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
After confirmation, credentials arrive automatically:
|
|
171
|
+
```
|
|
172
|
+
PROXY_USER=brd-customer-hl_XXXXXX-zone-mcp_unlocker-country-ro
|
|
173
|
+
PROXY_PASS=XXXXXXXXXX
|
|
174
|
+
PROXY_HOST=brd.superproxy.io
|
|
175
|
+
PROXY_PORT=22225
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Prerequisites
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
npm install playwright
|
|
184
|
+
npx playwright install chromium --with-deps
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Requires residential proxy credentials β see [humanbrowser.dev](https://humanbrowser.dev) for plans.
|
|
188
|
+
For manual Bright Data setup, see [references/brightdata-setup.md](references/brightdata-setup.md).
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## How it compares
|
|
193
|
+
|
|
194
|
+
| Feature | Regular Playwright | Human Browser |
|
|
195
|
+
|---------|-------------------|---------------|
|
|
196
|
+
| IP type | Data center β blocked | Residential β clean |
|
|
197
|
+
| Bot detection | Fails | Passes all |
|
|
198
|
+
| Mouse movement | Instant teleport | Bezier curves |
|
|
199
|
+
| Typing speed | Instant | 60β220ms/char |
|
|
200
|
+
| Fingerprint | Detectable bot | iPhone 15 Pro |
|
|
201
|
+
| Countries | None | 10+ residential |
|
|
202
|
+
| Cloudflare | β | β
Bypassed |
|
|
203
|
+
| DataDome | β | β
Bypassed |
|
|
204
|
+
| Agent payment | Manual | API-native |
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Links
|
|
209
|
+
|
|
210
|
+
- π Product page: [humanbrowser.dev](https://humanbrowser.dev)
|
|
211
|
+
- π¦ ClawHub: [clawhub.ai/al1enjesus/human-browser](https://clawhub.ai/al1enjesus/human-browser)
|
|
212
|
+
- π¦ npm: [@al1enjesus/human-browser](https://www.npmjs.com/package/@al1enjesus/human-browser)
|
|
213
|
+
- π skills.sh: [skills.sh/al1enjesus/human-browser](https://skills.sh/al1enjesus/human-browser)
|
|
214
|
+
- π¬ Support: [@virixlabs](https://t.me/virixlabs)
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
MIT License Β© [al1enjesus](https://github.com/al1enjesus)
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: human-browser
|
|
3
|
+
description: "Stealth browser with residential proxy for AI agents β runs on any server, no Mac Mini or desktop required. Supports 10+ countries (US, UK, RO, DE, NL, JP, FR, CA, AU, SG). Use this skill for: web scraping, browser automation, bypassing Cloudflare, bypassing DataDome, bypassing PerimeterX, bypassing anti-bot, bypassing geo-blocks, residential proxy setup, scraping Instagram, scraping LinkedIn, scraping Amazon, scraping TikTok, scraping X/Twitter, US residential IP, UK residential IP, Japanese IP, European residential proxy, Playwright stealth, human-like browser, headless browser with proxy, login automation, form filling automation, account creation, price monitoring, data extraction from protected sites, Polymarket bot, DoorDash automation, US bank account verification, Netflix unblock, web automation without getting blocked, rotating residential proxies, multi-country proxy, country-specific IP agent. Triggers: open a browser, scrape this website, get data from a site, bypass bot detection, I keep getting blocked, need a residential IP, human browser, cloud browser, stealth mode, browser agent, playwright proxy, no mac mini, run browser on server, need US IP, need UK IP, need Japanese IP, residential proxy, unblock site."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Human Browser β Cloud Stealth Browser for AI Agents
|
|
7
|
+
|
|
8
|
+
> **No Mac Mini. No local machine. Your agent runs it anywhere.**
|
|
9
|
+
> Residential IPs from 10+ countries. Bypasses Cloudflare, DataDome, PerimeterX.
|
|
10
|
+
>
|
|
11
|
+
> π **Product page:** https://humanbrowser.dev
|
|
12
|
+
> π¬ **Support:** https://t.me/virixlabs
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Why your agent needs this
|
|
17
|
+
|
|
18
|
+
Regular Playwright on a data-center server gets blocked **immediately** by:
|
|
19
|
+
- Cloudflare (bot score detection)
|
|
20
|
+
- DataDome (fingerprint analysis)
|
|
21
|
+
- PerimeterX (behavioral analysis)
|
|
22
|
+
- Instagram, LinkedIn, TikTok (residential IP requirement)
|
|
23
|
+
|
|
24
|
+
Human Browser solves this by combining:
|
|
25
|
+
1. **Residential IP** β real ISP address from the target country (not a data center)
|
|
26
|
+
2. **Real device fingerprint** β iPhone 15 Pro or Windows Chrome, complete with canvas, WebGL, fonts
|
|
27
|
+
3. **Human-like behavior** β Bezier mouse curves, 60β220ms typing, natural scroll with jitter
|
|
28
|
+
4. **Full anti-detection** β `webdriver=false`, no automation flags, correct timezone & geolocation
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Country β Service Compatibility
|
|
33
|
+
|
|
34
|
+
Pick the right country for the right service:
|
|
35
|
+
|
|
36
|
+
| Country | β
Works great | β Blocked |
|
|
37
|
+
|---------|--------------|-----------|
|
|
38
|
+
| π·π΄ Romania `ro` | Polymarket, Instagram, Binance, Cloudflare | US Banks, Netflix US |
|
|
39
|
+
| πΊπΈ United States `us` | Netflix, DoorDash, US Banks, Amazon US | Polymarket, Binance |
|
|
40
|
+
| π¬π§ United Kingdom `gb` | Polymarket, Binance, BBC iPlayer | US-only apps |
|
|
41
|
+
| π©πͺ Germany `de` | EU services, Binance, German e-commerce | US-only |
|
|
42
|
+
| π³π± Netherlands `nl` | Crypto, privacy, Polymarket, Web3 | US Banks |
|
|
43
|
+
| π―π΅ Japan `jp` | Japanese e-commerce, Line, localized prices | β |
|
|
44
|
+
| π«π· France `fr` | EU services, luxury brands | US-only |
|
|
45
|
+
| π¨π¦ Canada `ca` | North American services | Some US-only |
|
|
46
|
+
| πΈπ¬ Singapore `sg` | APAC/SEA e-commerce | US-only |
|
|
47
|
+
| π¦πΊ Australia `au` | Oceania content | β |
|
|
48
|
+
|
|
49
|
+
**β Interactive country selector + service matrix:** https://humanbrowser.dev
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
const { launchHuman } = require('./scripts/browser-human');
|
|
57
|
+
|
|
58
|
+
// Default: iPhone 15 Pro + Romania residential IP
|
|
59
|
+
const { browser, page, humanType, humanClick, humanScroll, sleep } = await launchHuman();
|
|
60
|
+
|
|
61
|
+
// Specific country
|
|
62
|
+
const { page } = await launchHuman({ country: 'us' }); // US residential IP
|
|
63
|
+
const { page } = await launchHuman({ country: 'gb' }); // UK residential IP
|
|
64
|
+
const { page } = await launchHuman({ country: 'jp' }); // Japan IP
|
|
65
|
+
|
|
66
|
+
// Desktop Chrome (Windows fingerprint)
|
|
67
|
+
const { page } = await launchHuman({ mobile: false, country: 'us' });
|
|
68
|
+
|
|
69
|
+
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
|
|
70
|
+
await humanScroll(page, 'down');
|
|
71
|
+
await humanType(page, 'input[type="email"]', 'user@example.com');
|
|
72
|
+
await humanClick(page, 760, 400);
|
|
73
|
+
await browser.close();
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Get Credentials
|
|
79
|
+
|
|
80
|
+
Credentials (proxy username/password/zone) are required to use the residential IP.
|
|
81
|
+
|
|
82
|
+
**β Purchase at: https://humanbrowser.dev**
|
|
83
|
+
|
|
84
|
+
| Plan | Price | Countries | Bandwidth |
|
|
85
|
+
|------|-------|-----------|-----------|
|
|
86
|
+
| Starter π·π΄ | $13.99/mo | Romania only | 2GB |
|
|
87
|
+
| Pro π | $49.99/mo | All 10+ countries | 20GB |
|
|
88
|
+
| Enterprise | $199/mo | All + dedicated zone | Unlimited |
|
|
89
|
+
|
|
90
|
+
Payment options: **Stripe** (card + Apple Pay + Google Pay) or **Crypto** (USDT TRC20, BTC, ETH, SOL).
|
|
91
|
+
|
|
92
|
+
After payment β credentials are delivered automatically (email + Telegram).
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## π€ Agent-Native Payment (Autonomous Purchase)
|
|
97
|
+
|
|
98
|
+
Your agent can **purchase credentials without human involvement** using the API.
|
|
99
|
+
|
|
100
|
+
### Step 1 β Create payment via API
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
// Your agent calls this to start a purchase
|
|
104
|
+
const res = await fetch('https://humanbrowser.dev/api/buy', {
|
|
105
|
+
method: 'POST',
|
|
106
|
+
headers: { 'Content-Type': 'application/json' },
|
|
107
|
+
body: JSON.stringify({
|
|
108
|
+
plan: 'starter', // 'starter' | 'pro' | 'enterprise'
|
|
109
|
+
currency: 'USDT', // 'card' | 'USDT' | 'BTC' | 'ETH' | 'SOL'
|
|
110
|
+
email: 'your@email.com'
|
|
111
|
+
})
|
|
112
|
+
});
|
|
113
|
+
const data = await res.json();
|
|
114
|
+
// { payment_url, order_id, currency, method }
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Step 2 β Route by payment method
|
|
118
|
+
|
|
119
|
+
**If currency = 'card' (Stripe):**
|
|
120
|
+
```js
|
|
121
|
+
// Send human to the Stripe checkout link
|
|
122
|
+
return `To activate Human Browser, please complete payment:\n${data.payment_url}`;
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**If currency = 'USDT' / 'BTC' / 'ETH' / 'SOL' (crypto):**
|
|
126
|
+
```js
|
|
127
|
+
// payment_url contains the crypto invoice page
|
|
128
|
+
// Tell your human the payment URL:
|
|
129
|
+
return `To activate Human Browser:
|
|
130
|
+
Order: ${data.order_id}
|
|
131
|
+
Payment page: ${data.payment_url}
|
|
132
|
+
|
|
133
|
+
Open the link to see the exact wallet address and amount.
|
|
134
|
+
Credentials will be delivered automatically after confirmation.`;
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**For fully autonomous crypto (agent-assisted wallet):**
|
|
138
|
+
```js
|
|
139
|
+
// Agent fetches the 0xProcessing invoice page and extracts the address
|
|
140
|
+
// Then tells the human EXACTLY what to send and where:
|
|
141
|
+
const page = await invoice_page_fetch(data.payment_url);
|
|
142
|
+
// Extract: wallet address, amount in USDT, network (TRC20)
|
|
143
|
+
return `Please send ${amount} USDT (TRC20) to:\n${walletAddress}\n\nOrder: ${data.order_id}`;
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Available plans & currencies
|
|
147
|
+
|
|
148
|
+
```js
|
|
149
|
+
// Plans
|
|
150
|
+
'starter' // $13.99/mo β Romania, 2GB
|
|
151
|
+
'pro' // $49.99/mo β All countries, 20GB
|
|
152
|
+
'enterprise' // $199/mo β Unlimited + dedicated
|
|
153
|
+
|
|
154
|
+
// Currencies
|
|
155
|
+
'card' // Stripe checkout (card + Apple Pay + Google Pay)
|
|
156
|
+
'USDT' // Tether (TRC20 / ERC20)
|
|
157
|
+
'BTC' // Bitcoin mainnet
|
|
158
|
+
'ETH' // Ethereum ERC20
|
|
159
|
+
'SOL' // Solana
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### After payment
|
|
163
|
+
|
|
164
|
+
Credentials are sent automatically. You'll receive:
|
|
165
|
+
```
|
|
166
|
+
PROXY_USER=brd-customer-hl_XXXXXX-zone-mcp_unlocker-country-ro
|
|
167
|
+
PROXY_PASS=XXXXXXXXXX
|
|
168
|
+
PROXY_HOST=brd.superproxy.io
|
|
169
|
+
PROXY_PORT=22225
|
|
170
|
+
CDP_ENDPOINT=wss://brd-customer-...@brd.superproxy.io:9222
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Use these in `launchHuman()`:
|
|
174
|
+
```js
|
|
175
|
+
const { page } = await launchHuman({
|
|
176
|
+
country: 'ro',
|
|
177
|
+
proxyUser: process.env.PROXY_USER,
|
|
178
|
+
proxyPass: process.env.PROXY_PASS,
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Show human the product page
|
|
183
|
+
|
|
184
|
+
When you need to explain what this does, show pricing, or send someone to pay:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
π https://humanbrowser.dev
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Real-world recipes
|
|
193
|
+
|
|
194
|
+
### Scrape Instagram without getting blocked
|
|
195
|
+
```js
|
|
196
|
+
const { page } = await launchHuman({ country: 'ro' });
|
|
197
|
+
await page.goto('https://www.instagram.com/username/');
|
|
198
|
+
// Romanian residential IP β passes Instagram's residential check
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Polymarket / crypto platforms (EU IP required)
|
|
202
|
+
```js
|
|
203
|
+
const { page } = await launchHuman({ country: 'ro' }); // or 'gb', 'nl'
|
|
204
|
+
await page.goto('https://polymarket.com');
|
|
205
|
+
// Polymarket is blocked in US β Romanian IP works perfectly
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Netflix / DoorDash / US-only services
|
|
209
|
+
```js
|
|
210
|
+
const { page } = await launchHuman({ country: 'us', mobile: false });
|
|
211
|
+
await page.goto('https://doordash.com');
|
|
212
|
+
// US residential IP β passes geo-check
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### React input fields (don't use page.fill!)
|
|
216
|
+
```js
|
|
217
|
+
// page.fill() fails silently on React inputs β use humanType instead
|
|
218
|
+
await humanType(page, 'input[name="email"]', 'user@example.com');
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Bypass animated button detection
|
|
222
|
+
```js
|
|
223
|
+
await page.evaluate((text) => {
|
|
224
|
+
[...document.querySelectorAll('button')]
|
|
225
|
+
.find(b => b.offsetParent && b.textContent.includes(text))?.click();
|
|
226
|
+
}, 'Continue');
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Verify your IP is residential
|
|
230
|
+
```js
|
|
231
|
+
await page.goto('https://api.ipify.org?format=json');
|
|
232
|
+
const { ip } = JSON.parse(await page.textContent('body'));
|
|
233
|
+
console.log('IP:', ip); // Should show a residential IP from your target country
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Setup
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
# Install dependencies
|
|
242
|
+
npm install playwright
|
|
243
|
+
npx playwright install chromium --with-deps
|
|
244
|
+
|
|
245
|
+
# (Optional) Install via skill manager
|
|
246
|
+
clawhub install al1enjesus/human-browser
|
|
247
|
+
# OR
|
|
248
|
+
skild install al1enjesus/human-browser
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## How it compares
|
|
254
|
+
|
|
255
|
+
| Feature | Regular Playwright | Human Browser |
|
|
256
|
+
|---------|-------------------|---------------|
|
|
257
|
+
| IP type | Data center β blocked | Residential β clean |
|
|
258
|
+
| Bot detection | Fails | Passes all |
|
|
259
|
+
| Mouse movement | Instant teleport | Bezier curves |
|
|
260
|
+
| Typing speed | Instant | 60β220ms/char |
|
|
261
|
+
| Fingerprint | Detectable bot | iPhone 15 Pro |
|
|
262
|
+
| Countries | None | 10+ residential |
|
|
263
|
+
| Cloudflare | Blocked | Bypassed |
|
|
264
|
+
| DataDome | Blocked | Bypassed |
|
|
265
|
+
| Agent payment | Manual | API-native |
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
β **Product page + country selector + pricing:** https://humanbrowser.dev
|
|
270
|
+
β **Support & questions:** https://t.me/virixlabs
|
|
271
|
+
β **Bright Data manual setup:** see `references/brightdata-setup.md`
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "human-browser",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Stealth browser with residential proxies from 10+ countries for AI agents. Bypasses Cloudflare, DataDome, PerimeterX. iPhone 15 Pro fingerprint.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"browser-automation",
|
|
7
|
+
"stealth-browser",
|
|
8
|
+
"residential-proxy",
|
|
9
|
+
"playwright",
|
|
10
|
+
"cloudflare-bypass",
|
|
11
|
+
"anti-bot",
|
|
12
|
+
"scraping",
|
|
13
|
+
"ai-agent",
|
|
14
|
+
"human-browser",
|
|
15
|
+
"multi-country",
|
|
16
|
+
"instagram-scraping",
|
|
17
|
+
"web-scraping",
|
|
18
|
+
"agent-skill"
|
|
19
|
+
],
|
|
20
|
+
"author": "al1enjesus",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"homepage": "https://humanbrowser.dev",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/al1enjesus/human-browser"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"SKILL.md",
|
|
29
|
+
"README.md",
|
|
30
|
+
"scripts/",
|
|
31
|
+
"references/"
|
|
32
|
+
],
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"playwright": ">=1.40.0"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public",
|
|
38
|
+
"registry": "https://registry.npmjs.org/"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Bright Data β Setup & Reference
|
|
2
|
+
|
|
3
|
+
## Sign Up
|
|
4
|
+
- Registration: https://brightdata.com/
|
|
5
|
+
- After signup, go to: https://brightdata.com/cp/zones
|
|
6
|
+
|
|
7
|
+
## Create Zones
|
|
8
|
+
|
|
9
|
+
### Web Unlocker Zone (for regular proxying)
|
|
10
|
+
1. Dashboard β Proxies & Scraping β Add Zone
|
|
11
|
+
2. Type: **Web Unlocker**
|
|
12
|
+
3. Name: `mcp_unlocker` (or any name)
|
|
13
|
+
4. Country: Romania (or leave "All" for auto-rotation)
|
|
14
|
+
5. Copy credentials from zone settings
|
|
15
|
+
|
|
16
|
+
### Scraping Browser Zone (for Playwright CDP)
|
|
17
|
+
1. Dashboard β Proxies & Scraping β Add Zone
|
|
18
|
+
2. Type: **Scraping Browser**
|
|
19
|
+
3. Name: `mcp_browser`
|
|
20
|
+
4. Used for: `wss://brd.superproxy.io:9222` CDP endpoint
|
|
21
|
+
|
|
22
|
+
## Billing & Top-Up
|
|
23
|
+
- Top up balance: https://brightdata.com/cp/billing
|
|
24
|
+
- Minimum deposit: $10
|
|
25
|
+
- Pay-as-you-go pricing:
|
|
26
|
+
- Web Unlocker: ~$3/GB
|
|
27
|
+
- Scraping Browser: ~$9/hour
|
|
28
|
+
|
|
29
|
+
## Proxy Credentials Format
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
# HTTP Proxy (for Playwright context)
|
|
33
|
+
server: http://brd.superproxy.io:22225
|
|
34
|
+
username: brd-customer-<CUSTOMER_ID>-zone-<ZONE_NAME>-country-ro
|
|
35
|
+
password: <ZONE_PASSWORD>
|
|
36
|
+
|
|
37
|
+
# CDP WebSocket (Scraping Browser only)
|
|
38
|
+
wss://brd-customer-<CUSTOMER_ID>-zone-<ZONE_NAME>-country-ro:<PASSWORD>@brd.superproxy.io:9222
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Where to Find Credentials
|
|
42
|
+
- Dashboard: https://brightdata.com/cp/zones
|
|
43
|
+
- Click on your zone β **Access Parameters** tab
|
|
44
|
+
- Copy: Customer ID, Zone name, Password
|
|
45
|
+
|
|
46
|
+
## Country Codes
|
|
47
|
+
- `ro` β Romania (DIGI / WS Telecom residential IPs)
|
|
48
|
+
- `us` β United States
|
|
49
|
+
- `de` β Germany
|
|
50
|
+
- Remove `-country-XX` for global rotation
|
|
51
|
+
|
|
52
|
+
## Node.js Dependency
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install playwright
|
|
56
|
+
npx playwright install chromium --with-deps
|
|
57
|
+
```
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* browser-human.js β Human Browser for AI Agents
|
|
3
|
+
*
|
|
4
|
+
* Stealth browser with residential proxies from 10+ countries.
|
|
5
|
+
* Appears as iPhone 15 Pro or Desktop Chrome to every website.
|
|
6
|
+
* Bypasses Cloudflare, DataDome, PerimeterX out of the box.
|
|
7
|
+
*
|
|
8
|
+
* Get credentials: https://humanbrowser.dev
|
|
9
|
+
* Support: https://t.me/virixlabs
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* const { launchHuman } = require('./browser-human');
|
|
13
|
+
* const { browser, page } = await launchHuman({ country: 'us' });
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const { chromium } = require('playwright');
|
|
17
|
+
require('dotenv').config();
|
|
18
|
+
|
|
19
|
+
// βββ COUNTRY CONFIGS ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
20
|
+
|
|
21
|
+
const COUNTRY_META = {
|
|
22
|
+
ro: { locale: 'ro-RO', tz: 'Europe/Bucharest', lat: 44.4268, lon: 26.1025, lang: 'ro-RO,ro;q=0.9,en-US;q=0.8' },
|
|
23
|
+
us: { locale: 'en-US', tz: 'America/New_York', lat: 40.7128, lon: -74.006, lang: 'en-US,en;q=0.9' },
|
|
24
|
+
uk: { locale: 'en-GB', tz: 'Europe/London', lat: 51.5074, lon: -0.1278, lang: 'en-GB,en;q=0.9' },
|
|
25
|
+
gb: { locale: 'en-GB', tz: 'Europe/London', lat: 51.5074, lon: -0.1278, lang: 'en-GB,en;q=0.9' },
|
|
26
|
+
de: { locale: 'de-DE', tz: 'Europe/Berlin', lat: 52.5200, lon: 13.4050, lang: 'de-DE,de;q=0.9,en;q=0.8' },
|
|
27
|
+
nl: { locale: 'nl-NL', tz: 'Europe/Amsterdam', lat: 52.3676, lon: 4.9041, lang: 'nl-NL,nl;q=0.9,en;q=0.8' },
|
|
28
|
+
jp: { locale: 'ja-JP', tz: 'Asia/Tokyo', lat: 35.6762, lon: 139.6503, lang: 'ja-JP,ja;q=0.9,en;q=0.8' },
|
|
29
|
+
fr: { locale: 'fr-FR', tz: 'Europe/Paris', lat: 48.8566, lon: 2.3522, lang: 'fr-FR,fr;q=0.9,en;q=0.8' },
|
|
30
|
+
ca: { locale: 'en-CA', tz: 'America/Toronto', lat: 43.6532, lon: -79.3832, lang: 'en-CA,en;q=0.9' },
|
|
31
|
+
au: { locale: 'en-AU', tz: 'Australia/Sydney', lat: -33.8688, lon: 151.2093,lang: 'en-AU,en;q=0.9' },
|
|
32
|
+
sg: { locale: 'en-SG', tz: 'Asia/Singapore', lat: 1.3521, lon: 103.8198, lang: 'en-SG,en;q=0.9' },
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// βββ PROXY CONFIG βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
36
|
+
|
|
37
|
+
function buildProxy(country = 'ro') {
|
|
38
|
+
const c = country.toLowerCase();
|
|
39
|
+
const server = process.env.PROXY_SERVER || 'http://brd.superproxy.io:22225';
|
|
40
|
+
const username = process.env.PROXY_USERNAME || '';
|
|
41
|
+
const password = process.env.PROXY_PASSWORD || '';
|
|
42
|
+
|
|
43
|
+
if (!username || !password) {
|
|
44
|
+
console.warn('β οΈ No proxy credentials set. Get them at: https://humanbrowser.dev');
|
|
45
|
+
console.warn(' Set PROXY_USERNAME and PROXY_PASSWORD in your .env file.');
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Inject country code into username if needed
|
|
50
|
+
// e.g. brd-customer-XXX-zone-YYY β brd-customer-XXX-zone-YYY-country-ro
|
|
51
|
+
const hasCountry = username.includes('-country-');
|
|
52
|
+
const finalUser = hasCountry
|
|
53
|
+
? username.replace(/-country-\w+/, `-country-${c}`)
|
|
54
|
+
: `${username}-country-${c}`;
|
|
55
|
+
|
|
56
|
+
return { server, username: finalUser, password };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// βββ DEVICE PROFILES βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
60
|
+
|
|
61
|
+
function buildDevice(mobile, country = 'ro') {
|
|
62
|
+
const meta = COUNTRY_META[country.toLowerCase()] || COUNTRY_META.ro;
|
|
63
|
+
|
|
64
|
+
if (mobile) {
|
|
65
|
+
return {
|
|
66
|
+
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Mobile/15E148 Safari/604.1',
|
|
67
|
+
viewport: { width: 393, height: 852 },
|
|
68
|
+
deviceScaleFactor: 3,
|
|
69
|
+
isMobile: true,
|
|
70
|
+
hasTouch: true,
|
|
71
|
+
locale: meta.locale,
|
|
72
|
+
timezoneId: meta.tz,
|
|
73
|
+
geolocation: { latitude: meta.lat, longitude: meta.lon, accuracy: 50 },
|
|
74
|
+
colorScheme: 'light',
|
|
75
|
+
extraHTTPHeaders: {
|
|
76
|
+
'Accept-Language': meta.lang,
|
|
77
|
+
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
|
78
|
+
'Accept-Encoding': 'gzip, deflate, br',
|
|
79
|
+
'sec-fetch-dest': 'document',
|
|
80
|
+
'sec-fetch-mode': 'navigate',
|
|
81
|
+
'sec-fetch-site': 'none',
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
|
88
|
+
viewport: { width: 1440, height: 900 },
|
|
89
|
+
locale: meta.locale,
|
|
90
|
+
timezoneId: meta.tz,
|
|
91
|
+
geolocation: { latitude: meta.lat, longitude: meta.lon, accuracy: 50 },
|
|
92
|
+
colorScheme: 'light',
|
|
93
|
+
extraHTTPHeaders: {
|
|
94
|
+
'Accept-Language': meta.lang,
|
|
95
|
+
'sec-ch-ua': '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
|
96
|
+
'sec-ch-ua-mobile': '?0',
|
|
97
|
+
'sec-ch-ua-platform': '"Windows"',
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// βββ HUMAN BEHAVIOR βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
103
|
+
|
|
104
|
+
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
|
|
105
|
+
const rand = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
|
|
106
|
+
|
|
107
|
+
async function humanMouseMove(page, toX, toY) {
|
|
108
|
+
const cp1x = toX + rand(-80, 80), cp1y = toY + rand(-60, 60);
|
|
109
|
+
const cp2x = toX + rand(-50, 50), cp2y = toY + rand(-40, 40);
|
|
110
|
+
const startX = rand(100, 300), startY = rand(200, 600);
|
|
111
|
+
const steps = rand(12, 25);
|
|
112
|
+
for (let i = 0; i <= steps; i++) {
|
|
113
|
+
const t = i / steps;
|
|
114
|
+
const x = Math.round(Math.pow(1-t,3)*startX + 3*Math.pow(1-t,2)*t*cp1x + 3*(1-t)*t*t*cp2x + t*t*t*toX);
|
|
115
|
+
const y = Math.round(Math.pow(1-t,3)*startY + 3*Math.pow(1-t,2)*t*cp1y + 3*(1-t)*t*t*cp2y + t*t*t*toY);
|
|
116
|
+
await page.mouse.move(x, y);
|
|
117
|
+
await sleep(t < 0.2 || t > 0.8 ? rand(8, 20) : rand(2, 8));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function humanClick(page, x, y) {
|
|
122
|
+
await humanMouseMove(page, x, y);
|
|
123
|
+
await sleep(rand(50, 180));
|
|
124
|
+
await page.mouse.down();
|
|
125
|
+
await sleep(rand(40, 100));
|
|
126
|
+
await page.mouse.up();
|
|
127
|
+
await sleep(rand(100, 300));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function humanType(page, selector, text) {
|
|
131
|
+
const el = await page.$(selector);
|
|
132
|
+
if (!el) throw new Error(`Element not found: ${selector}`);
|
|
133
|
+
const box = await el.boundingBox();
|
|
134
|
+
if (box) await humanClick(page, box.x + box.width / 2, box.y + box.height / 2);
|
|
135
|
+
await sleep(rand(200, 500));
|
|
136
|
+
for (const char of text) {
|
|
137
|
+
await page.keyboard.type(char);
|
|
138
|
+
await sleep(rand(60, 220));
|
|
139
|
+
if (Math.random() < 0.08) await sleep(rand(400, 900));
|
|
140
|
+
}
|
|
141
|
+
await sleep(rand(200, 400));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function humanScroll(page, direction = 'down', amount = null) {
|
|
145
|
+
const scrollAmount = amount || rand(200, 600);
|
|
146
|
+
const delta = direction === 'down' ? scrollAmount : -scrollAmount;
|
|
147
|
+
const vp = page.viewportSize();
|
|
148
|
+
await humanMouseMove(page, rand(100, vp.width - 100), rand(200, vp.height - 200));
|
|
149
|
+
const steps = rand(4, 10);
|
|
150
|
+
for (let i = 0; i < steps; i++) {
|
|
151
|
+
await page.mouse.wheel(0, delta / steps + rand(-5, 5));
|
|
152
|
+
await sleep(rand(30, 80));
|
|
153
|
+
}
|
|
154
|
+
await sleep(rand(200, 800));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function humanRead(page, minMs = 1500, maxMs = 4000) {
|
|
158
|
+
await sleep(rand(minMs, maxMs));
|
|
159
|
+
if (Math.random() < 0.3) await humanScroll(page, 'down', rand(50, 150));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// βββ LAUNCH βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Launch a human-like browser with residential proxy
|
|
166
|
+
*
|
|
167
|
+
* @param {Object} opts
|
|
168
|
+
* @param {string} opts.country - 'ro'|'us'|'uk'|'de'|'nl'|'jp'|'fr'|'ca'|'au'|'sg' (default: 'ro')
|
|
169
|
+
* @param {boolean} opts.mobile - iPhone 15 Pro (true) or Desktop Chrome (false). Default: true
|
|
170
|
+
* @param {boolean} opts.useProxy - Enable residential proxy. Default: true
|
|
171
|
+
* @param {boolean} opts.headless - Headless mode. Default: true
|
|
172
|
+
*
|
|
173
|
+
* @returns {{ browser, ctx, page, humanClick, humanType, humanScroll, humanRead, sleep, rand }}
|
|
174
|
+
*/
|
|
175
|
+
async function launchHuman(opts = {}) {
|
|
176
|
+
const {
|
|
177
|
+
country = 'ro',
|
|
178
|
+
mobile = true,
|
|
179
|
+
useProxy = true,
|
|
180
|
+
headless = true,
|
|
181
|
+
} = opts;
|
|
182
|
+
|
|
183
|
+
const meta = COUNTRY_META[country.toLowerCase()] || COUNTRY_META.ro;
|
|
184
|
+
const device = buildDevice(mobile, country);
|
|
185
|
+
const proxy = useProxy ? buildProxy(country) : null;
|
|
186
|
+
|
|
187
|
+
const browser = await chromium.launch({
|
|
188
|
+
headless,
|
|
189
|
+
args: [
|
|
190
|
+
'--no-sandbox',
|
|
191
|
+
'--disable-setuid-sandbox',
|
|
192
|
+
'--ignore-certificate-errors',
|
|
193
|
+
'--disable-blink-features=AutomationControlled',
|
|
194
|
+
'--disable-features=IsolateOrigins,site-per-process',
|
|
195
|
+
'--disable-web-security',
|
|
196
|
+
],
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const ctxOpts = {
|
|
200
|
+
...device,
|
|
201
|
+
ignoreHTTPSErrors: true,
|
|
202
|
+
permissions: ['geolocation', 'notifications'],
|
|
203
|
+
};
|
|
204
|
+
if (proxy) ctxOpts.proxy = proxy;
|
|
205
|
+
|
|
206
|
+
const ctx = await browser.newContext(ctxOpts);
|
|
207
|
+
|
|
208
|
+
// Anti-detection overrides
|
|
209
|
+
await ctx.addInitScript((m) => {
|
|
210
|
+
Object.defineProperty(navigator, 'webdriver', { get: () => false });
|
|
211
|
+
Object.defineProperty(navigator, 'maxTouchPoints', { get: () => 5 });
|
|
212
|
+
Object.defineProperty(navigator, 'platform', { get: () => m.mobile ? 'iPhone' : 'Win32' });
|
|
213
|
+
Object.defineProperty(navigator, 'hardwareConcurrency',{ get: () => m.mobile ? 6 : 8 });
|
|
214
|
+
Object.defineProperty(navigator, 'language', { get: () => m.locale });
|
|
215
|
+
Object.defineProperty(navigator, 'languages', { get: () => [m.locale, 'en'] });
|
|
216
|
+
}, { mobile, locale: meta.locale });
|
|
217
|
+
|
|
218
|
+
const page = await ctx.newPage();
|
|
219
|
+
|
|
220
|
+
return { browser, ctx, page, humanClick, humanMouseMove, humanType, humanScroll, humanRead, sleep, rand };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
module.exports = { launchHuman, humanClick, humanMouseMove, humanType, humanScroll, humanRead, sleep, rand, COUNTRY_META };
|
|
224
|
+
|
|
225
|
+
// βββ QUICK TEST βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
226
|
+
if (require.main === module) {
|
|
227
|
+
const country = process.argv[2] || 'ro';
|
|
228
|
+
console.log(`π§ͺ Testing Human Browser β country: ${country.toUpperCase()}\n`);
|
|
229
|
+
(async () => {
|
|
230
|
+
const { browser, page } = await launchHuman({ country, mobile: true });
|
|
231
|
+
await page.goto('https://ipinfo.io/json', { waitUntil: 'domcontentloaded', timeout: 30000 });
|
|
232
|
+
const info = JSON.parse(await page.textContent('body'));
|
|
233
|
+
console.log(`β
IP: ${info.ip}`);
|
|
234
|
+
console.log(`β
Country: ${info.country} (${info.city})`);
|
|
235
|
+
console.log(`β
Org: ${info.org}`);
|
|
236
|
+
console.log(`β
TZ: ${info.timezone}`);
|
|
237
|
+
await browser.close();
|
|
238
|
+
console.log('\nπ Human Browser is ready.');
|
|
239
|
+
})().catch(console.error);
|
|
240
|
+
}
|