How to Solve reCAPTCHA v2 and v3 Programmatically
Complete guide to solving reCAPTCHA v2 (checkbox, invisible) and v3 (score-based) programmatically using a CAPTCHA solver API. Includes Python and JavaScript code examples.
Solving reCAPTCHA v2 and v3 programmatically is the most common CAPTCHA automation task developers face today. Google’s reCAPTCHA protects millions of websites, and whether you are building a web scraper, automating form submissions, or running QA tests at scale, you need a reliable method to handle these challenges. This guide covers every reCAPTCHA variant — v2 checkbox, v2 invisible, v3 score-based, and their Enterprise counterparts — with production-ready code examples in Python and JavaScript.
Understanding reCAPTCHA Variants
Before writing any code, it helps to know what you are dealing with. Google currently deploys several reCAPTCHA versions, and each one requires a different solving approach.
reCAPTCHA v2 Checkbox is the classic “I’m not a robot” widget. Clicking the checkbox triggers a risk analysis. If Google is uncertain, it presents an image challenge (select all traffic lights, crosswalks, etc.). Once passed, the widget produces a g-recaptcha-response token that gets submitted with the form.
reCAPTCHA v2 Invisible works the same way under the hood, but there is no checkbox. The challenge fires automatically on a user action like a button click. The user only sees an image challenge if Google flags the session as suspicious. For a deep dive into how invisible reCAPTCHA works and how to identify it, see our dedicated post on invisible reCAPTCHA.
reCAPTCHA v3 takes a completely different approach. It runs entirely in the background, assigns a score from 0.0 (likely bot) to 1.0 (likely human), and never shows a visual challenge. The site owner decides what score threshold to enforce. We cover the scoring system in detail in our reCAPTCHA v3 score guide.
reCAPTCHA Enterprise is Google’s commercial offering. It uses the same v2 and v3 mechanics but adds additional detection signals, a different API endpoint (enterprise.google.com), and enterprise-specific site keys. Our reCAPTCHA Enterprise guide covers the differences in detail.
If you want a side-by-side breakdown of v2 versus v3, including when sites choose one over the other, check out our reCAPTCHA v2 vs v3 comparison.
How to Find the Site Key
Every reCAPTCHA implementation has a site key — a public identifier that tells Google which site is requesting verification. You need this key to submit a solve request to any CAPTCHA API.
Method 1: Search the Page Source
Open the page source (Ctrl+U) and search for data-sitekey:
<div class="g-recaptcha" data-sitekey="6LcR_RsTAAAAAFmw..."></div>
Method 2: Check JavaScript Calls
For v3 and invisible v2, the site key is often passed in a JavaScript call:
grecaptcha.execute('6LcR_RsTAAAAAFmw...', {action: 'submit'});
Method 3: Inspect Network Requests
Open DevTools, go to the Network tab, and filter by google.com/recaptcha. The render parameter in the URL contains the site key:
https://www.google.com/recaptcha/api2/anchor?k=6LcR_RsTAAAAAFmw...
For reCAPTCHA v3, also note the action parameter. This string (e.g., login, submit, homepage) is required when solving v3 challenges and directly affects the score. You can find it in the grecaptcha.execute() call or in the network request parameters.
API Task Types Reference
uCaptcha supports all reCAPTCHA variants through different task types. Here is the complete reference:
| Task Type | Use Case | Proxy Required |
|---|---|---|
RecaptchaV2TaskProxyless | v2 checkbox, standard | No |
RecaptchaV2Task | v2 checkbox with your proxy | Yes |
RecaptchaV2EnterpriseTaskProxyless | v2 Enterprise | No |
RecaptchaV2EnterpriseTask | v2 Enterprise with proxy | Yes |
RecaptchaV3TaskProxyless | v3 score-based | No |
RecaptchaV3Task | v3 with your proxy | Yes |
Proxyless vs Proxy tasks: Proxyless tasks are simpler — the solving service handles everything internally. Proxy tasks let you route the solve through your own proxy, which can improve success rates on sites that check IP consistency between the CAPTCHA solve and the subsequent form submission.
Solving reCAPTCHA v2 Checkbox
Python Example
import requests
import time
API_KEY = "YOUR_UCAPTCHA_API_KEY"
BASE_URL = "https://api.ucaptcha.net"
# Step 1: Create the task
response = requests.post(f"{BASE_URL}/createTask", json={
"clientKey": API_KEY,
"task": {
"type": "RecaptchaV2TaskProxyless",
"websiteURL": "https://example.com/login",
"websiteKey": "6LcR_RsTAAAAAFmw..."
}
})
task_id = response.json()["taskId"]
print(f"Task created: {task_id}")
# Step 2: Poll for the result
while True:
time.sleep(5)
result = requests.post(f"{BASE_URL}/getTaskResult", json={
"clientKey": API_KEY,
"taskId": task_id
})
data = result.json()
if data["status"] == "ready":
token = data["solution"]["gRecaptchaResponse"]
print(f"Token received: {token[:80]}...")
break
elif data["status"] == "processing":
print("Still solving...")
else:
print(f"Error: {data}")
break
# Step 3: Use the token in your form submission
form_response = requests.post("https://example.com/login", data={
"username": "user@example.com",
"password": "password123",
"g-recaptcha-response": token
})
JavaScript (Node.js) Example
const BASE_URL = "https://api.ucaptcha.net";
const API_KEY = "YOUR_UCAPTCHA_API_KEY";
async function solveRecaptchaV2(websiteURL, websiteKey) {
// Step 1: Create the task
const createRes = await fetch(`${BASE_URL}/createTask`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
clientKey: API_KEY,
task: {
type: "RecaptchaV2TaskProxyless",
websiteURL,
websiteKey,
},
}),
});
const { taskId } = await createRes.json();
console.log(`Task created: ${taskId}`);
// Step 2: Poll for the result
while (true) {
await new Promise((r) => setTimeout(r, 5000));
const resultRes = await fetch(`${BASE_URL}/getTaskResult`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
clientKey: API_KEY,
taskId,
}),
});
const data = await resultRes.json();
if (data.status === "ready") {
console.log(`Token: ${data.solution.gRecaptchaResponse.slice(0, 80)}...`);
return data.solution.gRecaptchaResponse;
}
if (data.status !== "processing") {
throw new Error(`Solve failed: ${JSON.stringify(data)}`);
}
console.log("Still solving...");
}
}
// Usage
const token = await solveRecaptchaV2(
"https://example.com/login",
"6LcR_RsTAAAAAFmw..."
);
Solving reCAPTCHA v2 with a Proxy
When the target site validates that the CAPTCHA-solving IP matches the IP that submits the form, you should use the proxy variant. Pass your proxy details in the task object:
response = requests.post(f"{BASE_URL}/createTask", json={
"clientKey": API_KEY,
"task": {
"type": "RecaptchaV2Task",
"websiteURL": "https://example.com/login",
"websiteKey": "6LcR_RsTAAAAAFmw...",
"proxyType": "http",
"proxyAddress": "123.45.67.89",
"proxyPort": 8080,
"proxyLogin": "proxyuser",
"proxyPassword": "proxypass"
}
})
The polling and token retrieval steps remain identical. The only difference is the task type and the added proxy fields.
Solving Invisible reCAPTCHA v2
Invisible reCAPTCHA v2 uses the same RecaptchaV2TaskProxyless task type, but you must set the isInvisible parameter to true:
response = requests.post(f"{BASE_URL}/createTask", json={
"clientKey": API_KEY,
"task": {
"type": "RecaptchaV2TaskProxyless",
"websiteURL": "https://example.com/signup",
"websiteKey": "6LcR_RsTAAAAAFmw...",
"isInvisible": True
}
})
Setting isInvisible tells the solver that there is no checkbox to interact with, which changes the internal solving strategy. Omitting this flag on an invisible reCAPTCHA will often result in invalid tokens.
Solving reCAPTCHA v3
reCAPTCHA v3 requires two additional parameters compared to v2: the page action and an optional minimum score.
Python Example
response = requests.post(f"{BASE_URL}/createTask", json={
"clientKey": API_KEY,
"task": {
"type": "RecaptchaV3TaskProxyless",
"websiteURL": "https://example.com/checkout",
"websiteKey": "6LcR_RsTAAAAAFmw...",
"pageAction": "checkout",
"minScore": 0.7
}
})
task_id = response.json()["taskId"]
# Poll for result (same as v2)
while True:
time.sleep(5)
result = requests.post(f"{BASE_URL}/getTaskResult", json={
"clientKey": API_KEY,
"taskId": task_id
})
data = result.json()
if data["status"] == "ready":
token = data["solution"]["gRecaptchaResponse"]
score = data["solution"].get("score")
print(f"Token: {token[:80]}...")
print(f"Score: {score}")
break
JavaScript Example
async function solveRecaptchaV3(websiteURL, websiteKey, pageAction, minScore = 0.7) {
const createRes = await fetch(`${BASE_URL}/createTask`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
clientKey: API_KEY,
task: {
type: "RecaptchaV3TaskProxyless",
websiteURL,
websiteKey,
pageAction,
minScore,
},
}),
});
const { taskId } = await createRes.json();
while (true) {
await new Promise((r) => setTimeout(r, 5000));
const resultRes = await fetch(`${BASE_URL}/getTaskResult`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ clientKey: API_KEY, taskId }),
});
const data = await resultRes.json();
if (data.status === "ready") {
return {
token: data.solution.gRecaptchaResponse,
score: data.solution.score,
};
}
if (data.status !== "processing") {
throw new Error(`Solve failed: ${JSON.stringify(data)}`);
}
}
}
const { token, score } = await solveRecaptchaV3(
"https://example.com/checkout",
"6LcR_RsTAAAAAFmw...",
"checkout",
0.7
);
Key parameters for v3:
- pageAction: Must match the action string used in the site’s
grecaptcha.execute()call. Common values arelogin,submit,checkout,homepage. An incorrect action will produce a token with a low score. - minScore: The minimum acceptable score (0.1 to 0.9). Higher values are harder to achieve but more likely to pass strict server-side checks. Most sites enforce a threshold between 0.5 and 0.7.
Solving reCAPTCHA Enterprise
Enterprise variants require the enterprise-specific task types. The main differences from standard reCAPTCHA are:
- Different site keys — Enterprise site keys are registered through the Google Cloud Console, not the standard reCAPTCHA admin.
- Enterprise API domain — The JavaScript loads from
enterprise.google.cominstead ofgoogle.com. - The
sparameter — Some Enterprise implementations include an additionalsvalue that must be passed to the solver.
Enterprise v2 Example
response = requests.post(f"{BASE_URL}/createTask", json={
"clientKey": API_KEY,
"task": {
"type": "RecaptchaV2EnterpriseTaskProxyless",
"websiteURL": "https://enterprise-site.com/form",
"websiteKey": "6LcR_ENTERPRISE_KEY...",
"enterprisePayload": {
"s": "additional_token_if_present"
}
}
})
For a comprehensive walkthrough of Enterprise-specific parameters and edge cases, see our reCAPTCHA Enterprise guide.
Building a Reusable Solver Class
For production use, wrap the solve logic in a reusable class that handles retries, timeouts, and error classification:
import requests
import time
class RecaptchaSolver:
def __init__(self, api_key, base_url="https://api.ucaptcha.net"):
self.api_key = api_key
self.base_url = base_url
def solve(self, task, timeout=120, poll_interval=5):
"""Submit a task and wait for the result."""
create_resp = requests.post(f"{self.base_url}/createTask", json={
"clientKey": self.api_key,
"task": task
})
create_data = create_resp.json()
if "taskId" not in create_data:
raise Exception(f"Task creation failed: {create_data}")
task_id = create_data["taskId"]
start_time = time.time()
while time.time() - start_time < timeout:
time.sleep(poll_interval)
result = requests.post(f"{self.base_url}/getTaskResult", json={
"clientKey": self.api_key,
"taskId": task_id
})
data = result.json()
if data["status"] == "ready":
return data["solution"]
if data["status"] != "processing":
raise Exception(f"Solve error: {data}")
raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
def solve_v2(self, url, site_key, invisible=False, proxy=None):
task = {
"type": "RecaptchaV2Task" if proxy else "RecaptchaV2TaskProxyless",
"websiteURL": url,
"websiteKey": site_key,
}
if invisible:
task["isInvisible"] = True
if proxy:
task.update(proxy)
return self.solve(task)
def solve_v3(self, url, site_key, action, min_score=0.7):
return self.solve({
"type": "RecaptchaV3TaskProxyless",
"websiteURL": url,
"websiteKey": site_key,
"pageAction": action,
"minScore": min_score,
})
# Usage
solver = RecaptchaSolver("YOUR_UCAPTCHA_API_KEY")
# Solve v2
solution = solver.solve_v2("https://example.com/login", "6LcR_RsTAAAA...")
print(solution["gRecaptchaResponse"])
# Solve v3
solution = solver.solve_v3("https://example.com/checkout", "6LcR_RsTAAAA...", "checkout")
print(solution["gRecaptchaResponse"], solution.get("score"))
Injecting the Token
After receiving the gRecaptchaResponse token, you need to submit it with your request. There are two common approaches.
Direct Form Submission
If you are making HTTP requests directly (not using a browser), include the token as the g-recaptcha-response field in your POST body:
requests.post("https://example.com/login", data={
"email": "user@example.com",
"password": "secret",
"g-recaptcha-response": token
})
Browser Injection (Selenium/Playwright)
If you are using a headless browser, inject the token into the hidden textarea and trigger the callback:
# Selenium example
driver.execute_script(f'''
document.getElementById("g-recaptcha-response").innerHTML = "{token}";
''')
# If there's a callback function:
driver.execute_script("___grecaptcha_cfg.clients[0].aa.l.callback(arguments[0])", token)
For reCAPTCHA v3, the token is typically passed through JavaScript rather than a hidden form field. Check the site’s source to determine how it sends the token to the server.
Troubleshooting Common Issues
ERROR_CAPTCHA_UNSOLVABLE: The solver could not produce a valid token. Retry the request. If this happens consistently, double-check your site key and URL.
Token rejected by site: The token was valid but the site rejected it. Common causes:
- The token expired (reCAPTCHA tokens are valid for about 120 seconds)
- IP mismatch between solve and submission — use a proxy task type
- Wrong site key or URL
- For v3: the action string does not match what the site expects
Low v3 scores: If your v3 tokens consistently receive low scores, ensure the pageAction matches exactly and consider requesting a higher minScore. See our reCAPTCHA v3 score guide for optimization tips.
Slow solve times: reCAPTCHA v2 typically solves in 10-30 seconds. v3 is faster at 5-15 seconds. If solves are consistently slow, try switching your routing preset in the uCaptcha dashboard to “Fastest” mode.
Cost Optimization with Auto-Routing
Different CAPTCHA solving providers charge different rates for reCAPTCHA. Prices fluctuate based on demand, provider capacity, and reCAPTCHA difficulty. uCaptcha routes your tasks across five providers — CapSolver, 2Captcha, AntiCaptcha, CapMonster, and Multibot — and can automatically select the cheapest or fastest option.
In the uCaptcha dashboard, you can choose a routing preset:
- Cheapest: Minimizes cost per solve
- Fastest: Minimizes average solve time
- Reliable: Maximizes success rate
- Custom: Fine-tune with sliders for cost, speed, and reliability
For high-volume reCAPTCHA solving, the “Cheapest” preset can reduce costs significantly compared to using a single provider.
Conclusion
Solving reCAPTCHA v2 and v3 programmatically comes down to three steps: extract the site key, submit the right task type to a solver API, and inject the returned token. The specific task type varies by reCAPTCHA version — RecaptchaV2TaskProxyless for standard v2, the same with isInvisible for invisible v2, RecaptchaV3TaskProxyless for v3, and the Enterprise variants when needed.
uCaptcha simplifies this by providing a single API endpoint at api.ucaptcha.net that routes to the optimal provider for each request. You can get a free API key instantly through @uCaptcha_bot on Telegram and start solving reCAPTCHA in minutes.
Frequently Asked Questions
How do I solve reCAPTCHA v2 programmatically?
Submit the site URL and site key to a CAPTCHA solver API using the RecaptchaV2TaskProxyless task type. The API returns a g-recaptcha-response token that you inject into the target page's form submission.
What is the difference between reCAPTCHA v2 and v3?
reCAPTCHA v2 presents a visible challenge (checkbox or image selection). reCAPTCHA v3 runs invisibly and returns a score from 0.0 to 1.0 indicating how likely the user is human. Both can be solved via API.
How much does it cost to solve reCAPTCHA?
reCAPTCHA v2 typically costs $0.50–$1.50 per 1,000 solves. reCAPTCHA v3 is slightly more expensive at $1.00–$3.00 per 1,000. uCaptcha's auto-routing can find the cheapest provider automatically.
Can I solve reCAPTCHA Enterprise?
Yes. Use the RecaptchaV2EnterpriseTaskProxyless or RecaptchaV3TaskProxyless task type with the isEnterprise flag. Enterprise tokens require the enterprise site key and may need additional parameters.
Related Articles
Invisible reCAPTCHA: How It Works and How to Solve It
Learn how invisible reCAPTCHA works under the hood and how to solve it programmatically using CAPTCHA solver APIs with the isInvisible parameter.
reCAPTCHA v2 vs v3: Key Differences and Solving Strategies
Understand the differences between reCAPTCHA v2 and v3 — how each works, when sites use them, and the different approaches needed to solve each version programmatically.
Solving reCAPTCHA Enterprise: Complete Guide
How to solve reCAPTCHA Enterprise challenges — understanding enterprise site keys, action parameters, minimum scores, and the correct API task types.