Move a 2Captcha reCAPTCHA integration to solvethree

By solvethree4 min read

This isn't just an endpoint change. Replace the clientKey/task envelope with a flat request authenticated by a Bearer key, configure the target site in solvethree, and supply a proxy. Keep existing 2Captcha task IDs separate from new solvethree tasks.

On this page

Check the task you're moving

This migration covers reCAPTCHA v3 Enterprise through 2Captcha API v2. It does not describe the legacy in.php/res.php API. Also, 2Captcha's API version isn't the CAPTCHA version: solvethree doesn't support reCAPTCHA v2.

The starting request uses the envelope documented by 2Captcha createTask: credentials outside a provider-specific task object.

Before · 2Captcha API v2 task envelope
{
  "clientKey": "TWO_CAPTCHA_API_KEY",
  "task": {
    "type": "RecaptchaV3TaskProxyless",
    "websiteURL": "https://accounts.example.com/login",
    "websiteKey": "PUBLIC_SITE_KEY",
    "minScore": 0.7,
    "pageAction": "login",
    "isEnterprise": true
  }
}

Don't carry this object into the new API unchanged. In particular, the proxyless task type and minScore have no place in the solvethree request below.

Configure the site, then replace the request

First, set up the target site in the solvethree console. Your workspace needs an active site profile before it can solve requests for that hostname. Sending a hostname and action doesn't create one.

Create new tasks with POST /v1/tasks at https://api.solvethree.com, using Authorization: Bearer with your workspace API key. Keep that key on the server. The task creation contract uses a flat JSON body rather than a nested task object.

Changes to the example request
Changes to the example request
2Captcha API v2 inputsolvethree replacement
clientKeyWorkspace API key in the Authorization header, not the JSON body.
task wrapperRemove it; send task fields at the top level.
type: RecaptchaV3TaskProxylessOmit type. Supply exactly one of proxy or proxyCandidates.
websiteURLUse site with the hostname only: accounts.example.com. Don't send url.
websiteKeyConfigure the target site profile in the console instead of copying this field into the task.
pageActionUse action with the target's action value, such as login.
isEnterpriseOmit it; recaptchaType defaults to enterprise-v3.
minScoreOmit it; don't copy it into the solvethree request.
reCAPTCHA Enterprise · request shape
{
  "site": "accounts.example.com",
  "action": "login",
  "proxy": "http://user:[email protected]:8080",
  "requestId": "example_login_001"
}

Replace the example hostname, action and proxy with your target's values. Choose requestId before sending the request and retain it for timeout recovery; use a new value for each new logical task.

The example uses one proxy. Alternatively, proxyCandidates accepts at most six distinct HTTP or HTTPS proxy URLs without paths, queries or fragments. Send one field or the other, never both. Candidates let the service try alternative egress; they don't guarantee a working proxy.

Replace polling and timeout handling

Keep in-flight 2Captcha tasks on its getTaskResult flow, using its credentials, task IDs and documented polling policy. A foreign task ID isn't a solvethree task handle.

  1. 1.

    Handle the creation response

    Check for a non-success HTTP response before reading a success payload. reCAPTCHA creation waits up to 15 seconds by default, but can return a nonterminal task. If it's already ready, use the solution without starting a polling loop.

  2. 2.

    Poll only unfinished tasks

    Retrieve the solvethree task with GET /v1/tasks/:id. Replace the old processing check with pending and solving; both mean the task isn't finished. Only ready contains a usable solution.

  3. 3.

    Set the wait in the URL

    GET polling doesn't wait by default. For long polling, set the waitMs URL query parameter to at most 15000, not a JSON field. Allow the requested wait plus network overhead in your HTTP client timeout.

  4. 4.

    Stop on failed

    Read errorCode and error, then stop polling that task. Failed solves are refunded. An error such as site-unreachable needs investigation; don't assume every failure is a credit problem or keep resubmitting unchanged invalid inputs.

A connection timeout doesn't prove creation failed. If you received the task ID, retrieve that task. If you didn't, repeat the same request with the same requestId to recover the existing task instead of creating another solve. Changing the task inputs while reusing that requestId causes a conflict.

Keep HTTP errors separate from terminal task failures in your adapter. The polling contract and failure handling describe those two paths; don't reuse 2Captcha's error payload parser.

Update token extraction and submission

Replace the old adapter's token lookup with solution.token from a ready solvethree task. Submit that token where the target expects its reCAPTCHA value—not the task ID or the entire solution object.

Use the returned userAgent and secChUa browser identity, together with the successful proxy, when submitting the token. If you supplied proxyCandidates, use the successful proxy rather than choosing another candidate for submission.

A ready task means a solution was generated, not that the website accepted your application request. If the target rejects it, inspect the outgoing token, action, target URL, proxy and browser identity before paying for another solve.

Run your first task.

Start with $5 in workspace credit.

Create a workspace