I'm trying to solve a ReCAPTCHA v2 challenge using CapSolver with the ReCaptchaV2Classification task type.
However, whenever I call the CapSolver API, the response is always false, and the images are not being selected, so the CAPTCHA is never solved.
I've followed the official documentation but still can't get it to work. Any help or guidance would be greatly appreciated.
import time
import base64
import requests
import os
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
CAPSOLVER_API_KEY = 'CAP-0000'
# Basic PT → EN translator for reCAPTCHA questions
WORD_TRANSLATOR = {
"ônibus": "/m/01bjv", # bus
"ônibus escolar": "/m/02yvhj", # school bus
"semáforos": "/m/015qff", # traffic lights
"faixas de pedestre": "/m/014xcs", # crosswalks
"carros": "/m/0k4j", # cars
"motocicletas": "/m/04_sv", # motorcycles
"hidrante": "/m/01pns0", # fire hydrant
"placas de trânsito": "/m/015qbp", # parking meters
"escadas": "/m/01lynh", # stairs
"bicicletas": "/m/0199g", # bicycles
"tratores": "/m/013xlm", # tractors
"táxis": "/m/0pg52", # taxis
"cruzamentos": "/m/015kr", # bridges
"barcos": "/m/019jd", # boats
"palmeiras": "/m/0cdl1", # palm trees
"montanhas": "/m/09d_r", # mountains or hills
"chaminés": "/m/01jk_4", # chimneys
}
def translate_question(text):
for pt, en in WORD_TRANSLATOR.items():
if pt in text:
return en
return "" # fallback
def launch_browser():
options = Options()
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_argument("start-maximized")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_experimental_option("detach", True)
root_path = os.path.dirname(os.path.abspath(__file__))
extension_path = os.path.join(root_path, "PGOJNOJMMHPOFJGDMAEBADHBOCAHPPOD_1_15_5_0.crx")
options.add_extension(extension_path)
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
driver.set_page_load_timeout(60)
return driver
def click_checkbox(driver):
WebDriverWait(driver, 10).until(
EC.frame_to_be_available_and_switch_to_it((By.XPATH, "//iframe[contains(@src, 'anchor')]"))
)
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "recaptcha-anchor"))
).click()
driver.switch_to.default_content()
def capture_question(driver):
try:
driver.switch_to.default_content()
WebDriverWait(driver, 10).until(
EC.frame_to_be_available_and_switch_to_it((By.XPATH, "//iframe[contains(@src, 'bframe')]"))
)
strong = WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".rc-imageselect-desc-wrapper strong"))
)
text = strong.text.strip().lower()
print(f"🧠 Captured question: {text}")
if "ônibus" in text:
if "escolar" in text:
return "/m/02yvhj"
else:
return "/m/01bjv"
for pt, code in WORD_TRANSLATOR.items():
if pt in text:
print(f"🔎 Matched term: '{pt}' → code {code}")
return code
print("⚠️ No matching term found.")
return ""
except Exception as e:
print("❌ Error capturing question:", e)
return ""
def take_grid_screenshot(driver, path='grid.png'):
try:
driver.switch_to.default_content()
WebDriverWait(driver, 10).until(
EC.frame_to_be_available_and_switch_to_it((By.XPATH, "//iframe[contains(@src, 'bframe')]"))
)
grid_container = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "rc-imageselect-target"))
)
grid_container.screenshot(path)
print(f"📸 Screenshot saved: {path}")
except Exception as e:
print(f"❌ Error taking grid screenshot: {e}")
raise
def image_to_base64(path):
with open(path, 'rb') as img:
return base64.b64encode(img.read()).decode('utf-8')
def solve_with_capsolver(image_b64, question_en):
url = "https://api.capsolver.com/createTask"
print('question:', question_en)
payload = {
"clientKey": CAPSOLVER_API_KEY,
"task": {
"type": "ReCaptchaV2Classification",
"image": image_b64,
"question": question_en
}
}
response = requests.post(url, json=payload)
result = response.json()
print(f"📬 CapSolver response: {result}")
solution = result.get('solution', {})
return solution.get('objects', []), solution.get('hasObject', False)
def click_images(driver, indices):
images = driver.find_elements(By.CSS_SELECTOR, "td img")
print(f"Images found: {len(images)} - clicking indices: {indices}")
tds = driver.find_elements(By.CSS_SELECTOR, "table.rc-imageselect-table td")
for i in indices:
if i < len(tds):
try:
tds[i].click()
time.sleep(0.4)
except:
pass
def is_challenge_active(driver):
try:
return driver.find_element(By.CSS_SELECTOR, "div.rc-imageselect") is not None
except:
return False
def solve_recaptcha(driver):
driver.get("https://www.google.com/recaptcha/api2/demo")
click_checkbox(driver)
attempt = 1
while True:
print(f"[{attempt}] Attempting to solve challenge...")
try:
question_en = capture_question(driver)
if not question_en:
print("❌ Invalid or unrecognized question.")
break
take_grid_screenshot(driver, 'grid.png')
base64_img = image_to_base64('grid.png')
indices, has_object = solve_with_capsolver(base64_img, question_en)
images = driver.find_elements(By.CSS_SELECTOR, "td img")
print(f"Images found: {len(images)}")
if len(images) > 9:
print("⚠️ Grid with more than 9 images detected. Reloading.")
driver.find_element(By.ID, "recaptcha-reload-button").click()
time.sleep(2)
attempt += 1
continue
if not has_object:
print("🤖 No object detected. Clicking 'Skip' and retrying.")
driver.find_element(By.ID, "recaptcha-reload-button").click()
time.sleep(2)
attempt += 1
continue
click_images(driver, indices)
try:
verify_btn = WebDriverWait(driver, 2).until(
EC.element_to_be_clickable((By.ID, "recaptcha-verify-button"))
)
verify_btn.click()
print("🟢 'Verify' button clicked.")
except:
print("🔄 'Verify' button not visible yet.")
time.sleep(3)
driver.switch_to.default_content()
WebDriverWait(driver, 10).until(
EC.frame_to_be_available_and_switch_to_it((By.XPATH, "//iframe[contains(@src, 'bframe')]"))
)
if not is_challenge_active(driver):
print("✅ reCAPTCHA solved successfully!")
break
except Exception as e:
print(f"❌ Error during solving process: {e}")
break
attempt += 1
time.sleep(1)
def main():
driver = launch_browser()
solve_recaptcha(driver)
if __name__ == "__main__":
main()
📬 CapSolver response: {'errorId': 0, 'status': 'ready', 'solution': {'hasObject': False, 'size': 0, 'type': ''}, 'taskId': '<task_id>'}
I managed to solve it by downloading the Google Chrome extension and adding the method that starts the chromedriver