Automation
How to solve CAPTCHAs in Selenium (Python)
CaptchaSonic Team
Automation & Web Scraping
If you automate with Selenium WebDriver in Python, a captcha on a login or checkout page usually stops your script cold. This guide shows the clean way past it: ask CaptchaSonic for a fresh token over gRPC and inject it into the page — no image tiles, no brittle screenshotting.
TIP
This is the token flow. CaptchaSonic solves the challenge server-side and returns a
g-recaptcha-response token you drop into the page. Your form submits as if a human passed.
Install
pip install captchasonic selenium
export CAPTCHASONIC_API_KEY=sonic_your_key_here # dashboard → API Keys
The core flow
Three steps: read the sitekey, solve, inject.
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
from captchasonic import CaptchaSonic
client = CaptchaSonic(os.environ["CAPTCHASONIC_API_KEY"])
driver = webdriver.Chrome()
driver.get("https://example.com/login")
# 1. Read the sitekey from the page.
sitekey = driver.find_element(By.CSS_SELECTOR, "[data-sitekey]").get_attribute("data-sitekey")
# 2. Solve over gRPC (auto-polls, returns when ready).
result = client.solve_recaptcha_v2_token(
website_url=driver.current_url,
website_key=sitekey,
)
token = result["solution"]["gRecaptchaResponse"]
# 3. Inject the token and submit.
driver.execute_script(
"document.getElementById('g-recaptcha-response').innerHTML = arguments[0];",
token,
)
driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
That's the entire integration. The SDK handles polling, retries, and error mapping, so your Selenium code stays about driving the page.
Handling the tricky cases
- Invisible reCAPTCHA / callback binding. Many sites don't submit the form directly —
they bind the token via a JavaScript callback (
data-callback="onCaptcha"). Call it with the token instead of writing the textarea:driver.execute_script("onCaptcha(arguments[0])", token). - Token freshness. reCAPTCHA tokens live ~120 seconds. Solve as late as possible — right before the click, not at the top of your script.
- Dynamic sitekeys. Read the sitekey from the live DOM at runtime instead of hard-coding it; it often changes between staging and production.
- IP-locked validation. If the target checks that the token was solved from the same IP that
submits it, pass a
proxy=argument so CaptchaSonic solves through your IP.
Beyond reCAPTCHA
The same client solves Cloudflare Turnstile, GeeTest, AWS WAF, and image captchas — just swap
the method (solve_turnstile_token, etc.). See the full list in the
Python SDK reference.
Next steps
- The step-by-step Selenium integration doc
- The ready-to-run selenium-python-solver example repo
- Create your first task if you'd rather call the REST API directly