How to Solve CAPTCHAs in Python Using Botasaurus and CapSolver (Full Guide)

Lucas Mitchell
Automation Engineer
12-Dec-2025
TLDR: This guide demonstrates how to combine Botasaurus, a Python web scraping framework with built-in anti-detection features, and CapSolver, a captcha solving API, to automatically bypass reCAPTCHA v2, reCAPTCHA v3, and Cloudflare Turnstile during large-scale web scraping. The core process involves setting up the environment, using the CapSolver browser extension to identify captcha parameters, calling the CapSolver API via a Python helper function to get a solution token, and finally using Botasaurus to inject the token into the webpage for form submission.

How to Solve CAPTCHAs in Python Using Botasaurus and CapSolver (Full Guide)
Web scraping at scale often encounters captchas that block automated access. This guide demonstrates how to combine Botasaurus, a powerful web scraping framework, with CapSolver to automatically solve reCAPTCHA v2, reCAPTCHA v3, and Cloudflare Turnstile captchas.
What is Botasaurus?
Botasaurus is a Python web scraping framework that simplifies browser automation with built-in anti-detection capabilities. It provides a clean decorator-based API for browser tasks.
Key Features:
- Anti-detection: Built-in stealth features to avoid bot detection
- Simple API: Decorator-based approach with
@browser - JavaScript execution: Run custom JS code in the browser context
- Element selection: Easy DOM manipulation with CSS selectors
Installation:
bash
pip install botasaurus
Basic usage:
python
from botasaurus.browser import browser, Driver
@browser()
def scrape_page(driver: Driver, data):
driver.get("https://example.com")
title = driver.get_text("h1")
return {"title": title}
# Run the scraper
result = scrape_page()
What is CapSolver?
CapSolver is a captcha solving service that provides an API to solve various captcha types including reCAPTCHA and Cloudflare Turnstile.
Supported captcha types:
- reCAPTCHA v2 (checkbox and invisible)
- reCAPTCHA v3 (score-based)
- reCAPTCHA Enterprise
- Cloudflare Turnstile
- And more
Getting your API key:
- Create an account at CapSolver Dashboard
- Add funds to your account
- Copy your API key (starts with
CAP-)
Project Setup
Install Dependencies
bash
pip install botasaurus capsolver requests python-dotenv
Configure Environment
Create a .env file in your project root:
env
CAPSOLVER_API_KEY=CAP-YOUR_API_KEY_HERE
Configuration Module
Create a shared configuration loader:
python
# shared/config.py
import os
from pathlib import Path
from dotenv import load_dotenv
# Load .env file from project root
ROOT_DIR = Path(__file__).parent.parent
load_dotenv(ROOT_DIR / ".env")
class Config:
"""Configuration class for CapSolver integration."""
# CapSolver API Key
CAPSOLVER_API_KEY: str = os.getenv("CAPSOLVER_API_KEY", "")
# CapSolver API endpoints
CAPSOLVER_API_URL = "https://api.capsolver.com"
CREATE_TASK_ENDPOINT = f"{CAPSOLVER_API_URL}/createTask"
GET_RESULT_ENDPOINT = f"{CAPSOLVER_API_URL}/getTaskResult"
@classmethod
def validate(cls) -> bool:
"""Check if the configuration is valid."""
if not cls.CAPSOLVER_API_KEY:
print("Error: CAPSOLVER_API_KEY not set!")
return False
return True
Identifying Captcha Parameters with CapSolver Extension
Before integrating with the API, you need to identify the correct parameters for the target captcha. The CapSolver browser extension provides an easy way to detect all required parameters automatically.
Installation
Install the CapSolver extension from the Chrome Web Store.
Using the Captcha Detector
- Press F12 to open developer tools
- Navigate to the Capsolver Captcha Detector tab
- Keep the detector panel open while visiting your target website
- Trigger the captcha on the page
Important: Do not close the Capsolver panel before triggering the captcha, as closing it erases previously detected information.
Detected Parameters
The extension automatically identifies all required reCAPTCHA parameters:
- Website URL
- Site Key
- pageAction (for v3)
- isInvisible
- isEnterprise
- Api Domain
The detector provides a formatted JSON output ready for API integration, making it easy to copy the exact parameters needed for your solving tasks.
For more details, see the complete guide on identifying captcha parameters.
Solving reCAPTCHA v2 with CapSolver API
reCAPTCHA v2 is the classic "I'm not a robot" checkbox captcha. It may present image selection challenges to users.
Finding the Site Key
You can use the CapSolver extension detector (described above) or find the site key manually:
Look in the page HTML for:
html
<div class="g-recaptcha" data-sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"></div>
Or in JavaScript:
javascript
grecaptcha.render('container', {'sitekey': '6Le-xxxxx...'});
Helper Function
python
# utils/capsolver_helper.py
import time
import requests
from shared.config import Config
def solve_recaptcha_v2(
website_url: str,
website_key: str,
is_invisible: bool = False,
timeout: int = 120
) -> dict:
"""
Solve reCAPTCHA v2 using CapSolver API.
Args:
website_url: The URL of the page with the captcha
website_key: The reCAPTCHA site key
is_invisible: Whether it's invisible reCAPTCHA v2
timeout: Maximum time to wait for solution (seconds)
Returns:
dict with 'gRecaptchaResponse' token
"""
if not Config.validate():
raise Exception("Invalid configuration - check your API key")
# Build task payload
task = {
"type": "ReCaptchaV2TaskProxyLess",
"websiteURL": website_url,
"websiteKey": website_key,
}
if is_invisible:
task["isInvisible"] = True
payload = {
"clientKey": Config.CAPSOLVER_API_KEY,
"task": task
}
# Create task
response = requests.post(Config.CREATE_TASK_ENDPOINT, json=payload)
result = response.json()
if result.get("errorId") and result.get("errorId") != 0:
raise Exception(f"Failed to create task: {result.get('errorDescription')}")
task_id = result.get("taskId")
# Poll for result
start_time = time.time()
while time.time() - start_time < timeout:
time.sleep(2)
result_payload = {
"clientKey": Config.CAPSOLVER_API_KEY,
"taskId": task_id
}
response = requests.post(Config.GET_RESULT_ENDPOINT, json=result_payload)
result = response.json()
if result.get("status") == "ready":
return result.get("solution", {})
elif result.get("status") == "failed":
raise Exception(f"Task failed: {result.get('errorDescription')}")
raise Exception(f"Timeout after {timeout} seconds")
Complete reCAPTCHA v2 Example
python
from botasaurus.browser import browser, Driver
from shared.config import Config
from utils.capsolver_helper import solve_recaptcha_v2
DEMO_URL = "https://www.google.com/recaptcha/api2/demo"
DEMO_SITEKEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
@browser(headless=False)
def solve_recaptcha_v2_with_api(driver: Driver, data: dict):
"""Solve reCAPTCHA v2 using CapSolver API and inject the token."""
url = data.get("url", DEMO_URL)
site_key = data.get("site_key", DEMO_SITEKEY)
# Step 1: Load the page
driver.get(url)
driver.sleep(2)
# Step 2: Extract site key from page (optional)
extracted_key = driver.run_js("""
const recaptchaDiv = document.querySelector('.g-recaptcha');
return recaptchaDiv ? recaptchaDiv.getAttribute('data-sitekey') : null;
""")
if extracted_key:
site_key = extracted_key
# Step 3: Solve captcha via CapSolver API
solution = solve_recaptcha_v2(
website_url=url,
website_key=site_key
)
token = solution.get("gRecaptchaResponse")
# Step 4: Inject token into the page
driver.run_js(f"""
// Set the hidden textarea value
const responseField = document.querySelector('[name="g-recaptcha-response"]');
if (responseField) {{
responseField.value = "{token}";
}}
// Trigger callback if available
if (typeof ___grecaptcha_cfg !== 'undefined') {{
try {{
const clients = ___grecaptcha_cfg.clients;
for (const key in clients) {{
const client = clients[key];
if (client && client.callback) {{
client.callback("{token}");
}}
}}
}} catch (e) {{}}
}}
""")
# Step 5: Submit the form
submit_button = driver.select('input[type="submit"]')
if submit_button:
submit_button.click()
driver.sleep(2)
return {"success": True, "token_length": len(token)}
# Run the demo
result = solve_recaptcha_v2_with_api(data={"url": DEMO_URL, "site_key": DEMO_SITEKEY})
Solving reCAPTCHA v3 with CapSolver API
reCAPTCHA v3 is invisible and works by analyzing user behavior to generate a score from 0.0 to 1.0.
Key difference from v2: reCAPTCHA v3 requires a pageAction parameter.
Finding the Page Action
The easiest way to find the pageAction is using the CapSolver extension detector. Alternatively, look in the page JavaScript for:
javascript
grecaptcha.execute('siteKey', {action: 'login'})
// The 'login' is your pageAction
Helper Function
python
def solve_recaptcha_v3(
website_url: str,
website_key: str,
page_action: str,
timeout: int = 120
) -> dict:
"""
Solve reCAPTCHA v3 using CapSolver API.
Args:
website_url: The URL of the page with the captcha
website_key: The reCAPTCHA site key
page_action: The action parameter (REQUIRED for v3)
timeout: Maximum time to wait for solution (seconds)
Returns:
dict with 'gRecaptchaResponse' token
"""
if not Config.validate():
raise Exception("Invalid configuration - check your API key")
if not page_action:
raise Exception("pageAction is REQUIRED for reCAPTCHA v3")
# Build task payload
task = {
"type": "ReCaptchaV3TaskProxyLess",
"websiteURL": website_url,
"websiteKey": website_key,
"pageAction": page_action, # REQUIRED for v3
}
payload = {
"clientKey": Config.CAPSOLVER_API_KEY,
"task": task
}
# Create task
response = requests.post(Config.CREATE_TASK_ENDPOINT, json=payload)
result = response.json()
if result.get("errorId") and result.get("errorId") != 0:
raise Exception(f"Failed to create task: {result.get('errorDescription')}")
task_id = result.get("taskId")
# Poll for result
start_time = time.time()
while time.time() - start_time < timeout:
time.sleep(2)
result_payload = {
"clientKey": Config.CAPSOLVER_API_KEY,
"taskId": task_id
}
response = requests.post(Config.GET_RESULT_ENDPOINT, json=result_payload)
result = response.json()
if result.get("status") == "ready":
return result.get("solution", {})
elif result.get("status") == "failed":
raise Exception(f"Task failed: {result.get('errorDescription')}")
raise Exception(f"Timeout after {timeout} seconds")
Complete reCAPTCHA v3 Example
python
from botasaurus.browser import browser, Driver
from shared.config import Config
from utils.capsolver_helper import solve_recaptcha_v3
DEMO_URL = "https://recaptcha-demo.appspot.com/recaptcha-v3-request-scores.php"
DEMO_SITEKEY = "6LdyC2cUAAAAACGuDKpXeDorzUDWXmdqeg-xy696"
PAGE_ACTION = "examples/v3scores"
@browser(headless=False)
def solve_recaptcha_v3_with_api(driver: Driver, data: dict):
"""Solve reCAPTCHA v3 using CapSolver API and inject the token."""
url = data.get("url", DEMO_URL)
site_key = data.get("site_key", DEMO_SITEKEY)
page_action = data.get("page_action", PAGE_ACTION)
# Step 1: Load the page
driver.get(url)
driver.sleep(2)
# Step 2: Solve captcha via CapSolver API
solution = solve_recaptcha_v3(
website_url=url,
website_key=site_key,
page_action=page_action
)
token = solution.get("gRecaptchaResponse")
# Step 3: Inject token into the page
driver.run_js(f"""
const token = "{token}";
// Set hidden field if exists
const responseField = document.querySelector('[name="g-recaptcha-response"]');
if (responseField) {{
responseField.value = token;
}}
// Create hidden field if form exists but field doesn't
const forms = document.querySelectorAll('form');
forms.forEach(form => {{
let field = form.querySelector('[name="g-recaptcha-response"]');
if (!field) {{
field = document.createElement('input');
field.type = 'hidden';
field.name = 'g-recaptcha-response';
form.appendChild(field);
}}
field.value = token;
}});
""")
# Step 4: Submit or verify
buttons = driver.select_all("button")
for button in buttons:
if "verify" in button.text.lower() or "submit" in button.text.lower():
button.click()
driver.sleep(2)
break
return {"success": True, "token_length": len(token)}
# Run the demo
result = solve_recaptcha_v3_with_api(data={
"url": DEMO_URL,
"site_key": DEMO_SITEKEY,
"page_action": PAGE_ACTION
})
Solving Cloudflare Turnstile with CapSolver API
Cloudflare Turnstile is a privacy-focused captcha alternative designed to be less intrusive than traditional captchas.
Key differences from reCAPTCHA:
- Task type is
AntiTurnstileTaskProxyLess - Response field is
token(notgRecaptchaResponse) - Site keys typically start with
0x4
Finding the Site Key
Look in the page HTML for:
html
<div class="cf-turnstile" data-sitekey="0x4AAAAAAABS7vwvV6VFfMcD"></div>
Helper Function
python
def solve_turnstile(
website_url: str,
website_key: str,
action: str = None,
cdata: str = None,
timeout: int = 120
) -> dict:
"""
Solve Cloudflare Turnstile using CapSolver API.
Args:
website_url: The URL of the page with Turnstile
website_key: The Turnstile site key (starts with 0x4)
action: Optional action from data-action attribute
cdata: Optional cdata from data-cdata attribute
timeout: Maximum time to wait for solution (seconds)
Returns:
dict with 'token' field
"""
if not Config.validate():
raise Exception("Invalid configuration - check your API key")
# Build task payload
task = {
"type": "AntiTurnstileTaskProxyLess",
"websiteURL": website_url,
"websiteKey": website_key,
}
# Add optional metadata
metadata = {}
if action:
metadata["action"] = action
if cdata:
metadata["cdata"] = cdata
if metadata:
task["metadata"] = metadata
payload = {
"clientKey": Config.CAPSOLVER_API_KEY,
"task": task
}
# Create task
response = requests.post(Config.CREATE_TASK_ENDPOINT, json=payload)
result = response.json()
if result.get("errorId") and result.get("errorId") != 0:
raise Exception(f"Failed to create task: {result.get('errorDescription')}")
task_id = result.get("taskId")
# Poll for result
start_time = time.time()
while time.time() - start_time < timeout:
time.sleep(2)
result_payload = {
"clientKey": Config.CAPSOLVER_API_KEY,
"taskId": task_id
}
response = requests.post(Config.GET_RESULT_ENDPOINT, json=result_payload)
result = response.json()
if result.get("status") == "ready":
return result.get("solution", {})
elif result.get("status") == "failed":
raise Exception(f"Task failed: {result.get('errorDescription')}")
raise Exception(f"Timeout after {timeout} seconds")
Complete Turnstile Example
python
from botasaurus.browser import browser, Driver
from shared.config import Config
from utils.capsolver_helper import solve_turnstile
DEMO_URL = "https://peet.ws/turnstile-test/non-interactive.html"
DEMO_SITEKEY = "0x4AAAAAAABS7vwvV6VFfMcD"
@browser(headless=False)
def solve_turnstile_with_api(driver: Driver, data: dict):
"""Solve Cloudflare Turnstile using CapSolver API and inject the token."""
url = data.get("url", DEMO_URL)
site_key = data.get("site_key", DEMO_SITEKEY)
# Step 1: Load the page
driver.get(url)
driver.sleep(3)
# Step 2: Extract site key from page (optional)
extracted_params = driver.run_js("""
const turnstileDiv = document.querySelector('.cf-turnstile, [data-sitekey]');
if (turnstileDiv) {
const key = turnstileDiv.getAttribute('data-sitekey');
if (key && key.startsWith('0x')) {
return {
sitekey: key,
action: turnstileDiv.getAttribute('data-action')
};
}
}
return null;
""")
if extracted_params and extracted_params.get("sitekey"):
site_key = extracted_params["sitekey"]
# Step 3: Solve Turnstile via CapSolver API
solution = solve_turnstile(
website_url=url,
website_key=site_key,
action=extracted_params.get("action") if extracted_params else None
)
token = solution.get("token")
# Step 4: Inject token into the page
driver.run_js(f"""
const token = "{token}";
// Find and fill cf-turnstile-response field
const responseFields = [
document.querySelector('[name="cf-turnstile-response"]'),
document.querySelector('[name="cf_turnstile_response"]'),
document.querySelector('input[name*="turnstile"]')
];
for (const field of responseFields) {{
if (field) {{
field.value = token;
break;
}}
}}
// Create hidden field if form exists but field doesn't
const forms = document.querySelectorAll('form');
forms.forEach(form => {{
let field = form.querySelector('[name="cf-turnstile-response"]');
if (!field) {{
field = document.createElement('input');
field.type = 'hidden';
field.name = 'cf-turnstile-response';
form.appendChild(field);
}}
field.value = token;
}});
""")
# Step 5: Submit the form
submit_btn = driver.select('button[type="submit"], input[type="submit"]')
if submit_btn:
submit_btn.click()
driver.sleep(2)
return {"success": True, "token_length": len(token)}
# Run the demo
result = solve_turnstile_with_api(data={"url": DEMO_URL, "site_key": DEMO_SITEKEY})
Task Types Reference
| Captcha Type | Task Type | Response Field | Required Parameters |
|---|---|---|---|
| reCAPTCHA v2 | ReCaptchaV2TaskProxyLess |
gRecaptchaResponse |
websiteURL, websiteKey |
| reCAPTCHA v2 Enterprise | ReCaptchaV2EnterpriseTaskProxyLess |
gRecaptchaResponse |
websiteURL, websiteKey |
| reCAPTCHA v3 | ReCaptchaV3TaskProxyLess |
gRecaptchaResponse |
websiteURL, websiteKey, pageAction |
| reCAPTCHA v3 Enterprise | ReCaptchaV3EnterpriseTaskProxyLess |
gRecaptchaResponse |
websiteURL, websiteKey, pageAction |
| Cloudflare Turnstile | AntiTurnstileTaskProxyLess |
token |
websiteURL, websiteKey |
For sites that block datacenter IPs, use the proxy variants (e.g., ReCaptchaV2Task) and provide your own residential proxy.
Best Practices
1. Token Expiry
Captcha tokens expire quickly (typically within 2 minutes). Always use the token immediately after receiving it:
python
# Get token
solution = solve_recaptcha_v2(url, site_key)
token = solution.get("gRecaptchaResponse")
# Use immediately - don't store for later
driver.run_js(f'document.querySelector("[name=g-recaptcha-response]").value = "{token}"')
driver.select('button[type="submit"]').click()
2. Error Handling
Always implement proper error handling for API failures:
python
try:
solution = solve_recaptcha_v2(url, site_key)
except Exception as e:
print(f"Captcha solving failed: {e}")
# Implement retry logic or fallback
3. Rate Limiting
Add delays between requests to avoid triggering anti-bot measures:
python
driver.sleep(2) # Wait after page load
# ... solve captcha ...
driver.sleep(1) # Wait before form submission
4. Validate Configuration
Always validate your API key before making requests:
python
if not Config.validate():
raise Exception("Please configure your API key in .env file")
Conclusion
Combining Botasaurus with CapSolver provides a robust solution for handling captchas in web scraping projects. The API-based approach gives you full control over the solving process and works reliably across different captcha types.
Boost your automation budget instantly!
Use bonus code CAPN when topping up your CapSolver account to get an extra 5% bonus on every recharge — with no limits.
Redeem it now in your CapSolver Dashboard
Key Takeaways
- Botasaurus provides browser automation with built-in anti-detection features
- CapSolver API offers a reliable way to solve multiple captcha types programmatically
- reCAPTCHA v2 requires
websiteURLandwebsiteKeyparameters - reCAPTCHA v3 additionally requires a
pageActionparameter - Cloudflare Turnstile returns a
tokenfield instead ofgRecaptchaResponse - Tokens expire quickly (~2 minutes), so use them immediately after receiving
Frequently Asked Questions (FAQ)
How to solve reCAPTCHA and Cloudflare Turnstile automatically in Python web scraping?
The most effective method is to use a robust browser automation framework like Botasaurus, which handles anti-detection, and integrate it with a dedicated captcha solving API like CapSolver to programmatically obtain the required solution tokens.
What are the benefits of using Botasaurus for anti-detection web scraping?
Botasaurus simplifies browser automation with a clean, decorator-based API while providing essential built-in stealth features to minimize the risk of being detected and blocked by target websites.
What is the difference between reCAPTCHA v2 and v3 solving with CapSolver API?
While both require the websiteURL and websiteKey, solving reCAPTCHA v3 (the invisible, score-based version) additionally requires a pageAction parameter to be included in the task payload sent to the CapSolver API.
What happens after CapSolver returns a captcha token?
Once the token (e.g., gRecaptchaResponse or token) is received, it must be immediately injected into the target webpage's hidden form field using a JavaScript execution command before the form can be successfully submitted to the server.
How long does a CapSolver token last before it expires?
The solution tokens provided by CapSolver for reCAPTCHA and Turnstile have a very short validity period, typically expiring in approximately 2 minutes, requiring immediate use.
Compliance Disclaimer: The information provided on this blog is for informational purposes only. CapSolver is committed to compliance with all applicable laws and regulations. The use of the CapSolver network for illegal, fraudulent, or abusive activities is strictly prohibited and will be investigated. Our captcha-solving solutions enhance user experience while ensuring 100% compliance in helping solve captcha difficulties during public data crawling. We encourage responsible use of our services. For more information, please visit our Terms of Service and Privacy Policy.
More

How to Solve CAPTCHAs in Python Using Botasaurus and CapSolver (Full Guide)
Learn to integrate Botasaurus (Python web scraping framework) with CapSolver API to automatically solve reCAPTCHA v2/v3 and Turnstile.

Lucas Mitchell
12-Dec-2025

What are 402, 403, 404, and 429 Errors in Web Scraping? A Comprehensive Guide
Master web scraping error handling by understanding what are 402, 403, 404, and 429 errors. Learn how to fix 403 Forbidden, implement rate limiting error 429 solutions, and handle the emerging 402 Payment Required status code.

Sora Fujimoto
11-Dec-2025

Best Web Scraping APIs in 2026: Top Tools Compared & Ranked
Discover the best Web Scraping APIs for 2026. We compare the top tools based on success rate, speed, AI features, and pricing to help you choose the right solution for your data extraction needs.

Ethan Collins
11-Dec-2025

Web Crawling vs. Web Scraping: The Essential Difference
Uncover the essential difference between web crawling and web scraping. Learn their distinct purposes, 10 powerful use cases, and how CapSolver helps bypass AWS WAF and CAPTCHA blocks for seamless data acquisition.

Sora Fujimoto
09-Dec-2025

How to Solve Captchas When Web Scraping with Scrapling and CapSolver
Scrapling + CapSolver enables automated scraping with ReCaptcha v2/v3 and Cloudflare Turnstile bypass.

Ethan Collins
04-Dec-2025

How to Make an AI Agent Web Scraper (Beginner-Friendly Tutorial)
Learn how to make an AI Agent Web Scraper from scratch with this beginner-friendly tutorial. Discover the core components, code examples, and how to bypass anti-bot measures like CAPTCHAs for reliable data collection.

Lucas Mitchell
02-Dec-2025


