# Changelog (/docs/changelog) What's new in NoCaptchaAI. For the full product log, see [nocaptchaai.com/logs](https://nocaptchaai.com/logs). ## NoCaptcha v2 — June 2026 [#nocaptcha-v2--june-2026] Our biggest release yet. A fresh look, a rebuilt documentation site, an overhauled API v2, agentic-first solving, and a faster, more reliable core. ### A fresh new look [#a-fresh-new-look] * Refreshed brand identity built around teal (`#14b8a6`). * Brand-new documentation site on **Fumadocs + TanStack Start**. * Interactive API playground, multi-language SDKs, full-text search, and `llms.txt`. ### API v2 overhaul [#api-v2-overhaul] * Reworked solver and billing API at `https://api.nocaptchaai.com`. * Task-based flow with `/createTask` + `/getTaskResult`, plus a sync `/solve` endpoint. * Balance and reporting endpoints, with cleaner task types and responses. ### Agentic-first solving [#agentic-first-solving] * First-class support for AI agents via a dedicated **MCP server**. * Guides for Claude Code, Codex, Cursor, Cline, and more. * Any agent can now solve captchas as a tool. ### Faster, more stable core [#faster-more-stable-core] * Service core re-optimised with **Go and Rust**. * Lower latency and higher reliability under load. ### Better support [#better-support] * Improved docs and error-handling guidance. * Reach us on Discord, Telegram, or email. # AwsWaf (/docs/imagetasks/awswaf) ## Create a task [#create-a-task] `POST https://api.nocaptchaai.com/createTask` ```json { "clientKey": "YOUR_API_KEY", "task": { "type": "AWSWAFTask", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" } } ``` Returns a `taskId`: ```json { "errorId": 0, "status": "idle", "taskId": "abc123" } ``` ## Get the result [#get-the-result] Poll `POST https://api.nocaptchaai.com/getTaskResult` until `status` is `ready`: ```json { "clientKey": "YOUR_API_KEY", "taskId": "abc123" } ``` ```json { "errorId": 0, "status": "ready", "solution": { "token": "0.WdWV79pV71mHDjQ...." } } ``` ## Code example [#code-example] ```python import requests, time API_KEY = "YOUR_API_KEY"; BASE = "https://api.nocaptchaai.com" task = requests.post(f"{BASE}/createTask", json={"clientKey": API_KEY, "task": { "type": "AWSWAFTask", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" }}).json() tid = task["taskId"] while True: time.sleep(2) res = requests.post(f"{BASE}/getTaskResult", json={"clientKey": API_KEY, "taskId": tid}).json() if res.get("status") == "ready": print(res["solution"]); break if res.get("status") == "failed" or res.get("errorId"): raise SystemExit(res) ``` ```js const API_KEY = "YOUR_API_KEY", BASE = "https://api.nocaptchaai.com"; const create = await fetch(`${BASE}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "AWSWAFTask", websiteURL: "https://example.com", websiteKey: "YOUR_WEBSITE_KEY" } }) }).then(r => r.json()); let out; while (true) { await new Promise(r => setTimeout(r, 2000)); const res = await fetch(`${BASE}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId: create.taskId }) }).then(r => r.json()); if (res.status === "ready") { out = res.solution; break; } if (res.status === "failed" || res.errorId) throw new Error(JSON.stringify(res)); } console.log(out); ``` ```bash curl -X POST https://api.nocaptchaai.com/createTask -H "Content-Type: application/json" -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "AWSWAFTask", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" } }' ``` ## Next steps [#next-steps] # Binance (/docs/imagetasks/binance) Binance has no dedicated template. Solve it via the generic Classification task by sending the captcha image in `body`. ## Create a task [#create-a-task] `POST https://api.nocaptchaai.com/createTask` ```json { "clientKey": "YOUR_API_KEY", "task": { "type": "ClassificationTask", "body": "/9j/4AAQSkZJRgABAQ....", "question": "Slide to complete the puzzle", "questionType": "image" } } ``` Returns a `taskId`: ```json { "errorId": 0, "status": "idle", "taskId": "abc123" } ``` ## Get the result [#get-the-result] Poll `POST https://api.nocaptchaai.com/getTaskResult` until `status` is `ready`: ```json { "clientKey": "YOUR_API_KEY", "taskId": "abc123" } ``` ```json { "errorId": 0, "status": "ready", "solution": { "objects": [0, 3, 5] } } ``` ## Code example [#code-example] ```python import requests, time API_KEY = "YOUR_API_KEY"; BASE = "https://api.nocaptchaai.com" task = requests.post(f"{BASE}/createTask", json={"clientKey": API_KEY, "task": { "type": "ClassificationTask", "body": "/9j/4AAQSkZJRgABAQ....", "question": "Slide to complete the puzzle", "questionType": "image" }}).json() tid = task["taskId"] while True: time.sleep(2) res = requests.post(f"{BASE}/getTaskResult", json={"clientKey": API_KEY, "taskId": tid}).json() if res.get("status") == "ready": print(res["solution"]); break if res.get("status") == "failed" or res.get("errorId"): raise SystemExit(res) ``` ```js const API_KEY = "YOUR_API_KEY", BASE = "https://api.nocaptchaai.com"; const create = await fetch(`${BASE}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "ClassificationTask", body: "/9j/4AAQSkZJRgABAQ....", question: "Slide to complete the puzzle", questionType: "image" } }) }).then(r => r.json()); let out; while (true) { await new Promise(r => setTimeout(r, 2000)); const res = await fetch(`${BASE}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId: create.taskId }) }).then(r => r.json()); if (res.status === "ready") { out = res.solution; break; } if (res.status === "failed" || res.errorId) throw new Error(JSON.stringify(res)); } console.log(out); ``` ```bash curl -X POST https://api.nocaptchaai.com/createTask -H "Content-Type: application/json" -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "ClassificationTask", "body": "/9j/4AAQSkZJRgABAQ....", "question": "Slide to complete the puzzle", "questionType": "image" } }' ``` ## Next steps [#next-steps] # BLS Captcha (/docs/imagetasks/bls) ## Create a task [#create-a-task] `POST https://api.nocaptchaai.com/createTask` ```json { "clientKey": "YOUR_API_KEY", "task": { "type": "BLSCaptchaTask", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" } } ``` Returns a `taskId`: ```json { "errorId": 0, "status": "idle", "taskId": "abc123" } ``` ## Get the result [#get-the-result] Poll `POST https://api.nocaptchaai.com/getTaskResult` until `status` is `ready`: ```json { "clientKey": "YOUR_API_KEY", "taskId": "abc123" } ``` ```json { "errorId": 0, "status": "ready", "solution": { "token": "0.WdWV79pV71mHDjQ...." } } ``` ## Code example [#code-example] ```python import requests, time API_KEY = "YOUR_API_KEY"; BASE = "https://api.nocaptchaai.com" task = requests.post(f"{BASE}/createTask", json={"clientKey": API_KEY, "task": { "type": "BLSCaptchaTask", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" }}).json() tid = task["taskId"] while True: time.sleep(2) res = requests.post(f"{BASE}/getTaskResult", json={"clientKey": API_KEY, "taskId": tid}).json() if res.get("status") == "ready": print(res["solution"]); break if res.get("status") == "failed" or res.get("errorId"): raise SystemExit(res) ``` ```js const API_KEY = "YOUR_API_KEY", BASE = "https://api.nocaptchaai.com"; const create = await fetch(`${BASE}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "BLSCaptchaTask", websiteURL: "https://example.com", websiteKey: "YOUR_WEBSITE_KEY" } }) }).then(r => r.json()); let out; while (true) { await new Promise(r => setTimeout(r, 2000)); const res = await fetch(`${BASE}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId: create.taskId }) }).then(r => r.json()); if (res.status === "ready") { out = res.solution; break; } if (res.status === "failed" || res.errorId) throw new Error(JSON.stringify(res)); } console.log(out); ``` ```bash curl -X POST https://api.nocaptchaai.com/createTask -H "Content-Type: application/json" -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "BLSCaptchaTask", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" } }' ``` ## Next steps [#next-steps] # GeeTest v3 (/docs/imagetasks/geetestv3) ## Create a task [#create-a-task] `POST https://api.nocaptchaai.com/createTask` ```json { "clientKey": "YOUR_API_KEY", "task": { "type": "GeeTestTaskProxyLess", "websiteURL": "https://www.geetest.com/en/demo", "gt": "019924a82c70bb123aae259222442445" } } ``` Returns a `taskId`: ```json { "errorId": 0, "status": "idle", "taskId": "abc123" } ``` ## Get the result [#get-the-result] Poll `POST https://api.nocaptchaai.com/getTaskResult` until `status` is `ready`: ```json { "clientKey": "YOUR_API_KEY", "taskId": "abc123" } ``` ```json { "errorId": 0, "status": "ready", "solution": { "token": "0.WdWV79pV71mHDjQ...." } } ``` ## Code example [#code-example] ```python import requests, time API_KEY = "YOUR_API_KEY"; BASE = "https://api.nocaptchaai.com" task = requests.post(f"{BASE}/createTask", json={"clientKey": API_KEY, "task": { "type": "GeeTestTaskProxyLess", "websiteURL": "https://www.geetest.com/en/demo", "gt": "019924a82c70bb123aae259222442445" }}).json() tid = task["taskId"] while True: time.sleep(2) res = requests.post(f"{BASE}/getTaskResult", json={"clientKey": API_KEY, "taskId": tid}).json() if res.get("status") == "ready": print(res["solution"]); break if res.get("status") == "failed" or res.get("errorId"): raise SystemExit(res) ``` ```js const API_KEY = "YOUR_API_KEY", BASE = "https://api.nocaptchaai.com"; const create = await fetch(`${BASE}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "GeeTestTaskProxyLess", websiteURL: "https://www.geetest.com/en/demo", gt: "019924a82c70bb123aae259222442445" } }) }).then(r => r.json()); let out; while (true) { await new Promise(r => setTimeout(r, 2000)); const res = await fetch(`${BASE}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId: create.taskId }) }).then(r => r.json()); if (res.status === "ready") { out = res.solution; break; } if (res.status === "failed" || res.errorId) throw new Error(JSON.stringify(res)); } console.log(out); ``` ```bash curl -X POST https://api.nocaptchaai.com/createTask -H "Content-Type: application/json" -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "GeeTestTaskProxyLess", "websiteURL": "https://www.geetest.com/en/demo", "gt": "019924a82c70bb123aae259222442445" } }' ``` ## Next steps [#next-steps] # GeeTestV4 (/docs/imagetasks/geetestv4) ## Create a task [#create-a-task] `POST https://api.nocaptchaai.com/createTask` ```json { "clientKey": "YOUR_API_KEY", "task": { "type": "GeeTestTaskProxyLess", "websiteURL": "https://www.geetest.com/en/demo", "gt": "019924a82c70bb123aae259222442445" } } ``` Returns a `taskId`: ```json { "errorId": 0, "status": "idle", "taskId": "abc123" } ``` ## Get the result [#get-the-result] Poll `POST https://api.nocaptchaai.com/getTaskResult` until `status` is `ready`: ```json { "clientKey": "YOUR_API_KEY", "taskId": "abc123" } ``` ```json { "errorId": 0, "status": "ready", "solution": { "token": "0.WdWV79pV71mHDjQ...." } } ``` ## Code example [#code-example] ```python import requests, time API_KEY = "YOUR_API_KEY"; BASE = "https://api.nocaptchaai.com" task = requests.post(f"{BASE}/createTask", json={"clientKey": API_KEY, "task": { "type": "GeeTestTaskProxyLess", "websiteURL": "https://www.geetest.com/en/demo", "gt": "019924a82c70bb123aae259222442445" }}).json() tid = task["taskId"] while True: time.sleep(2) res = requests.post(f"{BASE}/getTaskResult", json={"clientKey": API_KEY, "taskId": tid}).json() if res.get("status") == "ready": print(res["solution"]); break if res.get("status") == "failed" or res.get("errorId"): raise SystemExit(res) ``` ```js const API_KEY = "YOUR_API_KEY", BASE = "https://api.nocaptchaai.com"; const create = await fetch(`${BASE}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "GeeTestTaskProxyLess", websiteURL: "https://www.geetest.com/en/demo", gt: "019924a82c70bb123aae259222442445" } }) }).then(r => r.json()); let out; while (true) { await new Promise(r => setTimeout(r, 2000)); const res = await fetch(`${BASE}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId: create.taskId }) }).then(r => r.json()); if (res.status === "ready") { out = res.solution; break; } if (res.status === "failed" || res.errorId) throw new Error(JSON.stringify(res)); } console.log(out); ``` ```bash curl -X POST https://api.nocaptchaai.com/createTask -H "Content-Type: application/json" -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "GeeTestTaskProxyLess", "websiteURL": "https://www.geetest.com/en/demo", "gt": "019924a82c70bb123aae259222442445" } }' ``` ## Next steps [#next-steps] # ImageToText (/docs/imagetasks/imagetotext) ## Create a task [#create-a-task] `POST https://api.nocaptchaai.com/createTask` ```json { "clientKey": "YOUR_API_KEY", "task": { "type": "ImageToTextTask", "body": "/9j/4AAQSkZJRgABAQ....", "case": false, "numeric": 0, "math": false, "minLength": 0, "maxLength": 0 } } ``` Returns a `taskId`: ```json { "errorId": 0, "status": "idle", "taskId": "abc123" } ``` ## Get the result [#get-the-result] Poll `POST https://api.nocaptchaai.com/getTaskResult` until `status` is `ready`: ```json { "clientKey": "YOUR_API_KEY", "taskId": "abc123" } ``` ```json { "errorId": 0, "status": "ready", "solution": { "text": "aB3xQ" } } ``` ## Code example [#code-example] ```python import requests, time API_KEY = "YOUR_API_KEY"; BASE = "https://api.nocaptchaai.com" task = requests.post(f"{BASE}/createTask", json={"clientKey": API_KEY, "task": { "type": "ImageToTextTask", "body": "/9j/4AAQSkZJRgABAQ....", "case": False, "numeric": 0, "math": False, "minLength": 0, "maxLength": 0 }}).json() tid = task["taskId"] while True: time.sleep(2) res = requests.post(f"{BASE}/getTaskResult", json={"clientKey": API_KEY, "taskId": tid}).json() if res.get("status") == "ready": print(res["solution"]); break if res.get("status") == "failed" or res.get("errorId"): raise SystemExit(res) ``` ```js const API_KEY = "YOUR_API_KEY", BASE = "https://api.nocaptchaai.com"; const create = await fetch(`${BASE}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "ImageToTextTask", body: "/9j/4AAQSkZJRgABAQ....", case: false, numeric: 0, math: false, minLength: 0, maxLength: 0 } }) }).then(r => r.json()); let out; while (true) { await new Promise(r => setTimeout(r, 2000)); const res = await fetch(`${BASE}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId: create.taskId }) }).then(r => r.json()); if (res.status === "ready") { out = res.solution; break; } if (res.status === "failed" || res.errorId) throw new Error(JSON.stringify(res)); } console.log(out); ``` ```bash curl -X POST https://api.nocaptchaai.com/createTask -H "Content-Type: application/json" -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "ImageToTextTask", "body": "/9j/4AAQSkZJRgABAQ....", "case": false, "numeric": 0, "math": false, "minLength": 0, "maxLength": 0 } }' ``` ## Next steps [#next-steps] # MTCaptcha (/docs/imagetasks/mtcaptcha) ## Create a task [#create-a-task] `POST https://api.nocaptchaai.com/createTask` ```json { "clientKey": "YOUR_API_KEY", "task": { "type": "MTCaptchaTask", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" } } ``` Returns a `taskId`: ```json { "errorId": 0, "status": "idle", "taskId": "abc123" } ``` ## Get the result [#get-the-result] Poll `POST https://api.nocaptchaai.com/getTaskResult` until `status` is `ready`: ```json { "clientKey": "YOUR_API_KEY", "taskId": "abc123" } ``` ```json { "errorId": 0, "status": "ready", "solution": { "token": "0.WdWV79pV71mHDjQ...." } } ``` ## Code example [#code-example] ```python import requests, time API_KEY = "YOUR_API_KEY"; BASE = "https://api.nocaptchaai.com" task = requests.post(f"{BASE}/createTask", json={"clientKey": API_KEY, "task": { "type": "MTCaptchaTask", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" }}).json() tid = task["taskId"] while True: time.sleep(2) res = requests.post(f"{BASE}/getTaskResult", json={"clientKey": API_KEY, "taskId": tid}).json() if res.get("status") == "ready": print(res["solution"]); break if res.get("status") == "failed" or res.get("errorId"): raise SystemExit(res) ``` ```js const API_KEY = "YOUR_API_KEY", BASE = "https://api.nocaptchaai.com"; const create = await fetch(`${BASE}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "MTCaptchaTask", websiteURL: "https://example.com", websiteKey: "YOUR_WEBSITE_KEY" } }) }).then(r => r.json()); let out; while (true) { await new Promise(r => setTimeout(r, 2000)); const res = await fetch(`${BASE}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId: create.taskId }) }).then(r => r.json()); if (res.status === "ready") { out = res.solution; break; } if (res.status === "failed" || res.errorId) throw new Error(JSON.stringify(res)); } console.log(out); ``` ```bash curl -X POST https://api.nocaptchaai.com/createTask -H "Content-Type: application/json" -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "MTCaptchaTask", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" } }' ``` ## Next steps [#next-steps] # ReCaptcha v2 (/docs/imagetasks/recaptcha) ## Create a task [#create-a-task] `POST https://api.nocaptchaai.com/createTask` ```json { "clientKey": "YOUR_API_KEY", "task": { "type": "ReCaptchaV2TaskProxyLess", "websiteURL": "https://www.google.com/recaptcha/api2/demo", "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-" } } ``` Returns a `taskId`: ```json { "errorId": 0, "status": "idle", "taskId": "abc123" } ``` ## Get the result [#get-the-result] Poll `POST https://api.nocaptchaai.com/getTaskResult` until `status` is `ready`: ```json { "clientKey": "YOUR_API_KEY", "taskId": "abc123" } ``` ```json { "errorId": 0, "status": "ready", "solution": { "token": "0.WdWV79pV71mHDjQ...." } } ``` ## Code example [#code-example] ```python import requests, time API_KEY = "YOUR_API_KEY"; BASE = "https://api.nocaptchaai.com" task = requests.post(f"{BASE}/createTask", json={"clientKey": API_KEY, "task": { "type": "ReCaptchaV2TaskProxyLess", "websiteURL": "https://www.google.com/recaptcha/api2/demo", "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-" }}).json() tid = task["taskId"] while True: time.sleep(2) res = requests.post(f"{BASE}/getTaskResult", json={"clientKey": API_KEY, "taskId": tid}).json() if res.get("status") == "ready": print(res["solution"]); break if res.get("status") == "failed" or res.get("errorId"): raise SystemExit(res) ``` ```js const API_KEY = "YOUR_API_KEY", BASE = "https://api.nocaptchaai.com"; const create = await fetch(`${BASE}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "ReCaptchaV2TaskProxyLess", websiteURL: "https://www.google.com/recaptcha/api2/demo", websiteKey: "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-" } }) }).then(r => r.json()); let out; while (true) { await new Promise(r => setTimeout(r, 2000)); const res = await fetch(`${BASE}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId: create.taskId }) }).then(r => r.json()); if (res.status === "ready") { out = res.solution; break; } if (res.status === "failed" || res.errorId) throw new Error(JSON.stringify(res)); } console.log(out); ``` ```bash curl -X POST https://api.nocaptchaai.com/createTask -H "Content-Type: application/json" -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "ReCaptchaV2TaskProxyLess", "websiteURL": "https://www.google.com/recaptcha/api2/demo", "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-" } }' ``` ## Next steps [#next-steps] # Tiktok (/docs/imagetasks/tiktok) ## Create a task [#create-a-task] `POST https://api.nocaptchaai.com/createTask` ```json { "clientKey": "YOUR_API_KEY", "task": { "type": "TikTokTask", "websiteURL": "https://www.tiktok.com", "websiteKey": "YOUR_WEBSITE_KEY" } } ``` Returns a `taskId`: ```json { "errorId": 0, "status": "idle", "taskId": "abc123" } ``` ## Get the result [#get-the-result] Poll `POST https://api.nocaptchaai.com/getTaskResult` until `status` is `ready`: ```json { "clientKey": "YOUR_API_KEY", "taskId": "abc123" } ``` ```json { "errorId": 0, "status": "ready", "solution": { "token": "0.WdWV79pV71mHDjQ...." } } ``` ## Code example [#code-example] ```python import requests, time API_KEY = "YOUR_API_KEY"; BASE = "https://api.nocaptchaai.com" task = requests.post(f"{BASE}/createTask", json={"clientKey": API_KEY, "task": { "type": "TikTokTask", "websiteURL": "https://www.tiktok.com", "websiteKey": "YOUR_WEBSITE_KEY" }}).json() tid = task["taskId"] while True: time.sleep(2) res = requests.post(f"{BASE}/getTaskResult", json={"clientKey": API_KEY, "taskId": tid}).json() if res.get("status") == "ready": print(res["solution"]); break if res.get("status") == "failed" or res.get("errorId"): raise SystemExit(res) ``` ```js const API_KEY = "YOUR_API_KEY", BASE = "https://api.nocaptchaai.com"; const create = await fetch(`${BASE}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "TikTokTask", websiteURL: "https://www.tiktok.com", websiteKey: "YOUR_WEBSITE_KEY" } }) }).then(r => r.json()); let out; while (true) { await new Promise(r => setTimeout(r, 2000)); const res = await fetch(`${BASE}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId: create.taskId }) }).then(r => r.json()); if (res.status === "ready") { out = res.solution; break; } if (res.status === "failed" || res.errorId) throw new Error(JSON.stringify(res)); } console.log(out); ``` ```bash curl -X POST https://api.nocaptchaai.com/createTask -H "Content-Type: application/json" -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "TikTokTask", "websiteURL": "https://www.tiktok.com", "websiteKey": "YOUR_WEBSITE_KEY" } }' ``` ## Next steps [#next-steps] # Document Index (/docs) Welcome to the **NoCaptchaAI** docs. Solve captchas programmatically with our AI-powered API, or use the browser extension for no-code solving. ## Get started [#get-started] ## Base URL [#base-url] All API requests go to: ``` https://api.nocaptchaai.com ``` Authenticate by passing your API key as `clientKey` in the request body (or the `apikey` header for the synchronous `/solve` endpoint). ## Supported captcha types [#supported-captcha-types] ## FAQ [#faq] Create a free account at [nocaptchaai.com/manage](https://nocaptchaai.com/manage) and copy your API key from the dashboard. Pass it as `clientKey` in the request body (or the `apikey` header for the synchronous `/solve` endpoint). See [Authentication](/docs/start/authentication). `/createTask` is asynchronous — you get a `taskId` and poll `/getTaskResult` until it's ready. `/solve` is synchronous — you send the challenge and get the solution back in one request. Use the async flow for token captchas (Turnstile, reCAPTCHA) and the sync flow for image/OCR tasks. hCaptcha, reCAPTCHA, Cloudflare Turnstile, GeeTest v3/v4, AWS WAF, MTCaptcha, Binance, TikTok, BLS, image-to-text and more. Browse [Token Tasks](/docs/token/turnstile) and [Image Tasks](/docs/imagetasks/recaptcha). The API returns an error `code` with a `msg` and sometimes `retryAfterSec`. Rate-limit and capacity errors are retryable with backoff; account/key errors are not. See the [Error Handling](/docs/guides/error-handling) guide. Yes — install the [browser extension](/docs/guides/browser-extension) for Chrome or Firefox to solve captchas automatically without writing any code. # Authentication (/docs/start/authentication) Every request to the NoCaptchaAI API must be authenticated with your API key. This page covers where to find your key and the two ways to send it. ## Get an API key [#get-an-api-key] Sign in to the [NoCaptchaAI dashboard](https://nocaptchaai.com/manage) and copy your API key from the account page. The same key works across the async (`/createTask`), sync (`/solve`), and `/balance` endpoints. The API base URL is: ```text https://api.nocaptchaai.com ``` Treat your API key like a password. Never embed it in client-side code, browser extensions, mobile apps, or public repositories. Always call the API from a server you control, and rotate the key immediately if it leaks. ## Authentication methods [#authentication-methods] There are two methods, depending on the endpoint you call. | Method | Where the key goes | Endpoints | | ----------- | ------------------ | ----------------------------------------- | | `clientKey` | JSON request body | `POST /createTask`, `POST /getTaskResult` | | `apikey` | Request header | `POST /solve` | ### Method 1 — `clientKey` in the JSON body [#method-1--clientkey-in-the-json-body] The async flow passes the key as a `clientKey` field inside the request body. ```bash curl -X POST https://api.nocaptchaai.com/createTask \ -H "Content-Type: application/json" \ -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "ImageToTextTask", "body": "BASE64_IMAGE" } }' ``` ```python import requests resp = requests.post( "https://api.nocaptchaai.com/createTask", json={ "clientKey": "YOUR_API_KEY", "task": { "type": "ImageToTextTask", "body": "BASE64_IMAGE", }, }, ) print(resp.json()) ``` ```js const resp = await fetch("https://api.nocaptchaai.com/createTask", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: "YOUR_API_KEY", task: { type: "ImageToTextTask", body: "BASE64_IMAGE", }, }), }); console.log(await resp.json()); ``` The same `clientKey` is required when you poll for the result: ```bash curl -X POST https://api.nocaptchaai.com/getTaskResult \ -H "Content-Type: application/json" \ -d '{ "clientKey": "YOUR_API_KEY", "taskId": "TASK_ID" }' ``` ### Method 2 — `apikey` request header [#method-2--apikey-request-header] The synchronous `/solve` endpoint reads the key from an `apikey` header instead of the body. ```bash curl -X POST https://api.nocaptchaai.com/solve \ -H "apikey: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "ImageToTextTask", "body": "BASE64_IMAGE" }' ``` ```python import requests resp = requests.post( "https://api.nocaptchaai.com/solve", headers={"apikey": "YOUR_API_KEY"}, json={ "type": "ImageToTextTask", "body": "BASE64_IMAGE", }, ) print(resp.status_code, resp.json()) ``` ```js const resp = await fetch("https://api.nocaptchaai.com/solve", { method: "POST", headers: { apikey: "YOUR_API_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ type: "ImageToTextTask", body: "BASE64_IMAGE", }), }); console.log(resp.status, await resp.json()); ``` ## Check your balance [#check-your-balance] You can verify a key and see remaining credits with the `/balance` endpoint, which takes the key as the `apiKey` query parameter: ```bash curl "https://api.nocaptchaai.com/balance?apiKey=YOUR_API_KEY" ``` A `KEY_DOES_NOT_EXIST` error (code `1`) means the key is missing or malformed. See [Error Handling](/docs/guides/error-handling) for the full list of error codes. # Error Codes (/docs/start/errorcodes) Error Codes # Error Codes [#error-codes] This document provides a complete reference for understanding error codes returned by NoCaptcha AI systems. *** ## Glossary [#glossary] | Field | Description | | ------------------ | ---------------------------------------------- | | `errorId` | Unique internal error identifier. | | `errorCode` | Public-facing error code. | | `errorDescription` | Human-readable explanation of the error. | | `status` | Current status of the request or system state. | *** #### Meaning [#meaning] | status | errorId | | ------ | ---------------- | | 200 | `1` = error | | 400 | `0` = successful | | 400 | `0` = successful | *** ## Example Response [#example-response] ```json { "errorId": 1, "errorCode": 0, "errorDescription": null, "status": "ready" } ``` # Quickstart (/docs/start/quickstart) Solve your first captcha with the NoCaptchaAI API in three short steps: create a task, poll for the result, and use the returned token. **Base URL:** `https://api.nocaptchaai.com` — Grab your free API key from the [NoCaptchaAI dashboard](https://nocaptchaai.com/manage). ## Solve a captcha with the API [#solve-a-captcha-with-the-api] The API is asynchronous: you submit a task, then poll for its result. The example below solves a Cloudflare Turnstile challenge, but the same flow works for every supported captcha type. ### Get your API key [#get-your-api-key] Sign in to the [NoCaptchaAI dashboard](https://nocaptchaai.com/manage) and copy your `clientKey` from the API section. Keep it secret — treat it like a password. Export it so the snippets below can pick it up: ```bash export NOCAPTCHAAI_KEY="YOUR_API_KEY" ``` ### Create a task [#create-a-task] Send a `POST` request to `/createTask` describing the challenge you want solved. ```bash curl -s -X POST https://api.nocaptchaai.com/createTask \ -H "Content-Type: application/json" \ -d '{ "clientKey": "'"$NOCAPTCHAAI_KEY"'", "task": { "type": "AntiTurnstileTask", "websiteURL": "https://example.com", "websiteKey": "0x4AAAAAAA..." } }' ``` ```python import os import requests API_KEY = os.environ["NOCAPTCHAAI_KEY"] BASE_URL = "https://api.nocaptchaai.com" resp = requests.post( f"{BASE_URL}/createTask", json={ "clientKey": API_KEY, "task": { "type": "AntiTurnstileTask", "websiteURL": "https://example.com", "websiteKey": "0x4AAAAAAA...", }, }, ) resp.raise_for_status() task_id = resp.json()["taskId"] print("taskId:", task_id) ``` ```javascript const API_KEY = process.env.NOCAPTCHAAI_KEY; const BASE_URL = "https://api.nocaptchaai.com"; const res = await fetch(`${BASE_URL}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "AntiTurnstileTask", websiteURL: "https://example.com", websiteKey: "0x4AAAAAAA...", }, }), }); const { taskId } = await res.json(); console.log("taskId:", taskId); ``` A successful response returns a `taskId` you'll use to fetch the result: ```json { "errorId": 0, "status": "idle", "taskId": "8f0e5b2a-1c3d-4e6f-9a0b-1c2d3e4f5a6b" } ``` ### Poll for the result [#poll-for-the-result] Send the `taskId` to `/getTaskResult` until `status` is `"ready"`. While the task is still being solved you'll get `status: "processing"` — wait a couple of seconds and try again. ```bash curl -s -X POST https://api.nocaptchaai.com/getTaskResult \ -H "Content-Type: application/json" \ -d '{ "clientKey": "'"$NOCAPTCHAAI_KEY"'", "taskId": "8f0e5b2a-1c3d-4e6f-9a0b-1c2d3e4f5a6b" }' ``` ```python import time while True: resp = requests.post( f"{BASE_URL}/getTaskResult", json={"clientKey": API_KEY, "taskId": task_id}, ) resp.raise_for_status() result = resp.json() if result["status"] == "ready": break time.sleep(2) token = result["solution"]["token"] print("token:", token) ``` ```javascript let result; while (true) { const res = await fetch(`${BASE_URL}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId }), }); result = await res.json(); if (result.status === "ready") break; await new Promise((r) => setTimeout(r, 2000)); } const token = result.solution.token; console.log("token:", token); ``` When the task is solved, the response includes the token under `solution.token`: ```json { "errorId": 0, "status": "ready", "solution": { "token": "0.aBcDeFgH...turnstile-response-token" } } ``` ### Use the solution [#use-the-solution] The returned `solution.token` is the captcha response you submit to the target site — exactly as a real browser would. For Turnstile and reCAPTCHA, place it in the form field the site expects (for example `cf-turnstile-response` or `g-recaptcha-response`) and send your request as usual. Tokens are single-use and short-lived. Submit each token immediately and request a fresh task for every new attempt. ## No-code option [#no-code-option] Prefer not to write code? Install the browser extension and let NoCaptchaAI solve captchas automatically as you browse — just sign in with the same API key. ## Next steps [#next-steps] # Cloudflare Task (/docs/token/cloudflare) ## Create a task [#create-a-task] `POST https://api.nocaptchaai.com/createTask` ```json { "clientKey": "YOUR_API_KEY", "task": { "type": "CloudflareTurnstileTaskProxyLess", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" } } ``` The API returns a `taskId`: ```json { "errorId": 0, "status": "idle", "taskId": "CFQ2yP5DOL" } ``` ## Get the result [#get-the-result] Poll `POST https://api.nocaptchaai.com/getTaskResult` until `status` is `ready`: ```json { "clientKey": "YOUR_API_KEY", "taskId": "CFQ2yP5DOL" } ``` ```json { "errorId": 0, "status": "ready", "solution": { "token": "0.WdWV79pV71mHDjQ...." } } ``` ## Code example [#code-example] ```python # pip install requests import requests, time API_KEY = "YOUR_API_KEY" BASE = "https://api.nocaptchaai.com" task = requests.post(f"{BASE}/createTask", json={ "clientKey": API_KEY, "task": { "type": "CloudflareTurnstileTaskProxyLess", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY", } }).json() task_id = task["taskId"] while True: time.sleep(2) res = requests.post(f"{BASE}/getTaskResult", json={"clientKey": API_KEY, "taskId": task_id}).json() if res.get("status") == "ready": print(res["solution"]["token"]); break if res.get("status") == "failed" or res.get("errorId"): raise SystemExit(res) ``` ```js // Node 18+ const API_KEY = "YOUR_API_KEY"; const BASE = "https://api.nocaptchaai.com"; const create = await fetch(`${BASE}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "CloudflareTurnstileTaskProxyLess", websiteURL: "https://example.com", websiteKey: "YOUR_WEBSITE_KEY", }, }), }).then(r => r.json()); let solution; while (true) { await new Promise(r => setTimeout(r, 2000)); const res = await fetch(`${BASE}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId: create.taskId }), }).then(r => r.json()); if (res.status === "ready") { solution = res.solution.token; break; } if (res.status === "failed" || res.errorId) throw new Error(JSON.stringify(res)); } console.log(solution); ``` ```bash curl -X POST https://api.nocaptchaai.com/createTask \ -H "Content-Type: application/json" \ -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "CloudflareTurnstileTaskProxyLess", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" } }' ``` ## Next steps [#next-steps] # GeeTestv4 Task (/docs/token/geetestv4) ## Create a task [#create-a-task] `POST https://api.nocaptchaai.com/createTask` ```json { "clientKey": "YOUR_API_KEY", "task": { "type": "GeeTestTaskProxyLess", "websiteURL": "https://www.geetest.com/en/demo", "gt": "019924a82c70bb123aae259222442445" } } ``` The API returns a `taskId`: ```json { "errorId": 0, "status": "idle", "taskId": "CFQ2yP5DOL" } ``` ## Get the result [#get-the-result] Poll `POST https://api.nocaptchaai.com/getTaskResult` until `status` is `ready`: ```json { "clientKey": "YOUR_API_KEY", "taskId": "CFQ2yP5DOL" } ``` ```json { "errorId": 0, "status": "ready", "solution": { "token": "0.WdWV79pV71mHDjQ...." } } ``` ## Code example [#code-example] ```python # pip install requests import requests, time API_KEY = "YOUR_API_KEY" BASE = "https://api.nocaptchaai.com" task = requests.post(f"{BASE}/createTask", json={ "clientKey": API_KEY, "task": { "type": "GeeTestTaskProxyLess", "websiteURL": "https://www.geetest.com/en/demo", "gt": "019924a82c70bb123aae259222442445", } }).json() task_id = task["taskId"] while True: time.sleep(2) res = requests.post(f"{BASE}/getTaskResult", json={"clientKey": API_KEY, "taskId": task_id}).json() if res.get("status") == "ready": print(res["solution"]["token"]); break if res.get("status") == "failed" or res.get("errorId"): raise SystemExit(res) ``` ```js // Node 18+ const API_KEY = "YOUR_API_KEY"; const BASE = "https://api.nocaptchaai.com"; const create = await fetch(`${BASE}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "GeeTestTaskProxyLess", websiteURL: "https://www.geetest.com/en/demo", gt: "019924a82c70bb123aae259222442445", }, }), }).then(r => r.json()); let solution; while (true) { await new Promise(r => setTimeout(r, 2000)); const res = await fetch(`${BASE}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId: create.taskId }), }).then(r => r.json()); if (res.status === "ready") { solution = res.solution.token; break; } if (res.status === "failed" || res.errorId) throw new Error(JSON.stringify(res)); } console.log(solution); ``` ```bash curl -X POST https://api.nocaptchaai.com/createTask \ -H "Content-Type: application/json" \ -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "GeeTestTaskProxyLess", "websiteURL": "https://www.geetest.com/en/demo", "gt": "019924a82c70bb123aae259222442445" } }' ``` ## Next steps [#next-steps] # MTCaptcha Task (/docs/token/mtcaptcha) ## Create a task [#create-a-task] `POST https://api.nocaptchaai.com/createTask` ```json { "clientKey": "YOUR_API_KEY", "task": { "type": "MTCaptchaTask", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" } } ``` The API returns a `taskId`: ```json { "errorId": 0, "status": "idle", "taskId": "CFQ2yP5DOL" } ``` ## Get the result [#get-the-result] Poll `POST https://api.nocaptchaai.com/getTaskResult` until `status` is `ready`: ```json { "clientKey": "YOUR_API_KEY", "taskId": "CFQ2yP5DOL" } ``` ```json { "errorId": 0, "status": "ready", "solution": { "token": "0.WdWV79pV71mHDjQ...." } } ``` ## Code example [#code-example] ```python # pip install requests import requests, time API_KEY = "YOUR_API_KEY" BASE = "https://api.nocaptchaai.com" task = requests.post(f"{BASE}/createTask", json={ "clientKey": API_KEY, "task": { "type": "MTCaptchaTask", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY", } }).json() task_id = task["taskId"] while True: time.sleep(2) res = requests.post(f"{BASE}/getTaskResult", json={"clientKey": API_KEY, "taskId": task_id}).json() if res.get("status") == "ready": print(res["solution"]["token"]); break if res.get("status") == "failed" or res.get("errorId"): raise SystemExit(res) ``` ```js // Node 18+ const API_KEY = "YOUR_API_KEY"; const BASE = "https://api.nocaptchaai.com"; const create = await fetch(`${BASE}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "MTCaptchaTask", websiteURL: "https://example.com", websiteKey: "YOUR_WEBSITE_KEY", }, }), }).then(r => r.json()); let solution; while (true) { await new Promise(r => setTimeout(r, 2000)); const res = await fetch(`${BASE}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId: create.taskId }), }).then(r => r.json()); if (res.status === "ready") { solution = res.solution.token; break; } if (res.status === "failed" || res.errorId) throw new Error(JSON.stringify(res)); } console.log(solution); ``` ```bash curl -X POST https://api.nocaptchaai.com/createTask \ -H "Content-Type: application/json" \ -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "MTCaptchaTask", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" } }' ``` ## Next steps [#next-steps] # Cloudflare Turnstile Task (/docs/token/turnstile) ## Create a task [#create-a-task] `POST https://api.nocaptchaai.com/createTask` ```json { "clientKey": "YOUR_API_KEY", "task": { "type": "TurnstileTaskProxyLess", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" } } ``` The API returns a `taskId`: ```json { "errorId": 0, "status": "idle", "taskId": "CFQ2yP5DOL" } ``` ## Get the result [#get-the-result] Poll `POST https://api.nocaptchaai.com/getTaskResult` until `status` is `ready`: ```json { "clientKey": "YOUR_API_KEY", "taskId": "CFQ2yP5DOL" } ``` ```json { "errorId": 0, "status": "ready", "solution": { "token": "0.WdWV79pV71mHDjQ...." } } ``` ## Code example [#code-example] ```python # pip install requests import requests, time API_KEY = "YOUR_API_KEY" BASE = "https://api.nocaptchaai.com" task = requests.post(f"{BASE}/createTask", json={ "clientKey": API_KEY, "task": { "type": "TurnstileTaskProxyLess", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY", } }).json() task_id = task["taskId"] while True: time.sleep(2) res = requests.post(f"{BASE}/getTaskResult", json={"clientKey": API_KEY, "taskId": task_id}).json() if res.get("status") == "ready": print(res["solution"]["token"]); break if res.get("status") == "failed" or res.get("errorId"): raise SystemExit(res) ``` ```js // Node 18+ const API_KEY = "YOUR_API_KEY"; const BASE = "https://api.nocaptchaai.com"; const create = await fetch(`${BASE}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "TurnstileTaskProxyLess", websiteURL: "https://example.com", websiteKey: "YOUR_WEBSITE_KEY", }, }), }).then(r => r.json()); let solution; while (true) { await new Promise(r => setTimeout(r, 2000)); const res = await fetch(`${BASE}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId: create.taskId }), }).then(r => r.json()); if (res.status === "ready") { solution = res.solution.token; break; } if (res.status === "failed" || res.errorId) throw new Error(JSON.stringify(res)); } console.log(solution); ``` ```bash curl -X POST https://api.nocaptchaai.com/createTask \ -H "Content-Type: application/json" \ -d '{ "clientKey": "YOUR_API_KEY", "task": { "type": "TurnstileTaskProxyLess", "websiteURL": "https://example.com", "websiteKey": "YOUR_WEBSITE_KEY" } }' ``` ## Next steps [#next-steps] # Claude Code (/docs/agents/claude-code) [Claude Code](https://docs.claude.com/en/docs/claude-code) is Anthropic's terminal coding agent, and it speaks MCP natively. Point it at the [NoCaptchaAI MCP server](/docs/agents/mcp) and it can solve captchas inline while it browses, scrapes, or tests. ## Add the MCP server [#add-the-mcp-server] Register the server with a single command. The `-e` flag passes your API key as an environment variable, and everything after `--` is the command Claude Code runs to launch the server: ```bash claude mcp add nocaptchaai -e NOCAPTCHAAI_API_KEY=your_key -- npx -y nocaptchaai-mcp ``` Get `your_key` from the [dashboard](https://nocaptchaai.com/manage). Verify it registered: ```bash claude mcp list ``` ## Use it [#use-it] Once the server is connected, just ask in plain language and Claude Code will call the `solve_captcha` tool: ```text > Solve the Turnstile captcha on https://example.com (site key 0x4AAAAAAA...) and use the token to submit the form. ``` Claude Code creates the task, waits for the solution, and hands the resulting token back into whatever it was doing. ## Without MCP [#without-mcp] You don't strictly need the server. Because Claude Code can make HTTP requests, you can point it at the [API reference](/docs/api) and let it call the endpoints itself: ```text > Read https://api.nocaptchaai.com docs: POST /createTask then poll POST /getTaskResult until status is "ready". Solve the captcha on this page. ``` The MCP server is still recommended — it gives Claude Code a typed tool instead of ad-hoc requests, so it is more reliable across sessions. See the [MCP page](/docs/agents/mcp) for the server config and reference implementation. # Cline (/docs/agents/cline) [Cline](https://cline.bot) is an autonomous coding agent for VS Code with built-in MCP support. Add the [NoCaptchaAI MCP server](/docs/agents/mcp) to its settings and Cline can solve captchas as a tool. ## Add the MCP server [#add-the-mcp-server] Open Cline's **MCP Servers** panel and edit the MCP settings (the "Configure MCP Servers" / `cline_mcp_settings.json` view), then add the standard `mcpServers` config: ```json { "mcpServers": { "nocaptchaai": { "command": "npx", "args": ["-y", "nocaptchaai-mcp"], "env": { "NOCAPTCHAAI_API_KEY": "your_key" } } } } ``` Get `your_key` from the [dashboard](https://nocaptchaai.com/manage). Cline reloads its servers on save; the `nocaptchaai` server and its tools appear in the MCP panel once connected. ## Use it [#use-it] Ask Cline in plain language and it will call the `solve_captcha` tool when it hits a challenge: ```text Solve the Turnstile captcha on https://example.com (site key 0x4AAAAAAA...) and submit the form with the returned token. ``` See the [MCP page](/docs/agents/mcp) for the server config and reference implementation. # OpenAI Codex (/docs/agents/codex) The [OpenAI Codex CLI](https://github.com/openai/codex) supports MCP servers through its configuration file. Register the [NoCaptchaAI MCP server](/docs/agents/mcp) there and Codex can solve captchas as a native tool. ## Add the MCP server [#add-the-mcp-server] Edit `~/.codex/config.toml` and add an `[mcp_servers.nocaptchaai]` table that launches the server over stdio: ```toml [mcp_servers.nocaptchaai] command = "npx" args = ["-y", "nocaptchaai-mcp"] env = { NOCAPTCHAAI_API_KEY = "your_key" } ``` Get `your_key` from the [dashboard](https://nocaptchaai.com/manage). This is the same server shape used everywhere — only the file format differs from the JSON `mcpServers` config. ## Use it [#use-it] Start Codex and ask it to clear a challenge. It discovers the server's tools on launch and calls `solve_captcha` when needed: ```text Solve the Turnstile captcha on https://example.com (site key 0x4AAAAAAA...) and submit the form with the returned token. ``` Codex creates the task, polls until the solution is ready, and continues with the token in hand. See the [MCP page](/docs/agents/mcp) for the server config and reference implementation. # Cursor (/docs/agents/cursor) [Cursor](https://cursor.com) supports MCP servers, so its Composer and agent can solve captchas through the [NoCaptchaAI MCP server](/docs/agents/mcp). ## Add the MCP server [#add-the-mcp-server] Create `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` for all projects) with the standard `mcpServers` config: ```json { "mcpServers": { "nocaptchaai": { "command": "npx", "args": ["-y", "nocaptchaai-mcp"], "env": { "NOCAPTCHAAI_API_KEY": "your_key" } } } } ``` Get `your_key` from the [dashboard](https://nocaptchaai.com/manage). Cursor picks up the file automatically; you can confirm the server is connected under **Settings → MCP**. ## Use it [#use-it] In Composer (or the agent panel), ask in plain language and Cursor will call the `solve_captcha` tool: ```text Solve the Turnstile captcha on https://example.com (site key 0x4AAAAAAA...) and use the token to submit the form. ``` See the [MCP page](/docs/agents/mcp) for the server config and reference implementation. # Agents (/docs/agents) AI coding agents — Claude Code, OpenAI Codex, Cursor, Cline, and others — frequently hit captcha walls while browsing, scraping, or automating the web. NoCaptchaAI lets you hand that capability to the agent so it can clear the challenge and keep going. There are two ways to wire it up: * **Call the API directly.** Any agent that can make HTTP requests can `POST /createTask` and poll `POST /getTaskResult` against `https://api.nocaptchaai.com`. This works everywhere but the agent has to know the request shape each time. * **Use an MCP server (recommended).** A [Model Context Protocol](/docs/agents/mcp) server wraps those endpoints as first-class tools (`create_task`, `get_task_result`, `solve`, `balance`). The agent then sees "solve this captcha" as a native action, with typed inputs and outputs, instead of hand-rolling HTTP calls. Every integration below builds on one of these two foundations. Start with the MCP page — it is the source of truth for the server config the agent pages reuse. This list keeps growing. Every agent we support — and any agent you bring yourself — builds on the same [MCP server](/docs/agents/mcp) or the [raw API](/docs/api). Once you understand those two, adding a new agent is just a config snippet. Grab an API key from the [dashboard](https://nocaptchaai.com/manage) before you start. # Model Context Protocol (MCP) (/docs/agents/mcp) The [Model Context Protocol](https://modelcontextprotocol.io) is an open standard for connecting AI agents to external tools and data. An MCP server advertises a set of tools; the agent's MCP client discovers them and can call them on demand with typed arguments. Wrapping NoCaptchaAI in an MCP server turns "solve a captcha" into a first-class action the agent can invoke directly — no hand-written HTTP calls, no remembering the request shape. This page is the source of truth: every other agent page just points its MCP client at the server described here. ## Server configuration [#server-configuration] Most MCP clients accept the same `mcpServers` object. It tells the client how to launch the server (over stdio) and which environment variables to pass through: ```json { "mcpServers": { "nocaptchaai": { "command": "npx", "args": ["-y", "nocaptchaai-mcp"], "env": { "NOCAPTCHAAI_API_KEY": "your_key" } } } } ``` Get `your_key` from the [dashboard](https://nocaptchaai.com/manage). `npx -y nocaptchaai-mcp` is the recommended command shape and is what the agent pages use. An official package is not published yet, so the reference implementation below shows exactly what such a server does — drop it into your own project and point the same config at it (`"command": "node", "args": ["path/to/server.js"]`) until the package ships. ## Tools the server exposes [#tools-the-server-exposes] | Tool | Purpose | | ----------------- | ------------------------------------------------------------------- | | `create_task` | Submit a captcha task (`POST /createTask`) and return its `taskId`. | | `get_task_result` | Fetch a task's status/solution (`POST /getTaskResult`). | | `solve` | Convenience: create a task, poll until ready, return the solution. | | `balance` | Report the account's remaining balance. | The `solve` tool is what most agents reach for — it hides the create-then-poll loop behind a single call. ## Reference implementation [#reference-implementation] A minimal stdio server built on the official [TypeScript MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk) (`@modelcontextprotocol/sdk`). It registers a `solve_captcha` tool that calls `createTask` and then polls `getTaskResult` until the solution is ready. ```ts import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; const BASE_URL = "https://api.nocaptchaai.com"; const API_KEY = process.env.NOCAPTCHAAI_API_KEY; if (!API_KEY) { throw new Error("NOCAPTCHAAI_API_KEY is not set"); } async function post(path: string, body: unknown): Promise { const res = await fetch(`${BASE_URL}${path}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }); return res.json(); } const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); const server = new McpServer({ name: "nocaptchaai", version: "1.0.0" }); server.registerTool( "solve_captcha", { title: "Solve a captcha", description: "Create a NoCaptchaAI task, poll until it is ready, and return the solution.", inputSchema: { type: z.string().describe("Task type, e.g. AntiTurnstileTask"), websiteURL: z.string().describe("URL of the page with the captcha"), websiteKey: z.string().describe("Site key of the captcha widget"), }, }, async ({ type, websiteURL, websiteKey }) => { const created = await post("/createTask", { clientKey: API_KEY, task: { type, websiteURL, websiteKey }, }); if (created.errorId || !created.taskId) { throw new Error(`createTask failed: ${JSON.stringify(created)}`); } const deadline = Date.now() + 120_000; while (Date.now() < deadline) { const result = await post("/getTaskResult", { clientKey: API_KEY, taskId: created.taskId, }); if (result.status === "ready") { return { content: [{ type: "text", text: JSON.stringify(result.solution) }], }; } if (result.status === "failed" || result.errorId) { throw new Error(`task failed: ${JSON.stringify(result)}`); } await sleep(3000); } throw new Error("timed out waiting for the captcha solution"); }, ); const transport = new StdioServerTransport(); await server.connect(transport); ``` Build it (`tsc`) and run the compiled file with Node, or wire it straight into your client config. Swap `solve_captcha`'s task fields to match the captcha you are solving — the [API reference](/docs/api/solver/createtask/post) lists every supported `type`. The Claude Code, Codex, Cursor, Cline, and OpenClaw pages all just point their MCP client at this server using the `mcpServers` config above. If you change the server, they all pick it up. # OpenClaw (/docs/agents/openclaw) OpenClaw is an autonomous, browser-driving agent. Like any agent that can call external tools or HTTP APIs, it can clear captchas with NoCaptchaAI in one of two ways: through the [MCP server](/docs/agents/mcp) if your build supports MCP, or by calling the API endpoints directly. ## Option A — MCP server [#option-a--mcp-server] If your OpenClaw version speaks MCP, register the [NoCaptchaAI MCP server](/docs/agents/mcp) with the standard `mcpServers` config wherever OpenClaw reads its tool configuration: ```json { "mcpServers": { "nocaptchaai": { "command": "npx", "args": ["-y", "nocaptchaai-mcp"], "env": { "NOCAPTCHAAI_API_KEY": "your_key" } } } } ``` The agent then has a `solve_captcha` tool and can call it whenever it hits a challenge. ## Option B — call the API directly [#option-b--call-the-api-directly] If MCP isn't available, instruct the agent to call the endpoints itself. The flow is: `POST /createTask` to submit the challenge, then poll `POST /getTaskResult` until `status` is `ready`: ```bash # 1. Create the task curl -s https://api.nocaptchaai.com/createTask \ -H "Content-Type: application/json" \ -d '{ "clientKey": "your_key", "task": { "type": "AntiTurnstileTask", "websiteURL": "https://example.com", "websiteKey": "0x4AAAAAAA..." } }' # -> { "taskId": "..." } # 2. Poll until status is "ready"; the token is in "solution" curl -s https://api.nocaptchaai.com/getTaskResult \ -H "Content-Type: application/json" \ -d '{ "clientKey": "your_key", "taskId": "..." }' ``` Get `your_key` from the [dashboard](https://nocaptchaai.com/manage). OpenClaw's tooling and config layout vary between versions. Use whichever path your build supports — MCP if available, otherwise the raw API. Both hit the same endpoints behind the scenes. See the [MCP page](/docs/agents/mcp) for the server config and reference implementation. # Check balance & plan info (/docs/api/balance/balance/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List all error codes (/docs/api/balance/errorcode/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Legacy balance format (/docs/api/balance/legacy/balance/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # API Reference (/docs/api) The NoCaptchaAI API lets you solve captchas programmatically. Every endpoint below has an **interactive playground** — fill in your API key and parameters and send a real request to production, right from the docs. **Base URL** — all requests go to `https://api.nocaptchaai.com`. Authenticate with your API key (`clientKey` in the body, or the `apikey` header for `/solve`). See [Authentication](/docs/start/authentication). ## Endpoint groups [#endpoint-groups] ## Typical flow [#typical-flow] 1. `POST /createTask` → returns a `taskId`. 2. `POST /getTaskResult` → poll until `status` is `ready`. 3. Use the `solution` (e.g. the token) in your target request. New to the API? Start with the [Quickstart](/docs/start/quickstart), or grab ready-made client code from the [SDKs](/docs/sdks) section. # Collect endpoint (reserved) (/docs/api/solver/collect/post) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Create async captcha solving task (/docs/api/solver/createtask/post) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get response status (/docs/api/solver/getresponse/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Poll task result (GET) (/docs/api/solver/gettaskresult/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Poll task result (/docs/api/solver/gettaskresult/post) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get accuracy report (/docs/api/solver/report/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Report accuracy feedback (/docs/api/solver/reportaccuracy/post) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Solve captcha (/docs/api/solver/solveCaptcha) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Health check (/docs/api/system/health/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Browser Extension (/docs/guides/browser-extension) The NoCaptchaAI browser extension automatically detects and solves captchas as you browse — no code, no scripts, no integration work. Install it, paste your API key once, and supported captchas are solved for you in the background. ## Install [#install] Install for Chrome, Edge, Brave, and other Chromium browsers. Install for Mozilla Firefox. Browse the source, file issues, or build it yourself. ## Setup [#setup] ### Install the extension [#install-the-extension] Add it from the [Chrome Web Store](https://chromewebstore.google.com/detail/nocaptcha-ai-auto-captcha/hbnbcapieoandchfgacedlkjpdbbejgb) or [Firefox Add-ons](https://addons.mozilla.org/en-US/firefox/addon/nocaptcha-ai-captcha-solver/), then pin its icon to your browser toolbar so it's easy to reach. NoCaptchaAI extension icon pinned in the browser toolbar ### Get your API key [#get-your-api-key] Sign in to the [NoCaptchaAI dashboard](https://nocaptchaai.com/manage) and copy your API key. New accounts include free credits to get started. ### Paste your API key [#paste-your-api-key] Click the extension icon to open its popup, paste your API key into the key field, and save. The extension uses this key to authenticate every solve. ### Configure your options [#configure-your-options] Choose whether to auto-solve on every page or only on sites you enable, and set per-site preferences for the captcha types you care about. NoCaptchaAI extension configuration options ### Visit a page with a captcha [#visit-a-page-with-a-captcha] Open any page that shows a supported captcha. The extension detects it and solves it automatically — you'll see the status update in the extension popup. The extension uses the same API and the same credit balance as direct API calls — solves made in the browser draw from your account just like programmatic requests. If you'd rather integrate solving into your own code, follow the [Quickstart](/docs/start/quickstart). # Error Handling (/docs/guides/error-handling) A robust integration handles failures gracefully: it retries transient errors with backoff and fails fast on permanent ones. This page lists every error code the API can return and how to react to each. ## Error response shape [#error-response-shape] When a request fails, the API returns a JSON body with a numeric `code`, a human-readable `msg`, and—for rate or capacity errors—a `retryAfterSec` hint telling you how long to wait before retrying. ```json { "code": 16, "msg": "RATE_LIMITED", "retryAfterSec": 5 } ``` ## Error codes [#error-codes] | Code | Name | Meaning | What to do | | ---- | -------------------------- | -------------------------------------------------- | -------------------------------------- | | 1 | `KEY_DOES_NOT_EXIST` | The API key is missing, malformed, or invalid. | Fix the key. Do not retry. | | 2 | `NO_SLOT_AVAILABLE` | No worker slot is currently free for your account. | Retry after a short backoff. | | 3 | `ZERO_BALANCE` | Account balance is exhausted. | Top up credits. Do not retry. | | 10 | `ERROR_BAD_PARAMETERS` | The `task` payload is invalid or incomplete. | Fix the request. Do not retry. | | 12 | `ERROR_CAPTCHA_UNSOLVABLE` | The captcha could not be solved. | Retry, or resubmit with cleaner input. | | 14 | `PLAN_EXPIRED` | Your subscription plan has expired. | Renew the plan. Do not retry. | | 15 | `PLAN_INACTIVE` | Your plan is not active. | Activate the plan. Do not retry. | | 16 | `RATE_LIMITED` | Too many requests in a short window. | Back off, respect `retryAfterSec`. | | 17 | `DAILY_LIMIT_EXCEEDED` | Daily request quota reached. | Retry later (often next day). | | 18 | `QUOTA_LIMIT_EXCEEDED` | Plan quota reached. | Retry later or upgrade the plan. | | 21 | `SERVICE_UNAVAILABLE` | The service is temporarily unavailable. | Back off, respect `retryAfterSec`. | ## Retry strategy [#retry-strategy] Group errors into three buckets: **retryable**, **permanent**, and **input-related**. Only retry the first bucket, and always honor `retryAfterSec` when it is present. * **Retryable with backoff:** `2`, `16`, `17`, `18`, `21`. These are transient (rate, quota, or capacity). Wait `retryAfterSec` if provided, otherwise use exponential backoff with jitter. * **Permanent — fix your account or key:** `1`, `3`, `14`, `15`. Retrying will not help; surface the error to the operator. * **Bad request:** `10`. Fix the `task` payload before resending. * **Unsolvable:** `12`. Retry a few times, or resubmit with a clearer image or corrected parameters. Never retry permanent errors in a tight loop. Doing so wastes requests, can trigger `RATE_LIMITED` (code `16`), and delays surfacing the real problem (an expired plan or empty balance). ## Async flow with backoff (Python) [#async-flow-with-backoff-python] The example below submits a task with `POST /createTask`, then polls `POST /getTaskResult` until the status is `ready`. It treats `16`, `17`, `18`, `21`, and `2` as retryable and respects `retryAfterSec`. ```python import time import random import requests BASE_URL = "https://api.nocaptchaai.com" API_KEY = "YOUR_API_KEY" RETRYABLE = {2, 16, 17, 18, 21} def post(path, payload): resp = requests.post(f"{BASE_URL}{path}", json=payload, timeout=30) data = resp.json() code = data.get("code") if code in RETRYABLE: wait = data.get("retryAfterSec") raise RetryableError(wait) if code: # non-zero code that is not retryable raise RuntimeError(f"{code}: {data.get('msg')}") return data class RetryableError(Exception): def __init__(self, retry_after_sec=None): self.retry_after_sec = retry_after_sec def with_backoff(fn, max_attempts=6): for attempt in range(max_attempts): try: return fn() except RetryableError as err: if attempt == max_attempts - 1: raise wait = err.retry_after_sec if wait is None: wait = min(2 ** attempt, 30) + random.random() time.sleep(wait) raise RuntimeError("exceeded max retry attempts") def solve(task): created = with_backoff(lambda: post("/createTask", { "clientKey": API_KEY, "task": task, })) task_id = created["taskId"] while True: result = with_backoff(lambda: post("/getTaskResult", { "clientKey": API_KEY, "taskId": task_id, })) status = result.get("status") if status == "ready": return result["solution"] time.sleep(2) # still processing; poll again if __name__ == "__main__": solution = solve({"type": "ImageToTextTask", "body": "BASE64_IMAGE"}) print(solution) ``` Cap your total polling time and number of attempts so a stuck task cannot block your worker indefinitely. A few seconds between polls keeps you well under the rate limit. # Choosing a Task Type (/docs/guides/review) NoCaptchaAI exposes one task `type` per captcha. Picking the correct type is the most important decision when you integrate — it determines what you send and what you get back. The types fall into two families: * **Token tasks** return a verification **token** that you submit to the target site, exactly as a real user's browser would (for example Turnstile, reCAPTCHA, and GeeTest v4). * **Image / recognition tasks** return the **answer itself** — coordinates to click, the recognized text, or a grid selection — which you then apply in your own automation (for example reCAPTCHA image challenges, BLS, OCR, Binance, AWS WAF, and TikTok). ## Captcha to task type [#captcha-to-task-type] | Captcha | Task `type` | Docs | | ---------------------- | ------------------- | ------------------------------------------------------------ | | Cloudflare Turnstile | `AntiTurnstileTask` | [/docs/token/turnstile](/docs/token/turnstile) | | Cloudflare (challenge) | token task | [/docs/token/cloudflare](/docs/token/cloudflare) | | GeeTest v4 (token) | token task | [/docs/token/geetestv4](/docs/token/geetestv4) | | MTCaptcha (token) | token task | [/docs/token/mtcaptcha](/docs/token/mtcaptcha) | | reCAPTCHA v2 (images) | image task | [/docs/imagetasks/recaptcha](/docs/imagetasks/recaptcha) | | GeeTest v3 | image task | [/docs/imagetasks/geetestv3](/docs/imagetasks/geetestv3) | | GeeTest v4 (image) | image task | [/docs/imagetasks/geetestv4](/docs/imagetasks/geetestv4) | | ImageToText / OCR | image task | [/docs/imagetasks/imagetotext](/docs/imagetasks/imagetotext) | | BLS | image task | [/docs/imagetasks/bls](/docs/imagetasks/bls) | | Binance | image task | [/docs/imagetasks/binance](/docs/imagetasks/binance) | | AWS WAF | image task | [/docs/imagetasks/awswaf](/docs/imagetasks/awswaf) | | TikTok | image task | [/docs/imagetasks/tiktok](/docs/imagetasks/tiktok) | Each linked page lists the exact `type` value and the fields that task requires. When in doubt, start from the captcha you're facing and follow its link. ## Async vs sync [#async-vs-sync] All tasks are sent to `https://api.nocaptchaai.com` with your dashboard API key. There are two ways to run them: * **Async (recommended):** submit with `/createTask`, then poll `/getTaskResult` until the result is ready. This scales well, handles longer-running challenges, and is the right default for production workloads. * **Sync:** call `/solve` and wait for the answer in a single request. It's simpler for quick tests and low-volume use, but ties up the connection until the solve finishes. See the [Quickstart](/docs/start/quickstart) for a working end-to-end example, and the [API Reference](/docs/api) for the full request and response schemas. ## Explore the tasks [#explore-the-tasks] Get a verification token to submit to the site — Turnstile, Cloudflare, GeeTest v4, MTCaptcha, and more. Get the answer, coordinates, or text — reCAPTCHA images, BLS, OCR, Binance, AWS WAF, TikTok, and more. # Go (/docs/sdks/go) The helper below uses only the standard library (`net/http` and `encoding/json`). It submits a task with `POST /createTask`, polls `POST /getTaskResult` until the status is `ready`, and returns an error if the API reports a failure or the timeout is exceeded. The example solves a Cloudflare Turnstile challenge. Read the API key from an environment variable rather than hardcoding it. Set it once with `export NOCAPTCHAAI_KEY="your-key"` (get one at [nocaptchaai.com/manage](https://nocaptchaai.com/manage)). ```go package main import ( "bytes" "encoding/json" "errors" "fmt" "net/http" "os" "time" ) const baseURL = "https://api.nocaptchaai.com" func postJSON(path string, body any) (map[string]any, error) { payload, err := json.Marshal(body) if err != nil { return nil, err } resp, err := http.Post(baseURL+path, "application/json", bytes.NewReader(payload)) if err != nil { return nil, err } defer resp.Body.Close() var out map[string]any if err := json.NewDecoder(resp.Body).Decode(&out); err != nil { return nil, err } return out, nil } // Solve creates a task, polls until it is ready, and returns the solution. func Solve(apiKey string, task map[string]any, pollInterval, timeout time.Duration) (map[string]any, error) { created, err := postJSON("/createTask", map[string]any{"clientKey": apiKey, "task": task}) if err != nil { return nil, err } if created["errorId"] != nil && created["errorId"] != float64(0) { return nil, fmt.Errorf("createTask failed: %v", created) } taskID, ok := created["taskId"].(string) if !ok { return nil, fmt.Errorf("createTask returned no taskId: %v", created) } deadline := time.Now().Add(timeout) for { result, err := postJSON("/getTaskResult", map[string]any{"clientKey": apiKey, "taskId": taskID}) if err != nil { return nil, err } switch result["status"] { case "ready": solution, _ := result["solution"].(map[string]any) return solution, nil case "failed": return nil, fmt.Errorf("task failed: %v", result) } if result["errorId"] != nil && result["errorId"] != float64(0) { return nil, fmt.Errorf("task failed: %v", result) } if time.Now().After(deadline) { return nil, errors.New("timed out waiting for task " + taskID) } time.Sleep(pollInterval) } } func main() { apiKey := os.Getenv("NOCAPTCHAAI_KEY") task := map[string]any{ "type": "AntiTurnstileTask", "websiteURL": "https://example.com", "websiteKey": "0x4AAAAAAA...", } solution, err := Solve(apiKey, task, 3*time.Second, 120*time.Second) if err != nil { panic(err) } fmt.Printf("%+v\n", solution) } ``` Call `Solve()` with any task map — swap the `type`, `websiteURL`, and `websiteKey` for the captcha you need to solve. The returned solution map contains the token (and any other fields) you submit back to the target site. # SDKs & Code Samples (/docs/sdks) There is no package to install. The NoCaptchaAI API is plain JSON over HTTPS, so a "client" is just a small amount of code that calls `POST /createTask`, polls `POST /getTaskResult` until the solution is ready, and hands you the result. The snippets below are complete and runnable — copy one into your project, set your API key, and go. Every sample uses your language's standard HTTP tooling (`requests`, `fetch`, `net/http`) and the same async flow against the base URL `https://api.nocaptchaai.com`. Grab an API key from the [dashboard](https://nocaptchaai.com/manage). The interactive playground generates a ready-to-run sample for every endpoint and language — open [`POST /createTask`](/docs/api/solver/createtask/post), fill in the request, and copy the code in your preferred language. # JavaScript / Node.js (/docs/sdks/javascript) The helper below uses the native `fetch` API (built into Node.js 18+, no dependencies). It submits a task with `POST /createTask`, polls `POST /getTaskResult` until the status is `ready`, and throws if the API reports an error or the timeout is exceeded. The example solves a Cloudflare Turnstile challenge. Read the API key from an environment variable rather than hardcoding it. Set it once with `export NOCAPTCHAAI_KEY="your-key"` (get one at [nocaptchaai.com/manage](https://nocaptchaai.com/manage)). ```js const BASE_URL = "https://api.nocaptchaai.com"; const API_KEY = process.env.NOCAPTCHAAI_KEY; const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); async function post(path, body) { const res = await fetch(`${BASE_URL}${path}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }); return res.json(); } /** * Create a task, poll until it is ready, and return the solution. * Throws on an API error or if the timeout is reached. */ async function solve(task, { pollInterval = 3000, timeout = 120000 } = {}) { const created = await post("/createTask", { clientKey: API_KEY, task }); if (created.errorId) { throw new Error(`createTask failed: ${JSON.stringify(created)}`); } const taskId = created.taskId; const deadline = Date.now() + timeout; while (true) { const result = await post("/getTaskResult", { clientKey: API_KEY, taskId }); if (result.status === "ready") return result.solution; if (result.status === "failed" || result.errorId) { throw new Error(`task failed: ${JSON.stringify(result)}`); } if (Date.now() >= deadline) { throw new Error(`timed out waiting for task ${taskId}`); } await sleep(pollInterval); } } const solution = await solve({ type: "AntiTurnstileTask", websiteURL: "https://example.com", websiteKey: "0x4AAAAAAA...", }); console.log(solution); ``` Call `solve()` with any task object — swap the `type`, `websiteURL`, and `websiteKey` for the captcha you need to solve. The returned `solution` object contains the token (and any other fields) you submit back to the target site. # Python (/docs/sdks/python) The helper below uses the [`requests`](https://pypi.org/project/requests/) library. It submits a task with `POST /createTask`, polls `POST /getTaskResult` on a fixed interval until the status is `ready`, and raises a `RuntimeError` if the API reports an error or the timeout is exceeded. The example solves a Cloudflare Turnstile challenge. Read the API key from an environment variable rather than hardcoding it. Set it once with `export NOCAPTCHAAI_KEY="your-key"` (get one at [nocaptchaai.com/manage](https://nocaptchaai.com/manage)). ```python import os import time import requests BASE_URL = "https://api.nocaptchaai.com" API_KEY = os.environ["NOCAPTCHAAI_KEY"] def solve(task: dict, *, poll_interval: float = 3.0, timeout: float = 120.0) -> dict: """Create a task, poll until it is ready, and return the solution. Raises RuntimeError on an API error or if the timeout is reached. """ created = requests.post( f"{BASE_URL}/createTask", json={"clientKey": API_KEY, "task": task}, timeout=30, ).json() if created.get("errorId"): raise RuntimeError(f"createTask failed: {created}") task_id = created["taskId"] deadline = time.monotonic() + timeout while True: result = requests.post( f"{BASE_URL}/getTaskResult", json={"clientKey": API_KEY, "taskId": task_id}, timeout=30, ).json() status = result.get("status") if status == "ready": return result["solution"] if status == "failed" or result.get("errorId"): raise RuntimeError(f"task failed: {result}") if time.monotonic() >= deadline: raise RuntimeError(f"timed out after {timeout}s waiting for task {task_id}") time.sleep(poll_interval) if __name__ == "__main__": solution = solve( { "type": "AntiTurnstileTask", "websiteURL": "https://example.com", "websiteKey": "0x4AAAAAAA...", } ) print(solution) ``` Call `solve()` with any task object — swap the `type`, `websiteURL`, and `websiteKey` for the captcha you need to solve. The returned `solution` dict contains the token (and any other fields) you submit back to the target site.