Solve CAPTCHAs with two HTTP requests. Submit, poll, done.
Join the waitlist
Sign up with your email at the waitlist. We're finishing up the solver backend — you'll get a key starting with gs_ and 1,000 free solves when we launch.
curl -X POST https://gatesolve.dev/api/waitlist \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com"}'
# Response: { "status": "waitlisted", "message": "You're on the list!" }Submit a solve request
POST with your CAPTCHA details. Returns immediately with a solve ID.
Poll for the solution
GET the solve ID every 2-3 seconds. When status is solved, grab the token.
Don't know the CAPTCHA type or sitekey? Auto-detect it from any URL. No manual HTML inspection needed.
GET /api/detect/sitekey?url=https://example.com/loginReturns the primary CAPTCHA type, siteKey, and confidence score. Pass results directly to /api/solve.
# Auto-detect CAPTCHA type and sitekey from any URL
curl "https://gatesolve.dev/api/detect/sitekey?url=https://example.com/login"
# Response:
# {
# "primary": { "type": "recaptcha-v2", "siteKey": "6Le-wvkS...", "confidence": 0.95 },
# "captchas": [...],
# "pageTitle": "Login Page"
# }
# Then solve with the detected values:
curl -X POST https://gatesolve.dev/api/solve \
-H "Authorization: Bearer gs_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "type": "recaptcha-v2", "siteKey": "6Le-wvkS...", "pageUrl": "https://example.com/login" }'from gatesolve import GateSolve
import requests
# Step 1: Auto-detect
detect = requests.get(
"https://gatesolve.dev/api/detect/sitekey",
params={"url": "https://example.com/login"}
).json()
if detect["primary"]:
# Step 2: Solve with detected values
client = GateSolve(api_key="gs_YOUR_API_KEY")
token = client.solve(
type=detect["primary"]["type"],
site_key=detect["primary"]["siteKey"],
page_url="https://example.com/login",
)
print(token)# In Claude Code / Cursor, the MCP flow is:
# 1. Agent calls detect_sitekey tool with the URL
# 2. Gets back type + siteKey automatically
# 3. Calls solve_captcha with those values
# Zero manual inspection needed.Also available at /api/v1 for versioned access.
Pass your API key in the Authorization header:
Authorization: Bearer gs_YOUR_API_KEY/api/mpp/solveSubmit a CAPTCHA to be solved. Returns a solve ID for polling.
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | string | Yes | CAPTCHA type (see table below) |
| siteKey | string | Yes | The CAPTCHA site key from the target page |
| pageUrl | string | Yes | URL of the page with the CAPTCHA |
{
"id": "a1b2c3d4-e5f6-...",
"status": "pending",
"message": "Solve started. Poll for result.",
"poll": "https://gatesolve.dev/api/solve?id=a1b2c3d4-e5f6-...",
"estimated_time": "7-15 seconds"
}Poll for the result of a solve request. Call every 2-3 seconds.
{
"id": "a1b2c3d4-e5f6-...",
"status": "solved",
"token": "0.AbCdEfGhIjKlMnOpQrStUvWxYz...",
"solvedIn": "9.2s",
"type": "cloudflare-turnstile"
}{
"id": "a1b2c3d4-e5f6-...",
"status": "pending",
"message": "Solve in progress. Poll again in 2-3 seconds.",
"poll": "https://gatesolve.dev/api/solve?id=a1b2c3d4-e5f6-..."
}{
"error": "invalid_captcha_type",
"message": "Unsupported: 'foo'. Supported: cloudflare-turnstile, recaptcha-v2, recaptcha-v3, hcaptcha",
"status": 400
}# Install the Python SDK
pip install gatesolve
# Usage
from gatesolve import GateSolve
client = GateSolve(api_key="gs_YOUR_API_KEY")
token = client.solve(
type="cloudflare-turnstile",
site_key="0x4AAAAAAAB...",
page_url="https://example.com",
)
print(token) # Ready to use# 1. Submit a solve request
curl -X POST https://gatesolve.dev/api/solve \
-H "Content-Type: application/json" \
-H "Authorization: Bearer gs_YOUR_API_KEY" \
-d '{
"type": "cloudflare-turnstile",
"siteKey": "0x4AAAAAAAB...",
"pageUrl": "https://example.com"
}'
# Response: { "id": "abc-123", "status": "pending", "poll": "https://gatesolve.dev/api/solve?id=abc-123" }
# 2. Poll for result (every 2-3 seconds)
curl https://gatesolve.dev/api/solve?id=abc-123
# Response: { "id": "abc-123", "status": "solved", "token": "0.AbCdEf...", "solvedIn": "9.2s" }import requests
import time
API_KEY = "gs_YOUR_API_KEY"
# Submit solve request
resp = requests.post(
"https://gatesolve.dev/api/solve",
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}",
},
json={
"type": "cloudflare-turnstile",
"siteKey": "0x4AAAAAAAB...",
"pageUrl": "https://example.com",
},
)
solve_id = resp.json()["id"]
# Poll for result
while True:
result = requests.get(f"https://gatesolve.dev/api/solve?id={solve_id}").json()
if result["status"] == "solved":
print(f"Token: {result['token']}")
break
time.sleep(3)const API_KEY = "gs_YOUR_API_KEY";
// Submit solve request
const submit = await fetch("https://gatesolve.dev/api/solve", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`,
},
body: JSON.stringify({
type: "cloudflare-turnstile",
siteKey: "0x4AAAAAAAB...",
pageUrl: "https://example.com",
}),
});
const { id } = await submit.json();
// Poll for result
const poll = async (): Promise<string> => {
const res = await fetch(`https://gatesolve.dev/api/solve?id=${id}`);
const data = await res.json();
if (data.status === "solved") return data.token;
await new Promise((r) => setTimeout(r, 3000));
return poll();
};
const token = await poll();| Name | Type Value | Price | Avg Time | Status |
|---|---|---|---|---|
| Cloudflare Turnstile | cloudflare-turnstile | $0.02 | ~9s | Live |
| reCAPTCHA v2 | recaptcha-v2 | $0.03 | ~12s | Live |
| reCAPTCHA v3 | recaptcha-v3 | $0.02 | ~8s | Live |
| hCaptcha | hcaptcha | $0.03 | ~10s | Live |
| Status | Error | Description |
|---|---|---|
| 400 | missing_fields | Missing type, siteKey, or pageUrl |
| 400 | invalid_captcha_type | Unsupported CAPTCHA type |
| 401 | invalid_api_key | API key not found or revoked |
| 402 | free_tier_exceeded | 100 free solves used up. Use MPP for paid solves. |
| 404 | not_found | Solve request ID not found |
Instead of polling, provide a callbackUrl in your solve request. GateSolve will POST the result to your URL when the solve completes.
// Include callbackUrl in your solve request:
{
"type": "cloudflare-turnstile",
"siteKey": "0x4AAAA...",
"pageUrl": "https://example.com",
"callbackUrl": "https://your-server.com/webhook/captcha"
}
// GateSolve will POST to your callbackUrl when solved:
{
"id": "a1b2c3d4-...",
"status": "solved",
"token": "0.AbCdEfGh...",
"solvedIn": "9.2s",
"type": "cloudflare-turnstile"
}Optional: callbackUrl is not required. Polling still works as fallback.
Validation: Must be a valid http or https URL.
Timeout: Webhook POST has a 10-second timeout.
Free tier: 2 concurrent solves, 100 total per key
MPP/Paid: 10 concurrent solves, unlimited total
Polling: We recommend polling every 2-3 seconds. No rate limit on GET polls.
/api/healthService health, solver status, and solve metrics
/api/v1/typesList all supported CAPTCHA types with pricing
/api/v1/usageAUTHCheck API key quota — used, remaining, limit, and global stats
/api/v1/solve/dry-runNO AUTHValidate a solve request without consuming credits. Returns estimated time, cost, and warnings.
/api/detect?url=XNO AUTHClassify URL access blocks (captcha, js-challenge, auth-wall, rate-limited, blocked-silent)
/openapi.jsonOpenAPI 3.1 spec for programmatic API discovery
Get a free API key with 100 solves. No credit card required.