mirror of
https://github.com/CloakHQ/CloakBrowser.git
synced 2026-06-23 11:41:46 +02:00
- Remove --enable-automation via ignore_default_args (matches agent-browser Playwright patch — fixes connectionRTT, enables --fingerprint-* flags) - Randomize fingerprint seed per launch (unique canvas/WebGL/audio per session) - Change default GPU to RTX 3070 (higher market share = better blending) - Rewrite stealth_test.py with JS evaluation for 6 detection sites - Add --proxy flag to test script for Helper VPS routing - All 6/6 tests passing (verified on VPS with v142 binary)
225 lines
6.7 KiB
Python
225 lines
6.7 KiB
Python
"""Core browser launch functions for cloakbrowser.
|
|
|
|
Provides launch() and launch_async() — thin wrappers around Playwright
|
|
that use our patched stealth Chromium binary instead of stock Chromium.
|
|
|
|
Usage:
|
|
from cloakbrowser import launch
|
|
|
|
browser = launch()
|
|
page = browser.new_page()
|
|
page.goto("https://protected-site.com")
|
|
browser.close()
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Any
|
|
|
|
from .config import get_default_stealth_args
|
|
from .download import ensure_binary
|
|
|
|
logger = logging.getLogger("cloakbrowser")
|
|
|
|
|
|
def launch(
|
|
headless: bool = True,
|
|
proxy: str | None = None,
|
|
args: list[str] | None = None,
|
|
stealth_args: bool = True,
|
|
**kwargs: Any,
|
|
) -> Any:
|
|
"""Launch stealth Chromium browser. Returns a Playwright Browser object.
|
|
|
|
Args:
|
|
headless: Run in headless mode (default True).
|
|
proxy: Proxy server URL (e.g. 'http://proxy:8080' or 'socks5://proxy:1080').
|
|
args: Additional Chromium CLI arguments to pass.
|
|
stealth_args: Include default stealth fingerprint args (default True).
|
|
Set to False if you want to pass your own --fingerprint flags.
|
|
**kwargs: Passed directly to playwright.chromium.launch().
|
|
|
|
Returns:
|
|
Playwright Browser object — use same API as playwright.chromium.launch().
|
|
|
|
Example:
|
|
>>> from cloakbrowser import launch
|
|
>>> browser = launch()
|
|
>>> page = browser.new_page()
|
|
>>> page.goto("https://bot.incolumitas.com")
|
|
>>> print(page.title())
|
|
>>> browser.close()
|
|
"""
|
|
from playwright.sync_api import sync_playwright
|
|
|
|
binary_path = ensure_binary()
|
|
chrome_args = _build_args(stealth_args, args)
|
|
|
|
logger.debug("Launching stealth Chromium (headless=%s, args=%d)", headless, len(chrome_args))
|
|
|
|
pw = sync_playwright().start()
|
|
browser = pw.chromium.launch(
|
|
executable_path=binary_path,
|
|
headless=headless,
|
|
args=chrome_args,
|
|
ignore_default_args=["--enable-automation"],
|
|
**_build_proxy_kwargs(proxy),
|
|
**kwargs,
|
|
)
|
|
|
|
# Patch close() to also stop the Playwright instance
|
|
_original_close = browser.close
|
|
|
|
def _close_with_cleanup() -> None:
|
|
_original_close()
|
|
pw.stop()
|
|
|
|
browser.close = _close_with_cleanup
|
|
|
|
return browser
|
|
|
|
|
|
async def launch_async(
|
|
headless: bool = True,
|
|
proxy: str | None = None,
|
|
args: list[str] | None = None,
|
|
stealth_args: bool = True,
|
|
**kwargs: Any,
|
|
) -> Any:
|
|
"""Async version of launch(). Returns a Playwright Browser object.
|
|
|
|
Args:
|
|
headless: Run in headless mode (default True).
|
|
proxy: Proxy server URL (e.g. 'http://proxy:8080' or 'socks5://proxy:1080').
|
|
args: Additional Chromium CLI arguments to pass.
|
|
stealth_args: Include default stealth fingerprint args (default True).
|
|
**kwargs: Passed directly to playwright.chromium.launch().
|
|
|
|
Returns:
|
|
Playwright Browser object (async API).
|
|
|
|
Example:
|
|
>>> import asyncio
|
|
>>> from cloakbrowser import launch_async
|
|
>>>
|
|
>>> async def main():
|
|
... browser = await launch_async()
|
|
... page = await browser.new_page()
|
|
... await page.goto("https://bot.incolumitas.com")
|
|
... print(await page.title())
|
|
... await browser.close()
|
|
>>>
|
|
>>> asyncio.run(main())
|
|
"""
|
|
from playwright.async_api import async_playwright
|
|
|
|
binary_path = ensure_binary()
|
|
chrome_args = _build_args(stealth_args, args)
|
|
|
|
logger.debug("Launching stealth Chromium async (headless=%s, args=%d)", headless, len(chrome_args))
|
|
|
|
pw = await async_playwright().start()
|
|
browser = await pw.chromium.launch(
|
|
executable_path=binary_path,
|
|
headless=headless,
|
|
args=chrome_args,
|
|
ignore_default_args=["--enable-automation"],
|
|
**_build_proxy_kwargs(proxy),
|
|
**kwargs,
|
|
)
|
|
|
|
# Patch close() to also stop the Playwright instance
|
|
_original_close = browser.close
|
|
|
|
async def _close_with_cleanup() -> None:
|
|
await _original_close()
|
|
await pw.stop()
|
|
|
|
browser.close = _close_with_cleanup
|
|
|
|
return browser
|
|
|
|
|
|
def launch_context(
|
|
headless: bool = True,
|
|
proxy: str | None = None,
|
|
args: list[str] | None = None,
|
|
stealth_args: bool = True,
|
|
user_agent: str | None = None,
|
|
viewport: dict | None = None,
|
|
locale: str | None = None,
|
|
timezone_id: str | None = None,
|
|
**kwargs: Any,
|
|
) -> Any:
|
|
"""Launch stealth browser and return a BrowserContext with common options pre-set.
|
|
|
|
Convenience function that creates a browser + context in one call.
|
|
Useful for setting user agent, viewport, locale, etc.
|
|
|
|
Args:
|
|
headless: Run in headless mode (default True).
|
|
proxy: Proxy server URL.
|
|
args: Additional Chromium CLI arguments.
|
|
stealth_args: Include default stealth fingerprint args (default True).
|
|
user_agent: Custom user agent string.
|
|
viewport: Viewport size dict, e.g. {"width": 1920, "height": 1080}.
|
|
locale: Browser locale, e.g. "en-US".
|
|
timezone_id: Timezone, e.g. "America/New_York".
|
|
**kwargs: Passed to browser.new_context().
|
|
|
|
Returns:
|
|
Playwright BrowserContext object.
|
|
"""
|
|
browser = launch(headless=headless, proxy=proxy, args=args, stealth_args=stealth_args)
|
|
|
|
context_kwargs: dict[str, Any] = {}
|
|
if user_agent:
|
|
context_kwargs["user_agent"] = user_agent
|
|
if viewport:
|
|
context_kwargs["viewport"] = viewport
|
|
if locale:
|
|
context_kwargs["locale"] = locale
|
|
if timezone_id:
|
|
context_kwargs["timezone_id"] = timezone_id
|
|
context_kwargs.update(kwargs)
|
|
|
|
try:
|
|
context = browser.new_context(**context_kwargs)
|
|
except Exception:
|
|
browser.close()
|
|
raise
|
|
|
|
# Patch close() to also close the browser (and its Playwright instance)
|
|
_original_ctx_close = context.close
|
|
|
|
def _close_context_with_cleanup() -> None:
|
|
_original_ctx_close()
|
|
browser.close()
|
|
|
|
context.close = _close_context_with_cleanup
|
|
|
|
return context
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Internal helpers
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def _build_args(stealth_args: bool, extra_args: list[str] | None) -> list[str]:
|
|
"""Combine stealth args with user-provided args."""
|
|
result = []
|
|
if stealth_args:
|
|
result.extend(get_default_stealth_args())
|
|
if extra_args:
|
|
result.extend(extra_args)
|
|
return result
|
|
|
|
|
|
def _build_proxy_kwargs(proxy: str | None) -> dict[str, Any]:
|
|
"""Build proxy kwargs for Playwright launch."""
|
|
if proxy is None:
|
|
return {}
|
|
return {"proxy": {"server": proxy}}
|