Every CAPTCHA solve costs money. At scale — thousands of solves per day — small inefficiencies compound. These 10 strategies reduce your CaptchaAI spend without sacrificing success rates.
1. Skip CAPTCHAs that don't need solving
Not every page triggers a CAPTCHA. Check before submitting:
from selenium.webdriver.common.by import By
def has_captcha(driver):
recaptcha = driver.find_elements(By.CSS_SELECTOR, ".g-recaptcha, iframe[src*='recaptcha']")
turnstile = driver.find_elements(By.CSS_SELECTOR, ".cf-turnstile")
return len(recaptcha) > 0 or len(turnstile) > 0
if has_captcha(driver):
token = solve_captcha(sitekey, page_url)
else:
print("No CAPTCHA — skipping solve")
If only 60% of pages show CAPTCHAs, this saves 40% of your solve budget.
2. Cache tokens when possible
Some sites accept the same token for multiple submissions within a short window:
import time
token_cache = {}
CACHE_TTL = 90 # seconds
def get_or_solve(sitekey, page_url):
cache_key = f"{sitekey}:{page_url}"
cached = token_cache.get(cache_key)
if cached and time.time() - cached["time"] < CACHE_TTL:
print("Using cached token")
return cached["token"]
token = solve_captcha(sitekey, page_url)
token_cache[cache_key] = {"token": token, "time": time.time()}
return token
reCAPTCHA tokens typically expire after 120 seconds. Caching within a shorter window lets you reuse tokens across sequential requests to the same endpoint.
3. Report incorrect solves
CaptchaAI refunds reported bad solves. Always report when a token is rejected:
import requests
def report_bad(task_id):
requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "reportbad",
"id": task_id,
"json": "1",
})
print(f"Reported bad solve: {task_id}")
# After using the token
if not form_submitted_successfully:
report_bad(task_id)
4. Use the cheapest CAPTCHA method
Different CAPTCHA types have different costs. Image CAPTCHAs cost less than reCAPTCHA v2. If a site serves both, check if the image CAPTCHA is sufficient.
| Type | Relative cost |
|---|---|
| Image/OCR | Lowest |
| reCAPTCHA v2 | Medium |
| reCAPTCHA v3 | Medium |
| Cloudflare Turnstile | Medium |
| reCAPTCHA Enterprise | Higher |
5. Lower reCAPTCHA v3 min_score
The default min_score of 0.9 is the hardest to solve. If the target site only checks for 0.3 or 0.5, set min_score accordingly:
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"version": "v3",
"googlekey": sitekey,
"pageurl": page_url,
"action": "submit",
"min_score": "0.3", # only request what you need
"json": "1",
})
Lower scores solve faster and cost the same, but reduce retries from token rejection.
6. Avoid solving expired CAPTCHAs
If your workflow is slow between detecting a CAPTCHA and using the token, the token might expire before submission. Solve as close to usage as possible:
# Bad: solve early, use later
token = solve_captcha(sitekey, page_url)
# ... 3 minutes of processing ...
submit_form(token) # token expired
# Good: solve right before use
# ... processing ...
token = solve_captcha(sitekey, page_url)
submit_form(token) # fresh token
7. Deduplicate requests
Avoid double-solving when multiple threads detect the same CAPTCHA:
import threading
solving_lock = threading.Lock()
solved_tokens = {}
def solve_once(sitekey, page_url):
key = f"{sitekey}:{page_url}"
with solving_lock:
if key in solved_tokens:
return solved_tokens[key]
token = solve_captcha(sitekey, page_url)
with solving_lock:
solved_tokens[key] = token
return token
8. Set proper timeouts
Don't pay for solves that take too long and are no longer useful:
# If you only need the token within 60 seconds
def solve_with_budget_timeout(sitekey, page_url, timeout=60):
try:
return solve_captcha(sitekey, page_url, timeout=timeout)
except TimeoutError:
print("Solve too slow — skipping this page")
return None
9. Monitor your spend
Track daily costs to catch anomalies:
import requests
def check_balance():
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "getbalance",
"json": "1",
}).json()
return float(resp["request"])
# Log balance at start and end of each batch
start_balance = check_balance()
# ... run batch ...
end_balance = check_balance()
spent = start_balance - end_balance
print(f"Batch cost: ${spent:.4f} ({batch_size} solves)")
print(f"Cost per solve: ${spent/batch_size:.4f}")
10. Batch image CAPTCHAs efficiently
For image CAPTCHAs, submit all images at once rather than waiting for each result before submitting the next:
from concurrent.futures import ThreadPoolExecutor, as_completed
def submit_image(base64_body):
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "base64",
"body": base64_body,
"json": "1",
})
return resp.json()["request"]
# Submit all at once
images = [load_image(f) for f in image_files]
with ThreadPoolExecutor(max_workers=20) as pool:
task_ids = list(pool.map(submit_image, images))
# Poll all at once (not sequentially)
Parallel submission doesn't reduce per-solve cost, but it reduces total time — which means fewer expired tokens and fewer re-solves.
Cost savings summary
| Strategy | Typical savings |
|---|---|
| Skip unnecessary CAPTCHAs | 20-40% |
| Cache tokens | 5-15% |
| Report bad solves | 3-8% (refunds) |
| Lower v3 min_score | Reduces retries |
| Avoid expired tokens | 5-10% |
| Deduplicate | 5-15% |
Combining these strategies can reduce your monthly spend by 30-50%.
FAQ
Does CaptchaAI offer volume discounts?
Check the CaptchaAI pricing page for current bulk rates. Higher volume typically means lower per-solve cost.
Is it worth switching CAPTCHA types to save money?
Only if the target site accepts both. Don't compromise reliability for a small cost difference.
Optimize your CAPTCHA solving costs with CaptchaAI
Get your API key at captchaai.com.
Discussions (0)
Join the conversation
Sign in to share your opinion.
Sign InNo comments yet.