Solve reCAPTCHA Enterprise with Python

By solvethree3 min read

Use the official Python SDK to request a reCAPTCHA v3 Enterprise token, then submit solution.token with the returned browser identity and the same proxy. You'll need Python 3.10 or later, a workspace API key, and an active profile for the target site.

On this page

Install the SDK and configure your site

Install the official Python SDK:

Install the Python SDK
python -m pip install https://solvethree.com/downloads/solvethree_sdk-0.1.0-py3-none-any.whl
  1. 1.

    Create the site profile

    Set up the target hostname in the solvethree console and make sure its profile is active and available to your workspace. Sending a hostname in a solve request doesn't create a profile. See site profile setup if you haven't configured one.

  2. 2.

    Set SOLVETHREE_API_KEY

    In the shell or deployment environment that will run the script, set SOLVETHREE_API_KEY to your workspace API key. Keep it on the server, not in browser code or a committed source file.

  3. 3.

    Set SOLVETHREE_PROXY

    Set SOLVETHREE_PROXY to the proxy URL the solve and subsequent application request will use. The example uses one proxy, so don't also add proxyCandidates.

Request the Enterprise token

Save this example as solve.py. Replace accounts.example.com with your configured hostname—without a scheme or path—and replace login with the action used by the target page.

Python · solve.py
import os
from uuid import uuid4
from solvethree import Solvethree, SolvethreeError, TaskFailedError

client = Solvethree(os.environ["SOLVETHREE_API_KEY"])
request = {
    "site": "accounts.example.com",  # Use your configured hostname.
    "action": "login",              # Use the page's actual action.
    "proxy": os.environ["SOLVETHREE_PROXY"],
    "requestId": str(uuid4()),
}
try:
    result = client.solve(request, timeout=180)
except TaskFailedError as error:
    raise SystemExit(f"Task failed: {error.error_code}") from None
except SolvethreeError as error:
    # Keep these IDs so an interrupted request can be recovered.
    raise SystemExit(f"Recover request {error.request_id}, task {error.task_id}") from None

solution = result["solution"]
token = solution["token"]
user_agent = solution["userAgent"]
client_hints = solution["secChUa"]
print("Ready task:", result["id"])  # Do not print the token or proxy password.

The request defaults to enterprise-v3, so it doesn't need a recaptchaType field. Don't add type or url; those aren't reCAPTCHA request fields.

Solvethree is synchronous. client.solve creates the task once, then polls until it returns a ready result or raises an exception. Here, timeout=180 sets a 180-second limit on how long the client waits. On success, the script extracts the token, user agent and client hints without printing sensitive values.

Submit the token to your application

Continue in the same script after the solve. Install requests separately as noted in the example. Replace the login URL and form data with your application's actual request, including any required credentials, CSRF token and session cookies.

Python requests · apply a ready solution
# Continue after client.solve(). Install requests separately: pip install requests.
import requests

# This example endpoint accepts the standard reCAPTCHA form field.
# Use your application's real URL, form fields, CSRF token and session.
response = requests.post(
    "https://accounts.example.com/login",
    data={"g-recaptcha-response": solution["token"]},
    headers={
        "User-Agent": solution["userAgent"],
        "sec-ch-ua": solution["secChUa"],
    },
    proxies={"http": request["proxy"], "https": request["proxy"]},
    timeout=30,
    allow_redirects=False,
)
# Inspect the application's response to determine whether it accepted the request.
print("Application HTTP status:", response.status_code)

This example assumes the application accepts the token in g-recaptcha-response. Check the real request rather than assuming that field name. If the form depends on an existing session, submit through that session instead of making a fresh, cookieless request.

Keep the returned userAgent and secChUa, and use the same proxy supplied to the solve. Switching IPs or substituting an unrelated browser identity can break the request.

A ready task means a solution was generated, not that the application accepted it. Inspect the application's response and resulting session; an HTTP status alone doesn't establish a successful login. If it rejects the token, check the outgoing request before paying for another solve: it must contain solution.token, not the task ID or an old token. See diagnosing a rejected token.

Recover an interrupted solve without creating another task

The example generates a new requestId each time the script starts. Save that ID and the original request before calling solve if you need recovery across process restarts. Simply rerunning the script creates a new logical request.

  • If an exception includes task_id, use get_task to resume polling that task. Don't create a replacement just because the connection timed out.
  • If creation was interrupted and you only have request_id, replay the identical task request with that same requestId. It returns the existing task; changing the task inputs while reusing the ID conflicts.
  • For TaskFailedError, stop polling that task. Inspect its errorCode and error before retrying; unchanged invalid inputs won't be fixed by another solve. Failed solves are refunded.

The SDK doesn't automatically retry task creation. It does honor Retry-After for temporary polling failures within the solve deadline. For more control over waiting and recovery, see task polling and timeouts.

Run your first task.

Start with $5 in workspace credit.

Create a workspace