funbrowser 0.1.0__tar.gz

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.
Files changed (58) hide show
  1. funbrowser-0.1.0/.gitignore +44 -0
  2. funbrowser-0.1.0/LICENSE +21 -0
  3. funbrowser-0.1.0/PKG-INFO +316 -0
  4. funbrowser-0.1.0/README.md +275 -0
  5. funbrowser-0.1.0/funbrowser/__init__.py +120 -0
  6. funbrowser-0.1.0/funbrowser/_cdp.py +181 -0
  7. funbrowser-0.1.0/funbrowser/_errors.py +32 -0
  8. funbrowser-0.1.0/funbrowser/_flags.py +89 -0
  9. funbrowser-0.1.0/funbrowser/_launcher.py +153 -0
  10. funbrowser-0.1.0/funbrowser/browser.py +281 -0
  11. funbrowser-0.1.0/funbrowser/context.py +163 -0
  12. funbrowser-0.1.0/funbrowser/context_pool.py +162 -0
  13. funbrowser-0.1.0/funbrowser/element.py +258 -0
  14. funbrowser-0.1.0/funbrowser/fingerprint/__init__.py +14 -0
  15. funbrowser-0.1.0/funbrowser/fingerprint/data.py +74 -0
  16. funbrowser-0.1.0/funbrowser/fingerprint/presets.py +588 -0
  17. funbrowser-0.1.0/funbrowser/geo.py +139 -0
  18. funbrowser-0.1.0/funbrowser/humanly.py +188 -0
  19. funbrowser-0.1.0/funbrowser/panel.py +1181 -0
  20. funbrowser-0.1.0/funbrowser/pool.py +152 -0
  21. funbrowser-0.1.0/funbrowser/profile.py +73 -0
  22. funbrowser-0.1.0/funbrowser/proxy.py +236 -0
  23. funbrowser-0.1.0/funbrowser/py.typed +0 -0
  24. funbrowser-0.1.0/funbrowser/solver/__init__.py +12 -0
  25. funbrowser-0.1.0/funbrowser/solver/bridge.py +167 -0
  26. funbrowser-0.1.0/funbrowser/solver/client.py +244 -0
  27. funbrowser-0.1.0/funbrowser/solver/scripts/__init__.py +0 -0
  28. funbrowser-0.1.0/funbrowser/solver/scripts/_bootstrap.js +30 -0
  29. funbrowser-0.1.0/funbrowser/solver/scripts/funcaptcha.js +74 -0
  30. funbrowser-0.1.0/funbrowser/solver/scripts/geetest.js +76 -0
  31. funbrowser-0.1.0/funbrowser/solver/scripts/hcaptcha.js +76 -0
  32. funbrowser-0.1.0/funbrowser/solver/scripts/recaptcha_v2.js +79 -0
  33. funbrowser-0.1.0/funbrowser/solver/scripts/recaptcha_v3.js +45 -0
  34. funbrowser-0.1.0/funbrowser/solver/scripts/turnstile.js +60 -0
  35. funbrowser-0.1.0/funbrowser/stealth/__init__.py +13 -0
  36. funbrowser-0.1.0/funbrowser/stealth/flags.py +54 -0
  37. funbrowser-0.1.0/funbrowser/stealth/patches.py +214 -0
  38. funbrowser-0.1.0/funbrowser/stealth/scripts/__init__.py +0 -0
  39. funbrowser-0.1.0/funbrowser/stealth/scripts/_camouflage.js +32 -0
  40. funbrowser-0.1.0/funbrowser/stealth/scripts/_cleanup.js +8 -0
  41. funbrowser-0.1.0/funbrowser/stealth/scripts/audio_noise.js +32 -0
  42. funbrowser-0.1.0/funbrowser/stealth/scripts/canvas_noise.js +43 -0
  43. funbrowser-0.1.0/funbrowser/stealth/scripts/chrome_runtime.js +53 -0
  44. funbrowser-0.1.0/funbrowser/stealth/scripts/hardware.js +15 -0
  45. funbrowser-0.1.0/funbrowser/stealth/scripts/languages.js +13 -0
  46. funbrowser-0.1.0/funbrowser/stealth/scripts/permissions.js +15 -0
  47. funbrowser-0.1.0/funbrowser/stealth/scripts/platform.js +18 -0
  48. funbrowser-0.1.0/funbrowser/stealth/scripts/plugins.js +37 -0
  49. funbrowser-0.1.0/funbrowser/stealth/scripts/screen_props.js +18 -0
  50. funbrowser-0.1.0/funbrowser/stealth/scripts/webdriver.js +14 -0
  51. funbrowser-0.1.0/funbrowser/stealth/scripts/webgl.js +27 -0
  52. funbrowser-0.1.0/funbrowser/stealth/scripts/webrtc.js +45 -0
  53. funbrowser-0.1.0/funbrowser/tab.py +345 -0
  54. funbrowser-0.1.0/funbrowser/tls/__init__.py +25 -0
  55. funbrowser-0.1.0/funbrowser/tls/ca.py +181 -0
  56. funbrowser-0.1.0/funbrowser/tls/http.py +145 -0
  57. funbrowser-0.1.0/funbrowser/tls/mitm.py +326 -0
  58. funbrowser-0.1.0/pyproject.toml +159 -0
@@ -0,0 +1,44 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ .eggs/
7
+ build/
8
+ dist/
9
+ pip-wheel-metadata/
10
+
11
+ # Virtual environments
12
+ .venv/
13
+ venv/
14
+ env/
15
+
16
+ # Tooling caches
17
+ .mypy_cache/
18
+ .ruff_cache/
19
+ .pytest_cache/
20
+ .tox/
21
+ .coverage
22
+ .coverage.*
23
+ htmlcov/
24
+
25
+ # Editors
26
+ .idea/
27
+ .vscode/
28
+ *.swp
29
+ *.swo
30
+
31
+ # OS
32
+ .DS_Store
33
+ Thumbs.db
34
+
35
+ # FunBrowser-specific
36
+ # Profiles created by browser launches during local development
37
+ profiles/
38
+ *.profile/
39
+ # Example artifacts
40
+ example.png
41
+ examples/*.png
42
+ # Secrets: never commit API keys
43
+ .env
44
+ .env.local
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FunBrowser 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.
@@ -0,0 +1,316 @@
1
+ Metadata-Version: 2.4
2
+ Name: funbrowser
3
+ Version: 0.1.0
4
+ Summary: Undetect browser SDK for Python with built-in captcha solving via funsolver.com
5
+ Project-URL: Homepage, https://github.com/WhyY0u/funBrowser
6
+ Project-URL: Documentation, https://github.com/WhyY0u/funBrowser#readme
7
+ Project-URL: Repository, https://github.com/WhyY0u/funBrowser
8
+ Project-URL: Issues, https://github.com/WhyY0u/funBrowser/issues
9
+ Project-URL: Changelog, https://github.com/WhyY0u/funBrowser/blob/main/CHANGELOG.md
10
+ Project-URL: FunSolver API, https://funsolver.com
11
+ Author: FunBrowser contributors
12
+ License-Expression: MIT
13
+ License-File: LICENSE
14
+ Keywords: anti-bot,anti-detect,antibot,antidetect,async,asyncio,automation,bot-detection,browser,browser-automation,captcha,captcha-bypass,captcha-solver,cdp,chrome,chrome-devtools-protocol,cloudflare,cloudflare-bypass,fingerprint,fingerprint-spoofing,funcaptcha,funsolver,geetest,hcaptcha,headless,headless-chrome,proxy,python,recaptcha,scraping,stealth,stealth-browser,turnstile,undetect,undetected,web-scraping
15
+ Classifier: Development Status :: 4 - Beta
16
+ Classifier: Framework :: AsyncIO
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Operating System :: MacOS
20
+ Classifier: Operating System :: Microsoft :: Windows
21
+ Classifier: Operating System :: OS Independent
22
+ Classifier: Operating System :: POSIX :: Linux
23
+ Classifier: Programming Language :: Python :: 3
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Programming Language :: Python :: 3.13
27
+ Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
28
+ Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
29
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
30
+ Classifier: Topic :: Software Development :: Testing
31
+ Classifier: Typing :: Typed
32
+ Requires-Python: >=3.11
33
+ Requires-Dist: httpx>=0.27
34
+ Requires-Dist: websockets>=12.0
35
+ Provides-Extra: panel
36
+ Requires-Dist: aiohttp>=3.9; extra == 'panel'
37
+ Provides-Extra: tls
38
+ Requires-Dist: cryptography>=42; extra == 'tls'
39
+ Requires-Dist: curl-cffi>=0.7; extra == 'tls'
40
+ Description-Content-Type: text/markdown
41
+
42
+ # FunBrowser
43
+
44
+ [![PyPI - Version](https://img.shields.io/pypi/v/funbrowser)](https://pypi.org/project/funbrowser/)
45
+ [![Python Versions](https://img.shields.io/pypi/pyversions/funbrowser)](https://pypi.org/project/funbrowser/)
46
+ [![License](https://img.shields.io/pypi/l/funbrowser)](https://github.com/WhyY0u/funBrowser/blob/main/LICENSE)
47
+
48
+ **Undetect / anti-detect browser SDK for Python.** Drives real Chrome through
49
+ the DevTools Protocol with built-in stealth patches, customisable browser
50
+ fingerprints (UA, GPU, screen, timezone, CPU cores, …), full proxy support,
51
+ human-like input timing, browser-pool / context-pool farming, an optional
52
+ local web panel, and automatic captcha solving for **Cloudflare Turnstile**,
53
+ **reCAPTCHA v2 / v3**, **hCaptcha**, **FunCaptcha**, and **GeeTest** through
54
+ [funsolver.com](https://funsolver.com).
55
+
56
+ Built for web scraping, browser automation, and bypassing antibot services
57
+ (Cloudflare, DataDome, PerimeterX, Akamai) without the Selenium / Playwright
58
+ leaks that get scripts flagged.
59
+
60
+ ```bash
61
+ pip install funbrowser # core: stealth + automation + solver
62
+ pip install funbrowser[panel] # + local web panel for the pool
63
+ pip install funbrowser[tls] # + browser-grade TLS impersonation
64
+ ```
65
+
66
+ ## Quick start
67
+
68
+ ```python
69
+ import asyncio
70
+ import funbrowser
71
+
72
+ async def main():
73
+ async with await funbrowser.start(headless=True) as browser:
74
+ tab = await browser.get("https://example.com")
75
+ print(await tab.evaluate("document.title"))
76
+ # → Example Domain
77
+ print(await tab.evaluate("navigator.userAgent"))
78
+ # → Mozilla/5.0 ... Chrome/... — no "HeadlessChrome"
79
+
80
+ asyncio.run(main())
81
+ ```
82
+
83
+ ```python
84
+ # Full automation: stealth + proxy + auto-solve captchas + humanly input
85
+ async with await funbrowser.start(
86
+ headless=True,
87
+ proxy="user:pass@us-1.proxy.io:8080", # any common format works
88
+ api_key="fs_xxx", # funsolver.com key
89
+ humanly=True, # Bezier mouse + typing rhythm
90
+ fingerprint=funbrowser.presets.windows_11_nvidia_rtx_4070(),
91
+ ) as browser:
92
+ tab = await browser.get("https://target-with-captcha.com")
93
+ # captchas auto-solve in the background
94
+ await tab.fill("#email", "alice@example.com")
95
+ await tab.click("button[type=submit]")
96
+ ```
97
+
98
+ ## Features
99
+
100
+ ### Stealth (passes 25/25 standard antidetect probes)
101
+
102
+ - `navigator.webdriver` → undefined, **with native `toString` camouflage**
103
+ - UA + Client Hints with `HeadlessChrome` stripped
104
+ - `chrome.runtime`, `plugins`, `languages`, permissions consistency
105
+ - **Real GPU** for WebGL (`--use-gl=angle`, not SwiftShader)
106
+ - Canvas + audio readout noise to break fingerprint tracking
107
+ - WebRTC IP leak blocked (flag-level + SDP filter)
108
+ - iframe stealth propagation
109
+ - Geo auto-couples timezone + locale to proxy exit IP
110
+
111
+ ```bash
112
+ uv run python examples/detect_check.py # self-audit
113
+ ```
114
+
115
+ ### Fingerprint customisation
116
+
117
+ 17 ready presets (Windows × NVIDIA / Intel / AMD, macOS Apple Silicon /
118
+ Intel, Linux, plus 4 Android mobile) + arbitrary custom `Fingerprint(...)`.
119
+
120
+ ```python
121
+ from funbrowser import Fingerprint, presets
122
+
123
+ fp = presets.macos_apple_silicon_m3_pro().merge(
124
+ Fingerprint(timezone="Asia/Tokyo", languages=("ja-JP", "ja", "en"))
125
+ )
126
+ async with await funbrowser.start(fingerprint=fp) as browser:
127
+ ...
128
+ ```
129
+
130
+ ### Humanly mode (Bezier-curve mouse + typing rhythm)
131
+
132
+ ```python
133
+ async with await funbrowser.start(humanly=True) as browser:
134
+ await tab.click("button") # cursor curves toward target
135
+ await tab.type("#email", "ada") # per-keystroke random delay
136
+ ```
137
+
138
+ Presets: `humanly.FAST`, `humanly.DEFAULT`, `humanly.CAREFUL`, plus arbitrary
139
+ custom `HumanBehavior(...)`.
140
+
141
+ ### Captcha auto-solve
142
+
143
+ Paste a [funsolver.com](https://funsolver.com) API key. Five captcha
144
+ families detected on-page and solved automatically:
145
+
146
+ | | API method | Page integration |
147
+ |---|---|---|
148
+ | Cloudflare Turnstile | `solve_turnstile` | `.cf-turnstile` widgets |
149
+ | reCAPTCHA v2 (+ Enterprise) | `solve_recaptcha_v2` | `.g-recaptcha` widgets |
150
+ | reCAPTCHA v3 (+ Enterprise) | `solve_recaptcha_v3` | hooks `grecaptcha.execute()` |
151
+ | hCaptcha | `solve_hcaptcha` | `.h-captcha` widgets |
152
+ | FunCaptcha / Arkose | `solve_funcaptcha` | `[data-pkey]` elements |
153
+ | GeeTest v3 + v4 | `solve_geetest` | hooks `initGeetest` / `initGeetest4` |
154
+
155
+ ### Proxies (every format)
156
+
157
+ `host:port`, `host:port:user:pass`, `user:pass@host:port`, `host:port@user:pass`,
158
+ `socks5://...`, `chrome` URL form — all auto-parsed. HTTP/HTTPS auth flows
159
+ through CDP automatically.
160
+
161
+ ### Persistent profiles
162
+
163
+ ```python
164
+ from funbrowser import Profile
165
+
166
+ alice = Profile.ensure("alice") # ./funbrowser_profiles/alice
167
+ async with await funbrowser.start(user_data_dir=alice) as browser:
168
+ # cookies + localStorage + login state persist between runs
169
+ ...
170
+ ```
171
+
172
+ ### Browser farming — `BrowserPool` and `ContextPool`
173
+
174
+ ```python
175
+ from funbrowser import BrowserPool, ContextPool
176
+
177
+ # Process pool — full Chrome per slot (max isolation)
178
+ async with BrowserPool(
179
+ size=5,
180
+ proxies=["proxy1:8080", "proxy2:8080", "proxy3:8080"],
181
+ headless=True,
182
+ mini=True,
183
+ ) as pool:
184
+ async def scrape(browser):
185
+ tab = await browser.get("https://example.com")
186
+ return await tab.evaluate("document.title")
187
+
188
+ results = await pool.run_all([scrape] * 100)
189
+
190
+ # Context pool — 1 Chrome + N isolated contexts (~7-10x less RAM)
191
+ async with ContextPool(size=10, headless=True, mini=True) as pool:
192
+ async def scrape(ctx):
193
+ tab = await ctx.get("https://example.com")
194
+ return await tab.evaluate("document.title")
195
+
196
+ results = await pool.run_all([scrape] * 100)
197
+ ```
198
+
199
+ Memory comparison on the same 10-slot workload:
200
+ - `BrowserPool(size=10)` → ~1.0 GB
201
+ - `ContextPool(size=10)` → ~260 MB (one Chrome + 10 contexts)
202
+
203
+ ### `mini=True` mode
204
+
205
+ Curated set of Chrome flags that cut RAM / CPU / disk per browser
206
+ (~50% lower RSS): site isolation off, background throttling, audio
207
+ muted, extensions / sync / translate disabled, small disk caches,
208
+ V8 heap cap. Combines with stealth — does **not** turn off the real
209
+ GPU. Works on `Browser`, `BrowserPool`, and `ContextPool` alike.
210
+
211
+ ### TLS fingerprint impersonation (`pip install funbrowser[tls]`)
212
+
213
+ Script-level HTTP that picks JA3/JA4 from real-browser profiles:
214
+
215
+ ```python
216
+ from funbrowser.tls import ImpersonatedHTTPClient
217
+
218
+ async with ImpersonatedHTTPClient(profile="chrome131") as http:
219
+ r = await http.get("https://protected-api.com/endpoint")
220
+ ```
221
+
222
+ 23 supported profiles: `chrome99..chrome133a`, `safari15..safari18`,
223
+ `firefox133/135`, Android variants. See
224
+ [docs/M10_M11_DESIGN.md](docs/M10_M11_DESIGN.md) for the deeper
225
+ browser-traffic mitm proxy roadmap.
226
+
227
+ ### Local web panel (`pip install funbrowser[panel]`)
228
+
229
+ ```python
230
+ from funbrowser import BrowserPool, Panel
231
+
232
+ async with BrowserPool(size=5) as pool:
233
+ async with Panel(pool) as panel:
234
+ print(panel.url) # http://127.0.0.1:8765
235
+ await long_running_task()
236
+ ```
237
+
238
+ Black-and-white dashboard with: pool stats, FunSolver balance, browser
239
+ fleet table (proxy / geo / fingerprint / open tabs / per-row goto +
240
+ screenshot), activity log (panel actions + per-browser captcha solves),
241
+ quick actions, and a **script runner** — upload an `async def
242
+ main(browser)` script and run it on one browser or fan it out across
243
+ the whole pool, with per-run stdout / return / traceback captured.
244
+
245
+ ## Documentation
246
+
247
+ - [docs/stealth.md](docs/stealth.md) — anti-detect coverage in depth
248
+ - [docs/captchas.md](docs/captchas.md) — solver integration guide
249
+ - [docs/farming.md](docs/farming.md) — `BrowserPool` vs `ContextPool`
250
+ - [docs/panel.md](docs/panel.md) — the local web dashboard
251
+ - [docs/M10_M11_DESIGN.md](docs/M10_M11_DESIGN.md) — TLS + engine-layer roadmap
252
+ - [examples/](examples/) — runnable demos for every feature
253
+
254
+ ## Self-audit
255
+
256
+ ```bash
257
+ uv run python examples/detect_check.py
258
+ ```
259
+
260
+ ```
261
+ [navigator.* basics] 9/9 PASS
262
+ [chrome runtime + iframe] 6/6 PASS
263
+ [stealth-detection probes] 5/5 PASS
264
+ [WebGL / canvas / audio] 4/4 PASS
265
+ [WebRTC IP leak] 1/1 PASS
266
+
267
+ score: 25/25 (100%)
268
+ ```
269
+
270
+ ## Roadmap
271
+
272
+ | | Milestone | Status |
273
+ |---|---|---|
274
+ | M0 | Bootstrap | done |
275
+ | M1 | CDP core + Tab API | done |
276
+ | M2 | Stealth Tier 1 + 2 | done |
277
+ | M2.5 | Fingerprint customisation | done |
278
+ | M3 | Solver bridge + Turnstile | done |
279
+ | M4 | reCAPTCHA / hCaptcha / FunCaptcha / GeeTest | done |
280
+ | M5 | Production hardening (proxies, profiles, retries, multi-tab) | done |
281
+ | M5.5 | DX Tier S (auto-wait + ElementHandle + cookies + block_urls) | done |
282
+ | M5.5+ | Humanly mode | done |
283
+ | M5.5++ | WebRTC + toString camouflage + geo auto-couple | done |
284
+ | M5.5+++ | Mobile presets + expanded catalog | done |
285
+ | M5.6 | BrowserPool | done |
286
+ | M5.7 | Web Panel (+ FunSolver balance + per-browser logs + scripts) | done |
287
+ | M5.8 | Mini mode | done |
288
+ | M6 | **v0.1 release** | **in progress** |
289
+ | M10a | TLS HTTP client (curl_cffi) | done |
290
+ | M11-alt | ContextPool (lightweight pool) | done |
291
+ | M7 | Fingerprint consistency (Tier 3) | post-v0.1 |
292
+ | M8 | Real fingerprint pool (Tier 4) | post-v0.1 |
293
+ | M9 | Deep WebGL / canvas / shader spoofing | post-v0.1 |
294
+ | M10b | mitm proxy for Chrome traffic (production-grade) | post-v0.1 |
295
+ | M11 | Browser fork (Camoufox / Chromium) | post-v0.1 |
296
+ | M12 | Tauri UI for manual mode | post-v0.1 |
297
+
298
+ ## Development
299
+
300
+ Uses [uv](https://docs.astral.sh/uv/) for env + deps.
301
+
302
+ ```bash
303
+ uv sync # install
304
+ uv run pytest -q # full test suite (173 tests)
305
+ uv run ruff check . && uv run ruff format --check .
306
+ uv run mypy funbrowser
307
+ uv run python examples/detect_check.py
308
+ ```
309
+
310
+ ## Contributing
311
+
312
+ See [CONTRIBUTING.md](CONTRIBUTING.md). Issues + PRs welcome.
313
+
314
+ ## License
315
+
316
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,275 @@
1
+ # FunBrowser
2
+
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/funbrowser)](https://pypi.org/project/funbrowser/)
4
+ [![Python Versions](https://img.shields.io/pypi/pyversions/funbrowser)](https://pypi.org/project/funbrowser/)
5
+ [![License](https://img.shields.io/pypi/l/funbrowser)](https://github.com/WhyY0u/funBrowser/blob/main/LICENSE)
6
+
7
+ **Undetect / anti-detect browser SDK for Python.** Drives real Chrome through
8
+ the DevTools Protocol with built-in stealth patches, customisable browser
9
+ fingerprints (UA, GPU, screen, timezone, CPU cores, …), full proxy support,
10
+ human-like input timing, browser-pool / context-pool farming, an optional
11
+ local web panel, and automatic captcha solving for **Cloudflare Turnstile**,
12
+ **reCAPTCHA v2 / v3**, **hCaptcha**, **FunCaptcha**, and **GeeTest** through
13
+ [funsolver.com](https://funsolver.com).
14
+
15
+ Built for web scraping, browser automation, and bypassing antibot services
16
+ (Cloudflare, DataDome, PerimeterX, Akamai) without the Selenium / Playwright
17
+ leaks that get scripts flagged.
18
+
19
+ ```bash
20
+ pip install funbrowser # core: stealth + automation + solver
21
+ pip install funbrowser[panel] # + local web panel for the pool
22
+ pip install funbrowser[tls] # + browser-grade TLS impersonation
23
+ ```
24
+
25
+ ## Quick start
26
+
27
+ ```python
28
+ import asyncio
29
+ import funbrowser
30
+
31
+ async def main():
32
+ async with await funbrowser.start(headless=True) as browser:
33
+ tab = await browser.get("https://example.com")
34
+ print(await tab.evaluate("document.title"))
35
+ # → Example Domain
36
+ print(await tab.evaluate("navigator.userAgent"))
37
+ # → Mozilla/5.0 ... Chrome/... — no "HeadlessChrome"
38
+
39
+ asyncio.run(main())
40
+ ```
41
+
42
+ ```python
43
+ # Full automation: stealth + proxy + auto-solve captchas + humanly input
44
+ async with await funbrowser.start(
45
+ headless=True,
46
+ proxy="user:pass@us-1.proxy.io:8080", # any common format works
47
+ api_key="fs_xxx", # funsolver.com key
48
+ humanly=True, # Bezier mouse + typing rhythm
49
+ fingerprint=funbrowser.presets.windows_11_nvidia_rtx_4070(),
50
+ ) as browser:
51
+ tab = await browser.get("https://target-with-captcha.com")
52
+ # captchas auto-solve in the background
53
+ await tab.fill("#email", "alice@example.com")
54
+ await tab.click("button[type=submit]")
55
+ ```
56
+
57
+ ## Features
58
+
59
+ ### Stealth (passes 25/25 standard antidetect probes)
60
+
61
+ - `navigator.webdriver` → undefined, **with native `toString` camouflage**
62
+ - UA + Client Hints with `HeadlessChrome` stripped
63
+ - `chrome.runtime`, `plugins`, `languages`, permissions consistency
64
+ - **Real GPU** for WebGL (`--use-gl=angle`, not SwiftShader)
65
+ - Canvas + audio readout noise to break fingerprint tracking
66
+ - WebRTC IP leak blocked (flag-level + SDP filter)
67
+ - iframe stealth propagation
68
+ - Geo auto-couples timezone + locale to proxy exit IP
69
+
70
+ ```bash
71
+ uv run python examples/detect_check.py # self-audit
72
+ ```
73
+
74
+ ### Fingerprint customisation
75
+
76
+ 17 ready presets (Windows × NVIDIA / Intel / AMD, macOS Apple Silicon /
77
+ Intel, Linux, plus 4 Android mobile) + arbitrary custom `Fingerprint(...)`.
78
+
79
+ ```python
80
+ from funbrowser import Fingerprint, presets
81
+
82
+ fp = presets.macos_apple_silicon_m3_pro().merge(
83
+ Fingerprint(timezone="Asia/Tokyo", languages=("ja-JP", "ja", "en"))
84
+ )
85
+ async with await funbrowser.start(fingerprint=fp) as browser:
86
+ ...
87
+ ```
88
+
89
+ ### Humanly mode (Bezier-curve mouse + typing rhythm)
90
+
91
+ ```python
92
+ async with await funbrowser.start(humanly=True) as browser:
93
+ await tab.click("button") # cursor curves toward target
94
+ await tab.type("#email", "ada") # per-keystroke random delay
95
+ ```
96
+
97
+ Presets: `humanly.FAST`, `humanly.DEFAULT`, `humanly.CAREFUL`, plus arbitrary
98
+ custom `HumanBehavior(...)`.
99
+
100
+ ### Captcha auto-solve
101
+
102
+ Paste a [funsolver.com](https://funsolver.com) API key. Five captcha
103
+ families detected on-page and solved automatically:
104
+
105
+ | | API method | Page integration |
106
+ |---|---|---|
107
+ | Cloudflare Turnstile | `solve_turnstile` | `.cf-turnstile` widgets |
108
+ | reCAPTCHA v2 (+ Enterprise) | `solve_recaptcha_v2` | `.g-recaptcha` widgets |
109
+ | reCAPTCHA v3 (+ Enterprise) | `solve_recaptcha_v3` | hooks `grecaptcha.execute()` |
110
+ | hCaptcha | `solve_hcaptcha` | `.h-captcha` widgets |
111
+ | FunCaptcha / Arkose | `solve_funcaptcha` | `[data-pkey]` elements |
112
+ | GeeTest v3 + v4 | `solve_geetest` | hooks `initGeetest` / `initGeetest4` |
113
+
114
+ ### Proxies (every format)
115
+
116
+ `host:port`, `host:port:user:pass`, `user:pass@host:port`, `host:port@user:pass`,
117
+ `socks5://...`, `chrome` URL form — all auto-parsed. HTTP/HTTPS auth flows
118
+ through CDP automatically.
119
+
120
+ ### Persistent profiles
121
+
122
+ ```python
123
+ from funbrowser import Profile
124
+
125
+ alice = Profile.ensure("alice") # ./funbrowser_profiles/alice
126
+ async with await funbrowser.start(user_data_dir=alice) as browser:
127
+ # cookies + localStorage + login state persist between runs
128
+ ...
129
+ ```
130
+
131
+ ### Browser farming — `BrowserPool` and `ContextPool`
132
+
133
+ ```python
134
+ from funbrowser import BrowserPool, ContextPool
135
+
136
+ # Process pool — full Chrome per slot (max isolation)
137
+ async with BrowserPool(
138
+ size=5,
139
+ proxies=["proxy1:8080", "proxy2:8080", "proxy3:8080"],
140
+ headless=True,
141
+ mini=True,
142
+ ) as pool:
143
+ async def scrape(browser):
144
+ tab = await browser.get("https://example.com")
145
+ return await tab.evaluate("document.title")
146
+
147
+ results = await pool.run_all([scrape] * 100)
148
+
149
+ # Context pool — 1 Chrome + N isolated contexts (~7-10x less RAM)
150
+ async with ContextPool(size=10, headless=True, mini=True) as pool:
151
+ async def scrape(ctx):
152
+ tab = await ctx.get("https://example.com")
153
+ return await tab.evaluate("document.title")
154
+
155
+ results = await pool.run_all([scrape] * 100)
156
+ ```
157
+
158
+ Memory comparison on the same 10-slot workload:
159
+ - `BrowserPool(size=10)` → ~1.0 GB
160
+ - `ContextPool(size=10)` → ~260 MB (one Chrome + 10 contexts)
161
+
162
+ ### `mini=True` mode
163
+
164
+ Curated set of Chrome flags that cut RAM / CPU / disk per browser
165
+ (~50% lower RSS): site isolation off, background throttling, audio
166
+ muted, extensions / sync / translate disabled, small disk caches,
167
+ V8 heap cap. Combines with stealth — does **not** turn off the real
168
+ GPU. Works on `Browser`, `BrowserPool`, and `ContextPool` alike.
169
+
170
+ ### TLS fingerprint impersonation (`pip install funbrowser[tls]`)
171
+
172
+ Script-level HTTP that picks JA3/JA4 from real-browser profiles:
173
+
174
+ ```python
175
+ from funbrowser.tls import ImpersonatedHTTPClient
176
+
177
+ async with ImpersonatedHTTPClient(profile="chrome131") as http:
178
+ r = await http.get("https://protected-api.com/endpoint")
179
+ ```
180
+
181
+ 23 supported profiles: `chrome99..chrome133a`, `safari15..safari18`,
182
+ `firefox133/135`, Android variants. See
183
+ [docs/M10_M11_DESIGN.md](docs/M10_M11_DESIGN.md) for the deeper
184
+ browser-traffic mitm proxy roadmap.
185
+
186
+ ### Local web panel (`pip install funbrowser[panel]`)
187
+
188
+ ```python
189
+ from funbrowser import BrowserPool, Panel
190
+
191
+ async with BrowserPool(size=5) as pool:
192
+ async with Panel(pool) as panel:
193
+ print(panel.url) # http://127.0.0.1:8765
194
+ await long_running_task()
195
+ ```
196
+
197
+ Black-and-white dashboard with: pool stats, FunSolver balance, browser
198
+ fleet table (proxy / geo / fingerprint / open tabs / per-row goto +
199
+ screenshot), activity log (panel actions + per-browser captcha solves),
200
+ quick actions, and a **script runner** — upload an `async def
201
+ main(browser)` script and run it on one browser or fan it out across
202
+ the whole pool, with per-run stdout / return / traceback captured.
203
+
204
+ ## Documentation
205
+
206
+ - [docs/stealth.md](docs/stealth.md) — anti-detect coverage in depth
207
+ - [docs/captchas.md](docs/captchas.md) — solver integration guide
208
+ - [docs/farming.md](docs/farming.md) — `BrowserPool` vs `ContextPool`
209
+ - [docs/panel.md](docs/panel.md) — the local web dashboard
210
+ - [docs/M10_M11_DESIGN.md](docs/M10_M11_DESIGN.md) — TLS + engine-layer roadmap
211
+ - [examples/](examples/) — runnable demos for every feature
212
+
213
+ ## Self-audit
214
+
215
+ ```bash
216
+ uv run python examples/detect_check.py
217
+ ```
218
+
219
+ ```
220
+ [navigator.* basics] 9/9 PASS
221
+ [chrome runtime + iframe] 6/6 PASS
222
+ [stealth-detection probes] 5/5 PASS
223
+ [WebGL / canvas / audio] 4/4 PASS
224
+ [WebRTC IP leak] 1/1 PASS
225
+
226
+ score: 25/25 (100%)
227
+ ```
228
+
229
+ ## Roadmap
230
+
231
+ | | Milestone | Status |
232
+ |---|---|---|
233
+ | M0 | Bootstrap | done |
234
+ | M1 | CDP core + Tab API | done |
235
+ | M2 | Stealth Tier 1 + 2 | done |
236
+ | M2.5 | Fingerprint customisation | done |
237
+ | M3 | Solver bridge + Turnstile | done |
238
+ | M4 | reCAPTCHA / hCaptcha / FunCaptcha / GeeTest | done |
239
+ | M5 | Production hardening (proxies, profiles, retries, multi-tab) | done |
240
+ | M5.5 | DX Tier S (auto-wait + ElementHandle + cookies + block_urls) | done |
241
+ | M5.5+ | Humanly mode | done |
242
+ | M5.5++ | WebRTC + toString camouflage + geo auto-couple | done |
243
+ | M5.5+++ | Mobile presets + expanded catalog | done |
244
+ | M5.6 | BrowserPool | done |
245
+ | M5.7 | Web Panel (+ FunSolver balance + per-browser logs + scripts) | done |
246
+ | M5.8 | Mini mode | done |
247
+ | M6 | **v0.1 release** | **in progress** |
248
+ | M10a | TLS HTTP client (curl_cffi) | done |
249
+ | M11-alt | ContextPool (lightweight pool) | done |
250
+ | M7 | Fingerprint consistency (Tier 3) | post-v0.1 |
251
+ | M8 | Real fingerprint pool (Tier 4) | post-v0.1 |
252
+ | M9 | Deep WebGL / canvas / shader spoofing | post-v0.1 |
253
+ | M10b | mitm proxy for Chrome traffic (production-grade) | post-v0.1 |
254
+ | M11 | Browser fork (Camoufox / Chromium) | post-v0.1 |
255
+ | M12 | Tauri UI for manual mode | post-v0.1 |
256
+
257
+ ## Development
258
+
259
+ Uses [uv](https://docs.astral.sh/uv/) for env + deps.
260
+
261
+ ```bash
262
+ uv sync # install
263
+ uv run pytest -q # full test suite (173 tests)
264
+ uv run ruff check . && uv run ruff format --check .
265
+ uv run mypy funbrowser
266
+ uv run python examples/detect_check.py
267
+ ```
268
+
269
+ ## Contributing
270
+
271
+ See [CONTRIBUTING.md](CONTRIBUTING.md). Issues + PRs welcome.
272
+
273
+ ## License
274
+
275
+ MIT. See [LICENSE](LICENSE).