
Handling bot detection with SB Stealth Wrapper
It happened again. My script was perfect locally. I pushed it to CI, and... `403 Forbidden`. I wasn't testing a bank; I was testing a landing page. The modern web has become hostile to automation.
Developers are tired of getting blocked by 403 Forbidden errors, Cloudflare Turnstiles, and "Verify you are human" loops when using Selenium or Playwright. We spend more time fighting bot detection than writing actual tests.
The Old Way (The Struggle)
We've all been there. You try to make Selenium 'stealthy' by piling on options, changing user agents, and praying.
# The "Please don't ban me" starter pack
options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_argument("user-agent=Mozilla/5.0...")
# ... 20 more lines of hoping it works
driver = webdriver.Chrome(options=options)
# Result: Still blocked.The New Way (The 4-Line Fix)
I built **sb-stealth-wrapper** to solve this once and for all. It wraps SeleniumBase's UC Mode with intelligent defaults that just work.
from sb_stealth_wrapper import StealthBot
# 1. Initialize with one line (Auto-handles Linux/Xvfb)
with StealthBot(headless=True) as bot:
# 2. Navigate safely
bot.safe_get("https://nowsecure.nl")
# 3. Interact like a human
bot.smart_click("#verify")The Secret Sauce: Why it Works
1. The Linux/Xvfb Hack
Headless Chrome on Linux is a dead giveaway. It screams 'I am a bot' because it lacks a display server. My wrapper detects if it's running on Linux and automatically spawns a virtual display (Xvfb). This means Chrome *thinks* it has a screen, giving you the stealth of a headed browser with the convenience of a headless server.
2. Heuristic Clicking
`bot.click()` is too perfect. It's instantaneous and mechanical. `smart_click()` is different. It scrolls the element into view, hovers for a split second, and then clicks. If the element is obscured (a common anti-bot tactic), it intelligently falls back to a JavaScript click. It feels human.
Benchmark Results
I ran a comparison against standard Selenium and Playwright on a tough bot challenge (NowSecure). The results speak for themselves.
Run python examples/benchmark_comparison.py
=== Starting Benchmark Comparison ===
Target: https://nowsecure.nl
Timeout: 15s
[Benchmark] Running Standard Selenium (Chrome)...
[Result] Selenium: FAIL (0.50s) - Message: session not created: Chrome instance exited. Examine ChromeDriver verbose log to determine ...
[Benchmark] Running Playwright (Chromium)...
[Result] Playwright: FAIL (0.36s) - BrowserType.launch: Target page, context or browser has been closed
Browser logs:
βββββββββββββββββ...
[Benchmark] Running StealthBot...
[StealthBot] Linux detected. Enabling Xvfb and disabling native headless mode for stealth.
[StealthBot] Navigating to https://nowsecure.nl...
[StealthBot] Waiting for page content...
[StealthBot] Challenge passed!
-> navigator.webdriver: False
[Result] StealthBot: PASS (3.65s)
========================================
Tool | Status | Time
----------------------------------------
Selenium | FAIL | 0.50s
Playwright | FAIL | 0.36s
StealthBot | PASS (Bot Detected: False) | 3.65s
========================================Put This to Test Now
You don't need complex error handling to see the magic. Here is the raw proof.
We will run this in headless=True (which usually fails instantly) against NowSecure (a tough bot challenge).
from sb_stealth_wrapper import StealthBot
if __name__ == "__main__":
# 1. Initialize (Auto-handles Xvfb/Headless)
with StealthBot(headless=True) as bot:
print("--- Testing Protected Site (nowsecure.nl) ---")
bot.safe_get("https://nowsecure.nl")
# 2. Verify we passed the challenge
try:
# We wait for the success header (Note: The text changed from "OH YEAH" recently)
bot.sb.wait_for_text("NOWSECURE", "h1", timeout=30)
print("β
SUCCESS: Bypassed Cloudflare/Turnstile!")
bot.save_screenshot("success_proof")
except Exception as e:
print(f"β FAILURE: Detection triggered. Error: {e}")
# 3. Auto-Debug (Saves HTML so you can see why it failed)
with open("debug_failure.html", "w", encoding="utf-8") as f:
f.write(bot.sb.get_page_source())
print("Dumped page source to debug_failure.html")
print("Test Complete.")That is it. If you want the robust, production-ready version with error handling and HTML debugging, check out the full example on GitHub:
Get It Now
Stop writing boilerplate. Start writing tests.
pip install sb-stealth-wrapperCredits
This project stands on the shoulders of giants. A massive shoutout to the **SeleniumBase** team for their incredible work on UC Mode. `sb-stealth-wrapper` is essentially a love letter to their engineering, wrapping it in a way that makes it even more accessible for specific use cases.
**Ethical Disclaimer**: This tool is for educational purposes and for testing environments you own. Do not use it for unauthorized scraping or bypassing security controls on websites you do not have permission to test.
