SB Stealth Wrapper
A small reliability wrapper around SeleniumBase UC Mode for authorized browser testing on applications that use modern bot defenses.
SB Stealth Wrapper standardizes browser setup, bounded challenge recovery, explicit failure behavior, fallback clicks, screenshots, and variable input timing. It does not guarantee that a site will accept automated traffic, solve every challenge, or make automation undetectable.
Install
python -m pip install sb-stealth-wrapper
Python 3.9 or newer is required. On Linux, headless=True runs without a virtual display;
headed execution (headless=False) requires xvfb:
sudo apt-get install xvfb
Quick start
from sb_stealth_wrapper import StealthBot
with StealthBot(headless=False) as bot:
bot.safe_get("https://test.example.com/login")
bot.smart_click("#login-button")
bot.sb.wait_for_text("Dashboard", timeout=15)
bot.save_screenshot("after-login")
Use the package only on systems you own or have explicit permission to test.
Failure contract
safe_get() returns only after one of these conditions is proven:
- the configured
success_criteriatext is visible; or - no challenge is detected and no explicit success criterion was requested.
After three unsuccessful challenge-recovery attempts it performs one final state read and raises ChallengeNotSolvedError only if the challenge remains. When a page has no challenge but configured text remains absent after four bounded checks, it raises SuccessCriteriaNotMetError.
success_criteria applies to the current navigation outcome. Do not configure text that can appear only after a future click; verify post-click state explicitly as shown above.
smart_click() attempts:
- the configured input strategy;
- a standard SeleniumBase click;
- a JavaScript click;
- bounded challenge recovery and one final standard click.
If those attempts fail, it raises StealthBotError instead of silently continuing.
API
StealthBot(
headless=False,
proxy=None,
screenshot_path="debug_screenshots",
success_criteria=None,
driver_strategy=None,
input_strategy=None,
evasion_strategy=None,
)
safe_get(url)
Navigates to a URL, waits for the document body, checks known challenge indicators, and enforces the failure contract above.
smart_click(selector)
Uses variable pre-click timing and SeleniumBase UC click behavior, then bounded fallbacks. The package does not claim Bezier mouse movement.
smart_type(selector, text)
Types with variable delays. The default strategy may insert and immediately correct an occasional typo.
save_screenshot(name)
Writes <name>.png under screenshot_path and returns the resulting path. name must be a
plain filename stem, not a path; path separators are rejected.
Strategies
The strategy interfaces remain injectable for application-specific testing:
from sb_stealth_wrapper import StealthBot
from sb_stealth_wrapper.strategies.input import StandardInputStrategy
with StealthBot(input_strategy=StandardInputStrategy()) as bot:
bot.safe_get("https://test.example.com")
Fingerprint mutation is disabled by default in 0.5.0. CanvasPoisoningStrategy and AudioContextNoiseStrategy remain experimental opt-in components; they do not promise stable or undetectable fingerprints.
Testing policy
Deterministic unit tests and package builds run in required CI. Third-party anti-bot pages are unsuitable as release gates because their behavior can change independently of this package. Live checks belong in explicitly authorized manual testing, with real assertions and non-zero failure exits.
Limitations
- Bot-defense behavior varies by site, IP reputation, browser version, and policy.
- Challenge detection is keyword-based and can produce false positives or false negatives.
- The package does not bypass authorization, rate limits, access controls, or a site's terms.
headless=Falsegenerally offers behavior closer to an interactive browser; it is not a guarantee of acceptance.
Development
python -m pip install -c requirements-ci.txt -e ".[dev]" build twine
python -m pytest -q
python -m black --fast --check sb_stealth_wrapper tests examples
python -m isort --check-only sb_stealth_wrapper tests examples
python -m mypy sb_stealth_wrapper
python -m compileall -q sb_stealth_wrapper tests
python -m build
python -m twine check dist/*
Set PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 when you want the same isolated pytest-plugin behavior
used by CI.
License and responsible use
MIT. Created by Dhiraj Das and built on SeleniumBase.
Use only for legitimate QA, resilience testing, and automation on systems you are authorized to test. Do not use it for unauthorized scraping or to evade security controls on third-party services.
Metadata
Release files for sb-stealth-wrapper 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sb_stealth_wrapper-0.5.0.tar.gz | 15.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sb_stealth_wrapper-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.0 kB
Release files / sb_stealth_wrapper-0.5.0.tar.gz
| Download URL | sb_stealth_wrapper-0.5.0.tar.gz |
|---|---|
| Size | 15.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8c686e5f1cb5d8ab749bf0713b23294fab1fff39294735925a3a6d4a6a706cce
|
|
BLAKE2b-256 checksum How to use checksums |
f0e5828238240dacb886bf7128f70995740110d0dea6c69bb64c35cb594f2843
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|
Release files / sb_stealth_wrapper-0.5.0-py3-none-any.whl
| Download URL | sb_stealth_wrapper-0.5.0-py3-none-any.whl |
|---|---|
| Size | 11.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4c16523308fc40f50b2250433ed647487b6506d9e4ab547449df55ecb4370fe5
|
|
BLAKE2b-256 checksum How to use checksums |
218deef3643b7ddf1dc582c00073e90cc183e597a1cbc4782c6e5611895e94e3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|