CAPTCHA in the SDK and REST API
PHP, JavaScript, TypeScript and Python use the same automatic handling. It is independent of the target domain. Standard widgets require only a normal request or browser page. Supported types, site settings, run deadlines, budget and source access rules still apply.
Automatic mode and opt-out
| Language | HTTP without automatic handling | Browser session without automatic handling |
|---|---|---|
| PHP | $ctx->http()->get($url, autoCaptcha: false) |
$ctx->browser()->open($url, autoCaptcha: false) |
| JavaScript | await ctx.http().get(url, false) |
await ctx.browser().open(url, [], {}, false) |
| TypeScript | await ctx.http().get(url, false) |
await ctx.browser().open(url, [], {}, false) |
| Python | ctx.http().get(url, auto_captcha=False) |
ctx.browser().open(url, auto_captcha=False) |
The optional argument defaults to enabled. HTTP methods post, request, pool, pages and tryJson also accept it; Python uses try_json. For post and request, it follows the request body. HTTP opt-out applies to that call. Browser opt-out applies to the entire created session, including navigation, actions and reading HTML.
HTTP loading can escalate to a browser when the source settings permit it. Opt-out remains in effect during escalation. Use the browser for interactive forms and always close the page in finally.
Require a confirmed result
PHP:
$page = $ctx->browser()->open($url, [], ['success_selector' => '.product-card']);
try {
$page->waitFor('.product-card', 15000);
$html = $page->content();
} finally {
$page->close();
}
JavaScript and TypeScript:
const page = await ctx.browser().open(url, [], { success_selector: '.product-card' });
try {
await page.waitFor('.product-card', 15000);
const html = await page.content();
} finally {
await page.close();
}
Python:
page = ctx.browser().open(url, captcha_hints={"success_selector": ".product-card"})
try:
page.wait_for(".product-card", 15000)
html = page.content()
finally:
page.close()
Use a selector for the result of your specific operation. It must not remain visible before verification. For ordinary forms, completing a CAPTCHA does not submit the form: fill its fields and click its submit button using the SDK. Then inspect the server response and collected records. HTTP 200 and a filled CAPTCHA response field do not prove success.
Explicit handling after an action
Use $page->solveCaptcha($hints) in PHP, await page.solveCaptcha(hints) in JavaScript/TypeScript or page.solve_captcha(hints) in Python when a new challenge appears. The method returns the page, not an access verification report.
An explicit call requests handling even if automatic mode was disabled for that session. It cannot override a disabled site, plan restrictions or budget limits. To exclude paid tasks entirely, disable automatic handling and do not call this method.
Hints
| Field | Purpose |
|---|---|
kind |
Optional type: smartcaptcha, yandex_image, yandex_text, turnstile, recaptcha_v2, recaptcha_v3 |
sitekey |
Public widget key when not detected automatically |
action |
reCAPTCHA v3 action |
invisible |
Boolean for an invisible widget |
callback |
Existing callback name when required; executable code is not accepted |
success_selector |
CSS selector for the new successful result |
submit_selector |
Confirmation button if the site does not continue automatically |
image_selector |
Only the challenge image |
instructions_selector |
Image showing the object selection order for yandex_image |
answer_selector |
Answer input for yandex_text |
Pass hints as the third browser.open argument or to the explicit handling method. Python uses the named captcha_hints argument. Do not pass a website secret key or full page content. Additional challenges stay in the same session until the attempt limit. An old answer is not reused for a changed challenge. Avoid unbounded retries after rejection.
REST configuration and testing
Authenticate with the workspace's Bearer API key. Editing requires write permission. Another workspace's resources are unavailable. Configure params.captcha through PATCH /api/v1/sites/{site}:
{
"params": {
"captcha": {
"enabled": true,
"hints": {"success_selector": ".product-card"}
}
}
}
Read and merge existing params before sending them. A top-level PATCH does not imply recursive merging of every nested object. Set enabled:false to disable handling for the source. Agent execution uses execution_target:"agent" with an agent_id owned by the workspace.
Start a trial with POST /api/v1/script-versions/{version}/trial-run. A params.auto_captcha field works only if the source reads it using ctx.param and passes it to the SDK. An arbitrary parameter does not change scenario code. Inspect GET /api/v1/runs/{run}, its /log and /preview. Publishing a validated version remains a separate action.
GET /api/v1/billing includes captcha: enabled, limit, used, remaining, unlimited, payg, period_end, per_run, prices, plan_limits, maximum_spending_limit. Each price includes id, name, minimum, maximum, available, spending_limit. Divide monetary values by the response's unit for RUB per task; multiply by 1,000 for the comparison price. minimum:null means no published lower bound, not a free task. Change price caps in the application. There is no separate public REST endpoint for solving a CAPTCHA.
Failures, agents and acceptance checks
An unknown type, rejected answer, exhausted allowance or budget, price cap, cancellation or deadline must not turn into a successful empty export. The SDK reports failure. Inspect the run's status and error. A completed answer may be chargeable even if rejected. Wait for reconciliation when a reservation's outcome is unknown.
Agents use the same methods and hints without additional CAPTCHA keys. Connectivity to Akmelo is required. Attempts and costs belong to the agent's workspace.
Test a page without a CAPTCHA, a form with a website-confirmed result, and the same form with automatic handling disabled. For object selection, require an actual visual challenge; passing a text challenge is not that test.
User guide · PHP · JavaScript · TypeScript · Python · Prices
spending_limit and maximum_spending_limit also use internal currency units per task. A zero type cap disables paid tasks; null restores the system cap. The application displays these caps in RUB per 1,000 tasks.
Scenario walkthroughs by language
Every SDK includes a Working with CAPTCHA group: a shared algorithm and 12 detailed walkthroughs with complete source.
PHP · JavaScript · TypeScript · Python
Explicit task API
The SDK also provides ctx.captcha() (PHP: $ctx->captcha()) for tasks created explicitly by code: current types, schemas, quotations, submission, status retrieval, waiting and feedback. New types in this catalog are not automatically detected or applied by the browser. No external key is required; all work is billed to the workspace.
PHP · JavaScript · TypeScript · Python
Catalog and quotation calls do not submit a paid task. createTask does; Python uses create_task. The returned taskId belongs to Akmelo. getTaskResult reads it and waitForResult waits without creating another task. The options.maxCost ceiling uses micro-rubles, where 1,000,000 units = RUB 1. An answer does not prove website acceptance. Waiting timeout and run cancellation do not guarantee task cancellation or a refund.