Docs / Guides
Examples
Runnable curl, Python, Node.js and Playwright examples for createTask, getTaskResult and getBalance that you can paste straight into your own code.
There is no official SDK: the API is three POST endpoints with a JSON body, and every snippet on this site is plain HTTP or a standard library. The examples on this page are generated from the same source as the ones in the API reference, so they never describe a different request than the reference does.
The four variants
- curl — the two calls, with the shell picking
taskIdout of the response. - Python —
requests, a smallcall()helper that raises onerrorId: 1, then a polling loop. - Node.js —
fetchandnode:timers/promises, no dependencies. - Playwright — launches Chromium, solves the task, and applies the solution to the page: the token goes into the widget’s hidden response field, cookies are replayed as described in the comments.
Replace YOUR_API_KEY, the websiteURL, the site key and any proxy placeholders with
your own values before running one.
Applying the solution
Tokens are single-use and short-lived: read them from solution and put them into the
request that the page makes immediately. Cookie-producing types are different — the
cookie is bound to the IP and user agent that earned it, so replay it from the same
proxy session. Proxies lists the modes per type.
Where the per-type examples live
Open POST /createTask in the API reference: its right-hand panel carries a
request example for every one of the 16 task types, each with the exact fields that type
takes. The same data is available as JSON — GET /v1/task-types (public, no key) lists
every accepted name with its proxy mode, its required and optional fields and the keys the
solution returns. The guides explain the flow around them.
A complete example
A complete, runnable script generated from the same source as the examples in theAPI reference. It runs as-is against https://api.sursolver.comonce your key is in place; change the fields it sends to match your type (GET /v1/task-types lists them).
API="https://api.sursolver.com"
KEY="YOUR_API_KEY"
# 1/2 Create the task. API errors are HTTP 200 with errorId 1; -f also fails on HTTP 5xx.
created=$(curl -fsS -X POST "$API/createTask" \
-H "Content-Type: application/json" \
-d '{"clientKey":"'"$KEY"'","task":{"type":"ReCaptchaV3TaskProxyLess","websiteURL":"https://example.com/login","websiteKey":"6Le..."}}') || { echo "createTask: transport failure" >&2; exit 1; }
echo "$created"
task_id=$(echo "$created" | sed -n 's/.*"taskId": *"\([^"]*\)".*/\1/p')
[ -n "$task_id" ] || { echo "createTask: no taskId (errorId 1)" >&2; exit 1; }
# 2/2 Poll getTaskResult until the task is ready (60 tries, 3 s apart).
attempts=60
while [ "$attempts" -gt 0 ]; do
result=$(curl -fsS -X POST "$API/getTaskResult" \
-H "Content-Type: application/json" \
-d '{"clientKey":"'"$KEY"'","taskId":"'"$task_id"'"}') || { echo "getTaskResult: transport failure" >&2; exit 1; }
if echo "$result" | grep -q '"errorId": *1'; then echo "$result" >&2; exit 1; fi
if echo "$result" | grep -q '"status": *"ready"'; then echo "$result"; exit 0; fi
attempts=$((attempts - 1))
[ "$attempts" -gt 0 ] && sleep 3
done
echo "task $task_id was not ready after 60 polls" >&2
exit 1import time
import requests
API = "https://api.sursolver.com"
CLIENT_KEY = "YOUR_API_KEY"
POLL_ATTEMPTS = 60
def call(path, body):
# API errors are HTTP 200 with errorId 1; anything else is a transport failure.
response = requests.post(f"{API}{path}", json=body, timeout=30)
response.raise_for_status()
data = response.json()
if data["errorId"] != 0:
raise RuntimeError(f'{data["errorCode"]}: {data["errorDescription"]}')
return data
created = call(
"/createTask",
{
"clientKey": CLIENT_KEY,
"task": {
"type": "ReCaptchaV3TaskProxyLess",
"websiteURL": "https://example.com/login",
"websiteKey": "6Le...",
},
},
)
for _ in range(POLL_ATTEMPTS):
result = call(
"/getTaskResult",
{"clientKey": CLIENT_KEY, "taskId": created["taskId"]},
)
if result["status"] == "ready":
break
time.sleep(3)
else:
raise TimeoutError(f'task {created["taskId"]} was not ready in {POLL_ATTEMPTS} polls')
print(result["solution"])const { setTimeout: sleep } = require('node:timers/promises');
const API = 'https://api.sursolver.com';
const CLIENT_KEY = 'YOUR_API_KEY';
const POLL_ATTEMPTS = 60;
// API errors are HTTP 200 with errorId 1; anything else is a transport failure.
async function call(path, body) {
const res = await fetch(`${API}${path}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
if (data.errorId !== 0) throw new Error(`${data.errorCode}: ${data.errorDescription}`);
return data;
}
async function solve() {
const created = await call('/createTask', {
clientKey: CLIENT_KEY,
task: {
type: 'ReCaptchaV3TaskProxyLess',
websiteURL: 'https://example.com/login',
websiteKey: '6Le...',
},
});
for (let attempt = 0; attempt < POLL_ATTEMPTS; attempt += 1) {
const result = await call('/getTaskResult', {
clientKey: CLIENT_KEY,
taskId: created.taskId,
});
if (result.status === 'ready') return result.solution;
await sleep(3000);
}
throw new Error(`task ${created.taskId} was not ready in ${POLL_ATTEMPTS} polls`);
}
solve().then(
(solution) => console.log(solution),
(error) => {
console.error(error);
process.exitCode = 1;
},
);const { chromium } = require('playwright');
const { setTimeout: sleep } = require('node:timers/promises');
const API = 'https://api.sursolver.com';
const CLIENT_KEY = 'YOUR_API_KEY';
const POLL_ATTEMPTS = 60;
// API errors are HTTP 200 with errorId 1; anything else is a transport failure.
async function call(path, body) {
const res = await fetch(`${API}${path}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
if (data.errorId !== 0) throw new Error(`${data.errorCode}: ${data.errorDescription}`);
return data;
}
async function solve() {
const created = await call('/createTask', {
clientKey: CLIENT_KEY,
task: {
type: 'ReCaptchaV3TaskProxyLess',
websiteURL: 'https://example.com/login',
websiteKey: '6Le...',
},
});
for (let attempt = 0; attempt < POLL_ATTEMPTS; attempt += 1) {
const result = await call('/getTaskResult', {
clientKey: CLIENT_KEY,
taskId: created.taskId,
});
if (result.status === 'ready') return result.solution;
await sleep(3000);
}
throw new Error(`task ${created.taskId} was not ready in ${POLL_ATTEMPTS} polls`);
}
async function main() {
const browser = await chromium.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com/login');
const solution = await solve();
// Put the token into the captcha's hidden response field, then submit the form.
await page.evaluate(
({ selector, token }) => {
document.querySelector(selector).value = token;
},
{ selector: 'YOUR_RESPONSE_FIELD_SELECTOR', token: solution.gRecaptchaResponse },
);
} finally {
await browser.close();
}
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});