Skip to main content

Undetected Chrome browser driver with proxy support and captcha solving.

Project description

rtfox-browser

Undetected Chrome browser driver with SOCKS5 proxy, captcha solving and multiprocessing support.

Cloudflare bypass


Based on

This project is a fork of undetected-chromedriver by @UltrafunkAmsterdam.

We took the core Chrome driver stealth patching logic as a base and extended it with:

  • SOCKS5 proxy support with authentication
  • Built-in captcha solving module with plugin API
  • Multiprocessing isolation (per-worker profiles and binaries)
  • On-the-fly proxy replacement without browser restart
  • Structured logging via loguru
  • Improved cleanup and shutdown handling

Original project is licensed under GPL-3.0 — this fork inherits the same license.


Features

  • 🛡️ Bypasses CloudFlare / hCaptcha / Imperva detection out of the box
  • 🔒 SOCKS5 / HTTP / HTTPS proxy support with authentication
  • 🔄 On-the-fly proxy replacement via proxy_replacement() — no restart needed
  • 🧩 Built-in captcha solving module (2 solvers included)
  • ⚙️ Custom captcha solver API — share your own solvers
  • 🚀 Multiprocessing support
  • 🖥️ Cross-platform: Linux, macOS, Windows

Installation

pip install rtfox-browser

Quick start

import rtfox_browser as uc

driver = uc.Chrome()
driver.get("https://example.com")
driver.quit()

Proxy

SOCKS5 with authentication

driver = uc.Chrome(
    proxy={
        "host": "1.2.3.4",
        "port": 1080,
        "type": "socks5",
        "user": "username",
        "pass": "password",
    }
)

HTTP proxy (no auth)

driver = uc.Chrome(
    proxy={
        "host": "1.2.3.4",
        "port": 8080,
        "type": "http",
    }
)

Named keyword arguments (alternative style)

from rtfox_browser.proxy_types import ProxyType

driver = uc.Chrome(
    proxy_host="1.2.3.4",
    proxy_port=1080,
    proxy_type=ProxyType.SOCKS5,
    proxy_user="username",
    proxy_pass="password",
)

Proxy exceptions

Exception Cause
ProxyError Base class for all proxy errors
ProxyConnectionError Failed to connect to proxy (invalid host/port)
ProxyAuthError Wrong login or password
ProxyTimeoutError Proxy does not respond within timeout
ProxyInvalidAddressError Malformed host or port format
ProxyConfigError Missing or invalid proxy configuration fields
from rtfox_browser.exceptions import (
    ProxyError,
    ProxyConnectionError,
    ProxyAuthError,
    ProxyTimeoutError,
    ProxyInvalidAddressError,
    ProxyConfigError,
)

try:
    driver = uc.Chrome(proxy={
        "host": "1.2.3.4",
        "port": 1080,
        "type": "socks5",
        "user": "username",
        "pass": "password",
    })
except ProxyConfigError:
    print("Invalid or incomplete proxy config")
except ProxyInvalidAddressError:
    print("Malformed host or port")
except ProxyAuthError:
    print("Wrong credentials")
except ProxyTimeoutError:
    print("Proxy timed out")
except ProxyConnectionError:
    print("Could not connect to proxy")
except ProxyError:
    print("General proxy failure")

On-the-fly proxy replacement

Replace the active proxy at any time without restarting Chrome. A local transparent tunnel is always running, so switching works even on sessions started without a proxy.

driver = uc.Chrome()

# Switch to a new proxy
driver.proxy_replacement({
    "host": "5.6.7.8",
    "port": 1080,
    "type": "socks5",
    "user": "alice",
    "pass": "secret",
})

# Switch to direct connection (no proxy)
driver.proxy_replacement(None)

# Named-argument style
driver.proxy_replacement(
    host="5.6.7.8",
    port=1080,
    proxy_type="socks5",
    user="alice",
    password="secret",
)

By default proxy_replacement() clears browser cache and cookies after switching so Chrome opens fresh connections through the new proxy. Pass clear_connections=False to skip this step.


Multiprocessing

Multiprocessing

Each worker gets its own isolated Chrome profile and chromedriver binary.

worker_id is optional — if omitted, a random UUID is assigned automatically. Pass it explicitly only if you want predictable names in logs or file paths.

from multiprocessing import Pool
import rtfox_browser as uc

def run_worker(worker_id):
    driver = uc.Chrome(worker_id=worker_id)
    driver.get("https://example.com")
    driver.quit()

with Pool(4) as pool:
    pool.map(run_worker, ["w1", "w2", "w3", "w4"])

Without explicit worker_id:

def run_worker(_):
    driver = uc.Chrome()  # worker_id auto-assigned as UUID
    driver.get("https://example.com")
    driver.quit()

with Pool(4) as pool:
    pool.map(run_worker, range(4))

Captcha solving

rtfox-browser includes a captcha module with 2 built-in solvers. Solvers are loaded automatically from a solvers/ directory in your working directory.

Setup

from rtfox_browser.captcha import CaptchaService

driver = uc.Chrome()
captcha = CaptchaService(api_key="YOUR_2CAPTCHA_KEY", driver=driver)

# Check available solvers
print(captcha.available())
# ['ebay_hcaptcha', 'aws_image']

Solve a captcha

driver.get("https://example.com")
captcha.ebay_hcaptcha()

Custom solvers directory

captcha = CaptchaService(
    api_key="YOUR_KEY",
    driver=driver,
    solvers_dir="/path/to/your/solvers",
)

Creating your own captcha solver

Drop a file into the solvers/ folder — it will be picked up automatically. No registration needed.

1. Create solvers/my_solver.py:

from rtfox_browser.captcha import BaseCaptchaSolver

class MySolver(BaseCaptchaSolver):
    name = "my_captcha"  # becomes the method name on CaptchaService

    def solve(self, **kwargs) -> bool:
        driver = self.driver      # Selenium WebDriver
        api_key = self.api_key    # 2captcha API key

        # your solving logic here
        ...
        return True  # True = solved, False = failed

2. Use it:

captcha = CaptchaService(api_key="KEY", driver=driver)
captcha.my_captcha()

3. Or register manually at runtime:

captcha.register(MySolver)
captcha.my_captcha()

BaseCaptchaSolver API

Property Type Description
name str Method name exposed on CaptchaService
self.driver WebDriver The active browser instance
self.api_key str API key passed to CaptchaService
solve(**kwargs) bool Your solving logic, return True on success

ProxyConfig reference

You can construct proxy config directly using ProxyConfig:

from rtfox_browser.proxy_types import ProxyConfig, ProxyType

# From a dict
config = ProxyConfig.from_dict({
    "host": "1.2.3.4",
    "port": 8080,
    "type": "socks5",
    "user": "alice",
    "pass": "secret",
})

# From named arguments
config = ProxyConfig.from_args(
    host="1.2.3.4",
    port=8080,
    proxy_type=ProxyType.SOCKS5,
    user="alice",
    password="secret",
)

# Pass directly to Chrome
driver = uc.Chrome(proxy=config)

# Or use for proxy_replacement
driver.proxy_replacement(config)

Supported proxy types: socks5, http, https.


Cross-platform support

OS Supported
Linux
macOS
Windows

Community

💬 Telegram: @rtf_labs_studio 🎥 YouTube: RTF Labs Studio


License

GPL-3.0 © rtf-labs-studio

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rtfox_browser-0.0.2.tar.gz (36.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rtfox_browser-0.0.2-py3-none-any.whl (37.9 kB view details)

Uploaded Python 3

File details

Details for the file rtfox_browser-0.0.2.tar.gz.

File metadata

  • Download URL: rtfox_browser-0.0.2.tar.gz
  • Upload date:
  • Size: 36.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for rtfox_browser-0.0.2.tar.gz
Algorithm Hash digest
SHA256 17724e76c9e389774949994dc06c68eb20f5497c2677f74757f71a92d27cc9e4
MD5 abf984374c719ca58b293298bf4c9bfc
BLAKE2b-256 9ac03bde1507cf604a6de234b3ead21e9f85254c0fbf1e1ff4174dc16abaad72

See more details on using hashes here.

File details

Details for the file rtfox_browser-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: rtfox_browser-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 37.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for rtfox_browser-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 60b0f8dc981dae6665440b00e2636d5620dbb3c12942459008aa3b10881e1aa3
MD5 893627d6346875e62a4bb376c41b2fc5
BLAKE2b-256 5f47967e81278bf3e867a0e8937e5a44039be2e244e545f5fe78a43528550e8f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page