CaptchaAI offers two ways to receive solved CAPTCHA results: polling (you ask repeatedly) and callback (we tell you). Both work with all CAPTCHA types. Here's when to use each.
Polling (Default)
Poll the res.php endpoint every 5 seconds until the result is ready:
import requests
import time
API_KEY = "YOUR_API_KEY"
# Submit
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": "SITE_KEY",
"pageurl": "https://example.com"
})
task_id = resp.text.split("|")[1]
# Poll
while True:
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id
})
if result.text == "CAPCHA_NOT_READY":
continue
if result.text.startswith("OK|"):
token = result.text.split("|")[1]
break
Polling Pros
- Simple to implement
- No server infrastructure needed
- Works in any environment (scripts, serverless, CLI)
- No firewall or networking concerns
Polling Cons
- Wastes requests while waiting (one every 5 seconds)
- Adds latency — you check after the solve completes, not instantly
- Higher API call volume
Callback (Webhook)
Provide a pingback URL when submitting. CaptchaAI posts the result to your URL when solving completes:
# Submit with callback URL
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": "SITE_KEY",
"pageurl": "https://example.com",
"pingback": "https://your-server.com/captcha-callback"
})
task_id = resp.text.split("|")[1]
# No polling needed — result arrives at your callback URL
CaptchaAI sends a GET request to your callback URL:
GET https://your-server.com/captcha-callback?id=TASK_ID&code=TOKEN
Callback Server (Python Flask)
from flask import Flask, request
app = Flask(__name__)
results = {}
@app.route("/captcha-callback")
def callback():
task_id = request.args.get("id")
token = request.args.get("code")
results[task_id] = token
return "OK", 200
@app.route("/get-result/<task_id>")
def get_result(task_id):
token = results.get(task_id)
if token:
return {"status": "solved", "token": token}
return {"status": "pending"}, 202
if __name__ == "__main__":
app.run(port=8080)
Callback Server (Node.js Express)
const express = require("express");
const app = express();
const results = new Map();
app.get("/captcha-callback", (req, res) => {
const { id, code } = req.query;
results.set(id, code);
res.send("OK");
});
app.get("/get-result/:taskId", (req, res) => {
const token = results.get(req.params.taskId);
if (token) {
res.json({ status: "solved", token });
} else {
res.status(202).json({ status: "pending" });
}
});
app.listen(8080);
Callback Pros
- Instant notification when solve completes
- No wasted polling requests
- More efficient for high-volume usage
- Better for async architectures
Callback Cons
- Requires a publicly accessible server
- Need to handle webhook reliability (retries, timeouts)
- More complex infrastructure
- Firewall/networking setup required
Comparison
| Factor | Polling | Callback |
|---|---|---|
| Infrastructure needed | None | Web server with public URL |
| Implementation complexity | Simple | Medium |
| Latency after solve | 0-5 seconds | Near-instant |
| API calls per solve | ~3-12 (polling requests) | 1 (submit only) |
| Best for | Scripts, small projects | High-volume, server apps |
| Works behind firewall | ✅ | ❌ (needs public URL) |
| Works in serverless | ✅ | ⚠️ (requires webhook endpoint) |
When to Use Each
Use Polling When:
- Running local scripts or CLI tools
- Building prototypes or testing
- Behind a firewall without a public server
- Processing fewer than 100 CAPTCHAs per hour
- Using serverless functions (Lambda, Cloud Functions)
Use Callbacks When:
- Processing 100+ CAPTCHAs per hour
- Running a web application with a server already available
- Building real-time systems where latency matters
- You want to minimize API call volume
- Building a CAPTCHA solving microservice
Hybrid Approach
Use callbacks with a polling fallback:
import requests
import time
API_KEY = "YOUR_API_KEY"
CALLBACK_URL = "https://your-server.com/captcha-callback"
def solve_with_fallback(site_key, page_url):
# Try callback first
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": site_key,
"pageurl": page_url,
"pingback": CALLBACK_URL
})
task_id = resp.text.split("|")[1]
# Wait for callback result (check your callback store)
for _ in range(12): # 60 seconds
time.sleep(5)
result = check_callback_store(task_id)
if result:
return result
# Fallback to polling
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id
})
if result.text.startswith("OK|"):
return result.text.split("|")[1]
raise TimeoutError()
FAQ
Does the callback URL need HTTPS?
HTTPS is recommended for security, but HTTP also works. If your callback handles sensitive data (tokens), use HTTPS.
What if my callback server is down when the result arrives?
CaptchaAI may retry the callback. As a safety net, you can always fall back to polling the result endpoint.
Can I use the same callback URL for multiple tasks?
Yes. Each callback includes the id parameter so you can match results to their tasks.
Discussions (0)
Join the conversation
Sign in to share your opinion.
Sign InNo comments yet.