SeleniumBase: UC Mode, CDP Mode, proxies and hCaptcha.

SeleniumBase is a Python framework built on Selenium, with a pytest plugin and two modes aimed at bot detection. How to install it, write a first script, use UC Mode, CDP Mode and a proxy with a login, what its CAPTCHA helpers cover, and how to get an hCaptcha token into a SeleniumBase run.

What SeleniumBase is

Its PyPI summary reads: “SeleniumBase is a framework for web crawling, scraping, and testing. Supports pytest. CDP Mode adds stealth. Includes many tools.” In practice it wraps Selenium in shorter calls such as sb.type() and sb.assert_text() (the README says the assert methods “wait up to 7 seconds for the expected condition”), downloads the driver for you, and runs scripts either on their own or as pytest tests. The GitHub repository also ships a CLI and an MCP server.

SeleniumBase at a glance (read from PyPI and GitHub on 2 November 2026)
PackageMaintainerLatest versionLicence and requirements
seleniumbase (PyPI)Michael Mintz, mdmintz on GitHub4.56.5, released 29 October 2026MIT. Python 3.10+. Installs Selenium 4.51.0 and pytest

On GitHub since 2014, it is actively maintained: 98 releases so far in 2026, nine of them in October. Its issue tracker is open (14 open issues and 13,222 stars when we looked). Nearly every commit is Michael Mintz’s: 10,394 of them, against five for the next contributor.

Install it

Shell · pip
pip install seleniumbase

The install pulls in a pinned Selenium (4.51.0 for SeleniumBase 4.56.5) and pytest. The browser is not included. Google Chrome is the default, and the README says “Only unbranded Chromium and Chrome-for-Testing get downloaded automatically if not already present on the system.” The driver is downloaded for you: on our first run with Chrome 156.0.8078.79 it printed Getting chromedriver 156.0.8078.80 and saved it inside the package folder.

Quick start: the SB() context manager

SB() opens a browser, hands you an sb object with every SeleniumBase method, and closes the browser when the block ends:

Python · SB() quick start
from seleniumbase import SB

with SB(headless=True) as sb:
    sb.open("https://seleniumbase.io/demo_page")
    sb.assert_text("Demo Page", "h1")
    print(sb.get_title())

We ran it on 2 November 2026 with SeleniumBase 4.56.5, Python 3.13 and Chrome 156 on macOS; it printed Web Testing Page. Drop headless=True to watch the browser. In this default mode SeleniumBase is ordinary Selenium underneath: navigator.webdriver read true and the headless user agent said HeadlessChrome.

The same test with BaseCase and pytest

For test suites, subclass BaseCase and run the file with pytest. The BaseCase.main() line also lets you run it with plain python:

Python · BaseCase with pytest
from seleniumbase import BaseCase
BaseCase.main(__name__, __file__)


class ExampleTest(BaseCase):
    def test_example(self):
        self.open("https://seleniumbase.io/demo_page")
        self.assert_text("Demo Page", "h1")
Shell · run it headless
pytest test_example.py --headless

It passed in our run. Options such as --headless, --uc and --proxy= go on the pytest command line; in SB() they are keyword arguments.

UC Mode

The UC Mode docs say it “makes bots appear human, which lets them evade detection from anti-bot services that try to block them or trigger CAPTCHAs on various websites”. It “was originally based on undetected-chromedriver” and adds “improved stealth, better reliability, automatic driver downloads, and special methods for bypassing CAPTCHAs.” You turn it on with uc=True, or --uc under pytest:

Python · UC Mode
from seleniumbase import SB

with SB(uc=True) as sb:
    sb.goto("https://seleniumbase.io/demo_page")
    print(sb.execute_script("return navigator.webdriver"))   # False
    sb.solve_captcha()   # does nothing if there is no CAPTCHA

Run headless, this printed False, and the user agent had no HeadlessChrome in it. One behaviour to know about: in 4.56.5, opening a URL from UC Mode switches the session into CDP Mode, and WebDriver is disconnected afterwards (sb.is_connected() returned False). The source logs “Opening a URL from UC Mode now activates CDP Mode. To prevent this, call sb.driver.get(url) instead.”

The docs also warn that “UC Mode may be detectable in headless mode” and that “pyautogui doesn’t work in headless mode”, which rules out the uc_gui_* helpers there. On Linux servers they recommend xvfb=True, a virtual display, instead of headless.

CDP Mode

The CDP Mode docs describe it as “a stealth mode that uses the Chrome Devtools Protocol” and set out the difference: UC Mode’s stealth “is based on a modified chromedriver” that disconnects and reconnects WebDriver “at strategic times”, while CDP Mode “uses the Chrome DevTools Protocol directly, which is much better at avoiding bot-detection.” The UC Mode page points to CDP Mode as its successor. You reach it from UC Mode (as above, or with sb.activate_cdp_mode(url)), or start it on its own as Pure CDP Mode, with no WebDriver at all:

Python · Pure CDP Mode
from seleniumbase import sb_cdp

sb = sb_cdp.Chrome()
sb.goto("https://seleniumbase.io/demo_page")
print(sb.get_title())
print(sb.evaluate("navigator.webdriver"))   # False
sb.quit()

Headless, this printed the page title and False. Pure CDP Mode has its own, smaller set of methods (goto, click, type, evaluate, solve_captcha and more), listed in the CDP Mode docs.

Use a proxy, with or without a login

SeleniumBase takes the proxy as one string, host:port or user:pass@host:port, and its docs list SOCKS4 and SOCKS5 proxies as well:

Python · proxy with a login
from seleniumbase import SB

with SB(uc=True, proxy="user:pass@host:port") as sb:
    sb.goto("https://your-site.example/")

Pure CDP Mode takes the same argument (sb_cdp.Chrome(proxy=...)), and under pytest it goes on the command line:

Shell · proxy on the command line
pytest test_example.py --proxy=user:pass@host:port
pytest test_example.py --proxy="socks5://host:port"

We checked the login part against a local test proxy that answered 407 to any request without credentials. In plain mode, in UC Mode and in Pure CDP Mode, Chrome sent the username and password on the retry and the page loaded through the proxy. That is the main practical difference from undetected-chromedriver, whose Chrome flag has no place for a login. The docs mark authenticated proxies as “Chromium only”.

What its CAPTCHA helpers cover

SeleniumBase advertises CAPTCHA handling. Its README says CDP Mode “makes browser automation undetectable to anti-bot services” and “includes code for bypassing CAPTCHAs”, and that one example script “bypasses BrowserScan, Sannysoft, and Cloudflare bot-detection”. The screenshots under those examples show Cloudflare Turnstile, and the docs also include an invisible reCAPTCHA example. These are SeleniumBase’s claims; we did not test them against Cloudflare or reCAPTCHA.

The helpers themselves are described like this:

  • sb.solve_captcha() “handles CAPTCHAs that aren’t bypassed automatically. (If called when there’s no CAPTCHA on the page, then nothing happens / no-op.)” The CDP Mode method list adds “Uses CDP to click a CAPTCHA”.
  • UC Mode’s uc_gui_click_captcha() and uc_gui_handle_captcha() come with Cloudflare and reCAPTCHA variants (uc_gui_click_cf, uc_gui_click_rc). The docs say they “require pyautogui”, which needs a display; we did not run them, because we run browsers headless only.

None of the docs we read names hCaptcha. The 4.56.5 source goes slightly further than the docs: solve_captcha() also looks for an hCaptcha iframe and clicks its checkbox. On hCaptcha’s test sitekey, which passes any click by design, that click filled the response field with the test key’s dummy token in our headless run. That shows the click lands. It says nothing about a live sitekey, where hCaptcha decides after the click whether to show an image challenge. solve_captcha() stops at the click, has no code for an image challenge, and returns nothing you could pass on as a token.

Where NoneCap fits

When a page in your SeleniumBase run has hCaptcha, its form only goes through with a valid token in the h-captcha-response field, a P1_ string the site’s server checks with hCaptcha. NoneCap is an hCaptcha solving API that returns that token. Send it the page’s sitekey and url; with the Python SDK (pip install nonecap), nc.solve() waits for the result, so there is no polling loop:

Python · get an hCaptcha token
import json
import os

from nonecap import NoneCap

nc = NoneCap(api_key=os.environ["NONECAP_KEY"])


def get_token(sb):
    solve = nc.solve(
        type="hcaptcha",
        sitekey=sb.get_attribute("[data-sitekey]", "data-sitekey"),
        url=sb.get_current_url(),
        user_agent=sb.get_user_agent(),
    )
    return solve.token

Then put the token in the form, call the widget’s callback if the page set one, and submit:

Python · fill the token, submit
from seleniumbase import SB

FILL_TOKEN = """(() => {
  const token = %s;
  for (const name of ["h-captcha-response", "g-recaptcha-response"]) {
    const el = document.querySelector(`textarea[name="${name}"]`);
    if (el) el.value = token;
  }
  const cb = document.querySelector("[data-callback]")?.getAttribute("data-callback");
  if (cb && typeof window[cb] === "function") window[cb](token);
})()"""

with SB(uc=True) as sb:
    sb.goto("https://your-site.example/signup")
    token = get_token(sb)
    sb.execute_script(FILL_TOKEN % json.dumps(token))
    sb.click("button[type=submit]")

The token goes into the script with json.dumps because, once UC Mode has switched to CDP Mode, execute_script takes a single expression: passing the token as an extra argument raised an error in our run. The same call works in plain mode, UC Mode and Pure CDP Mode (there, sb.evaluate). We ran both blocks headless against a local test page with a fake token in place of the NoneCap call: the callback fired and the form posted the token in both h-captcha-response and g-recaptcha-response.

Sending the browser’s own user_agent is optional; some sites need it for the token to be accepted. If your browser goes through a proxy, you can pass the same one to nc.solve() as proxy (http://user:pass@host:port) so the token and the form come from the same IP address. Failed, cancelled and expired solves are never charged.

The Selenium guide covers sitekeys that are not in the DOM, invisible and enterprise (rqdata) sitekeys, and the error types the SDK raises. Every field and status is in the API reference. NoneCap solves hCaptcha only; it does not help with reCAPTCHA, Turnstile or other CAPTCHAs.

Solve hCaptcha in Selenium →

Last updated November 2026.

Frequently asked

What is SeleniumBase?
A Python framework for browser automation, scraping and testing, written by Michael Mintz and licensed MIT. Its PyPI summary calls it “a framework for web crawling, scraping, and testing”. It wraps Selenium with shorter methods, a pytest plugin and its own driver downloads, and adds two modes aimed at bot detection: UC Mode and CDP Mode.
How do I install SeleniumBase?
pip install seleniumbase on Python 3.10 or newer. It brings Selenium and pytest with it and downloads a matching ChromeDriver the first time you run a script. It uses the Google Chrome already on your machine.
What is the difference between UC Mode and CDP Mode?
In SeleniumBase’s words, UC Mode’s stealth “is based on a modified chromedriver” that disconnects and reconnects WebDriver “at strategic times”, while CDP Mode “uses the Chrome DevTools Protocol directly”. The UC Mode docs call CDP Mode its successor. In 4.56.5, opening a URL from UC Mode switches the session into CDP Mode. Pure CDP Mode (sb_cdp.Chrome()) skips WebDriver altogether.
How do I use a proxy with SeleniumBase?
Pass it when you start the browser: SB(uc=True, proxy="user:pass@host:port"), sb_cdp.Chrome(proxy="user:pass@host:port"), or --proxy= on the pytest command line. A username and password are supported. In our test against a local proxy that demanded a login, all three sent the credentials and loaded the page.
Does SeleniumBase solve hCaptcha?
Its documentation does not say so. The docs describe solve_captcha() as handling “CAPTCHAs that aren’t bypassed automatically”, and their examples are Cloudflare Turnstile and reCAPTCHA. The 4.56.5 source also clicks an hCaptcha checkbox. It has nothing for the image challenge hCaptcha can show after that click, and it does not hand you a token. When a site asks for one, NoneCap returns it.
Does SeleniumBase bypass Cloudflare?
Its README says an example script in CDP Mode “bypasses BrowserScan, Sannysoft, and Cloudflare bot-detection”, and captions a screenshot “Cloudflare Turnstile bypassed successfully”. Those are SeleniumBase’s own claims; we did not test them. NoneCap does not help with Cloudflare: it solves hCaptcha only.
Does UC Mode work headless?
It starts, and in our headless run navigator.webdriver read false and the user agent had no HeadlessChrome. The docs warn that “UC Mode may be detectable in headless mode” and that the PyAutoGUI-based methods, such as uc_gui_click_captcha(), need a display. On Linux servers they recommend xvfb=True instead of headless.
Is it allowed to use SeleniumBase and a solver on a site?
That depends on the site and on what you do there. Automate where you are allowed to: your own sites, your tests, and services whose terms permit it. NoneCap’s terms rule out fraud, credential stuffing, spam and unauthorised access. This is not legal advice.

Start solving hCaptcha in minutes.

1,300 free credits on signup. Pay per solve, credits never expire, failed solves never charged.