If your Selenium script keeps hitting Google's "I'm not a robot" box, you already know the pain: the automation runs fine until a reCAPTCHA widget stops it dead. This guide shows the approach that actually works in 2026 — not clicking image tiles at random, but fetching a valid reCAPTCHA token from a captcha-solving API and submitting it with the form.
We'll cover how reCAPTCHA decides you're a bot, why the old "brute-force the picture puzzle" trick is long dead, and then walk through a complete Python + Selenium example that detects the widget, requests a token, injects it, and submits.
A quick, honest disclaimer: solving CAPTCHAs to automate a site can violate that site's terms of service. Do it on properties you own or are authorized to test, respect
robots.txtand rate limits, and never use these techniques for fraud or account abuse.
How reCAPTCHA works in 2026
Google's reCAPTCHA stopped being a "read the squiggly text" test years ago. Modern versions are a risk-analysis engine: the JavaScript widget quietly measures how you behave and scores how human you look, long before you ever click anything.
There are three variants you'll meet in the wild:
- reCAPTCHA v2 ("I'm not a robot" checkbox). The classic widget. When you tick the box, the script has already been recording mouse movement, timing, scrolls, and browser fingerprint. If the risk score is high enough, you pass instantly. If not, it escalates to an image challenge (the 3×3 or 4×4 "select all buses" grid).
- reCAPTCHA v2 invisible. Same engine, no visible checkbox — it fires on a button click or form submit and only shows a challenge when suspicious.
- reCAPTCHA v3. No challenge at all. It returns a score from 0.0 to 1.0 (1.0 = very likely human) plus an
actionname, and the site decides what to do with low scores — block, throttle, or add step-up verification. - reCAPTCHA Enterprise. A paid, hardened version of the same scoring model with extra signals, common on banking, ticketing, and large e-commerce sites.
What the widget is actually measuring
The behavioral signals that feed the score are the same ones that have quietly powered reCAPTCHA since the "No CAPTCHA" rework:
- mouse movement — how smooth, straight, or jittery the path is;
- page scrolls and the timing between browser events;
- keystroke cadence;
- click-location history tied to a browser fingerprint;
- cookies and prior reputation for your IP and browser.
All of this is bundled, encrypted, and sent to Google's servers. The site never sees the raw signals — it only receives a token (the field named g-recaptcha-response), which it forwards to Google's siteverify endpoint with its secret key to confirm whether you passed. That token is the whole game: if you can produce a valid one, the form goes through.
Why the old brute-force trick is dead
The original 2015-era hack was to randomly click tiles in the image grid and resubmit, betting on the ~2–3% odds of a lucky solve. Google closed that door completely:
- grids grew larger and the required tiles less predictable, dropping single-attempt odds well below 1%;
- session timeouts (roughly 2–3 minutes) kill a challenge before random clicking can grind through it;
- IP reputation now compounds — every failed or timed-out attempt makes the next puzzle harder, so brute force gets slower exactly when you need it faster;
- v3 and invisible variants never show a grid to click at all.
Random clicking isn't "slow but workable" anymore — it simply doesn't converge. The reliable path is to hand the challenge to a service that returns a real token.
The modern approach: token-based solving
Every serious reCAPTCHA workflow in 2026 follows the same three steps, regardless of language:
- Detect the widget on the page and read its
sitekey(and, for v3, theaction). - Send the sitekey + page URL to a captcha-solving service, which runs the challenge (via human workers or ML) and returns a valid
g-recaptcha-responsetoken. - Inject the token into the page's hidden field, fire the callback, and submit the form.
Selenium's job is really only steps 1 and 3 — driving the browser. The actual solving is outsourced to an API such as 2Captcha, Anti-Captcha, CapSolver, or CapMonster Cloud. They differ on price and speed, but all expose the same token-for-sitekey contract.
Prerequisites
pip install selenium 2captcha-python
You'll also need Chrome (Selenium 4.6+ ships Selenium Manager, so you no longer download chromedriver by hand) and an API key from your chosen solving service.
Step 1 — Detect the widget and read the sitekey
The public site key lives in a data-sitekey attribute, usually on a div.g-recaptcha or referenced in the widget's iframe src. Grab it with a normal Selenium locator:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://example.com/form-with-recaptcha")
# Wait for the widget, then read the public site key
widget = WebDriverWait(driver, 15).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".g-recaptcha"))
)
sitekey = widget.get_attribute("data-sitekey")
print("sitekey:", sitekey)
If there's no .g-recaptcha element (common with invisible/v3), pull the key out of the reCAPTCHA iframe URL instead — it's the k= query parameter:
from urllib.parse import urlparse, parse_qs
iframe = driver.find_element(By.CSS_SELECTOR, "iframe[src*='recaptcha']")
sitekey = parse_qs(urlparse(iframe.get_attribute("src")).query)["k"][0]
Step 2 — Fetch a token from the solving service
With the sitekey and page URL, ask the service for a token. Using the official 2Captcha library:
from twocaptcha import TwoCaptcha
solver = TwoCaptcha("YOUR_API_KEY")
result = solver.recaptcha(
sitekey=sitekey,
url=driver.current_url,
)
token = result["code"] # this is the g-recaptcha-response value
Under the hood the service loads the same challenge, solves it, and returns a token that's valid for about two minutes — so fetch it right before you submit, not at the start of a long run.
Step 3 — Inject the token and submit
The token has to land in the hidden textarea#g-recaptcha-response element that Google injects into the page. Set its value with JavaScript, then either trigger the widget's callback or submit the form:
# Put the token into the hidden field reCAPTCHA reads from
driver.execute_script(
"document.getElementById('g-recaptcha-response').innerHTML = arguments[0];",
token,
)
# If the widget defines a data-callback, call it so the page reacts as if solved
driver.execute_script("""
const el = document.querySelector('.g-recaptcha');
const cb = el && el.getAttribute('data-callback');
if (cb && window[cb]) { window[cb](arguments[0]); }
""", token)
# Finally, submit the form
driver.find_element(By.CSS_SELECTOR, "button[type=submit]").click()
That's it — the site's backend forwards the token to Google, siteverify returns success, and you're through.
The full script
from urllib.parse import urlparse, parse_qs
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from twocaptcha import TwoCaptcha
API_KEY = "YOUR_API_KEY"
TARGET_URL = "https://example.com/form-with-recaptcha"
def get_sitekey(driver):
try:
widget = WebDriverWait(driver, 15).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".g-recaptcha"))
)
key = widget.get_attribute("data-sitekey")
if key:
return key
except Exception:
pass
iframe = driver.find_element(By.CSS_SELECTOR, "iframe[src*='recaptcha']")
return parse_qs(urlparse(iframe.get_attribute("src")).query)["k"][0]
def main():
driver = webdriver.Chrome()
solver = TwoCaptcha(API_KEY)
try:
driver.get(TARGET_URL)
sitekey = get_sitekey(driver)
token = solver.recaptcha(sitekey=sitekey, url=driver.current_url)["code"]
driver.execute_script(
"document.getElementById('g-recaptcha-response').innerHTML = arguments[0];",
token,
)
driver.execute_script("""
const el = document.querySelector('.g-recaptcha');
const cb = el && el.getAttribute('data-callback');
if (cb && window[cb]) { window[cb](arguments[0]); }
""", token)
driver.find_element(By.CSS_SELECTOR, "button[type=submit]").click()
WebDriverWait(driver, 15).until(EC.url_changes(TARGET_URL))
print("Submitted successfully.")
finally:
driver.quit()
if __name__ == "__main__":
main()
Handling reCAPTCHA v3 and Enterprise
For v3 there's no textarea to fill and no button to tick — the token is generated on an action and checked by score. You pass the extra parameters through to the solver, then feed the returned token into whatever request or callback the page uses:
result = solver.recaptcha(
sitekey=sitekey,
url=driver.current_url,
version="v3",
action="submit", # the action name the site expects
score=0.7, # target minimum score
)
token = result["code"]
Two realities to accept with v3: you can't force a high score — the service returns the best it can — and the site controls the passing threshold, so a token that scores 0.5 may still be rejected. Enterprise works the same way from your side (sitekey + action), but it layers in more signals, so a clean IP and a realistic browser matter far more.
Reduce how often challenges appear
Solving a token costs money and time, so the smarter play is to look human enough that reCAPTCHA rarely escalates in the first place:
- Use a stealthier browser. Plain Selenium leaks automation markers (
navigator.webdriver, ChromeDriver artifacts). Tools likeundetected-chromedriver,SeleniumBaseUC mode, or a Playwright-based headless browser setup remove many of them and can raise your v3 score without any solving call. - Rotate quality IPs. Datacenter IPs draw challenges immediately. Residential or mobile rotating proxies give you the clean reputation reCAPTCHA rewards.
- Slow down and vary behavior. Even pacing, zero mouse movement, and instant submits scream "bot." Add small randomized waits and realistic interaction.
- Warm up sessions. Reusing cookies and a consistent, aged browser profile builds the reputation that keeps scores high.
For the wider picture on evading blocks, see our guide to anti-scraping protection.
When to use a managed service instead
Wiring up a solver, proxies, and stealth tuning is doable, but it becomes a maintenance treadmill: Google tweaks the widget, your success rate drops, you re-tune. For production data collection at scale, most teams find it cheaper to hand the whole problem — CAPTCHA solving, proxy rotation, and browser fingerprinting — to infrastructure built for it. If you'd rather receive clean data than babysit token flows, scraping.pro runs this as a done-for-you scraping service and delivers the structured results directly.
FAQ
Can I solve reCAPTCHA with Selenium alone, no external service? Not reliably. Selenium can drive the page, but generating a valid token means passing Google's risk model, which you can't do by clicking tiles. You need either a solving API or a very well-disguised browser that scores high enough to skip the challenge.
What exactly is the reCAPTCHA token?
It's the value placed in the g-recaptcha-response field after a successful challenge. The site sends it to Google's siteverify endpoint to confirm you passed. Produce a valid token and the form is accepted.
Does the audio-challenge bypass still work? The old trick of downloading the audio challenge and running it through speech-to-text still exists in some libraries, but Google detects and rate-limits it aggressively. Token-based API solving is far more dependable today.
Is driver.switch_to_frame() still a thing?
No — that method was removed years ago. Modern Selenium 4 uses driver.switch_to.frame(...), and with token injection you usually don't need to enter the reCAPTCHA iframes at all.
Is this legal? Automating around a CAPTCHA can breach a site's terms of service and, depending on jurisdiction and intent, other rules too. Stick to sites you own or are authorized to test, and never use it for abuse.