Resolva e envie reCAPTCHA com aiohttp
Use aiohttp diretamente com a API REST: crie uma tarefa, consulte até que ela esteja pronta e envie solution.token ao destino. Mantenha as solicitações à API e ao destino em sessões separadas para que o token Bearer do seu workspace nunca chegue ao destino.
O exemplo exige Python 3.11+ e coloca a criação, as consultas e o envio ao destino dentro de um único prazo limite de 180 segundos. Esse é um timeout da aplicação, não uma promessa de tempo de resolução.
Nesta página
Defina o site, o proxy e a solicitação ao destino
- Defina SOLVETHREE_API_KEY com a chave de API do seu workspace. Mantenha-a no servidor.
- Defina SOLVETHREE_PROXY com a URL do proxy que o serviço deve usar na resolução. O envio ao destino usa esse mesmo proxy.
- Substitua accounts.example.com e a ação login pelo hostname e pela ação usados na sua integração. O site precisa de um perfil ativo disponível para seu workspace; configure o perfil antes de criar tarefas.
- Substitua a URL de login do destino e os dados do formulário pela solicitação real da aplicação. O exemplo envia apenas g-recaptcha-response; adicione os outros campos exigidos pelo destino e use o campo de token esperado por ele.
A tarefa envia site, action e um único proxy. Por padrão, ela usa reCAPTCHA Enterprise v3; não adicione os campos type nem url. Se o fluxo do destino precisar de cookies de uma solicitação anterior, faça essas solicitações pela sessão do destino — o exemplo começa com uma sessão nova.
Crie uma vez, consulte e envie
# pip install aiohttp
import asyncio
import os
import uuid
from urllib.parse import urlsplit, unquote
import aiohttp
async def main():
api = "https://api.solvethree.com/v1"
proxy = os.environ["SOLVETHREE_PROXY"]
task = {"site": "accounts.example.com", "action": "login", "proxy": proxy, "requestId": str(uuid.uuid4())}
task_id = None
try:
async with asyncio.timeout(180):
async with aiohttp.ClientSession(headers={"Authorization": "Bearer " + os.environ["SOLVETHREE_API_KEY"]}) as client:
async with client.post(api + "/tasks", params={"waitMs": 0}, json=task, allow_redirects=False) as response:
response.raise_for_status()
if response.status >= 300: raise RuntimeError("Unexpected API redirect")
result = await response.json()
task_id = result["id"]
while result["status"] in ("pending", "solving"):
async with client.get(api + "/tasks/" + task_id, params={"waitMs": 15000}, allow_redirects=False) as response:
response.raise_for_status()
if response.status >= 300: raise RuntimeError("Unexpected API redirect")
result = await response.json()
if result["status"] in ("pending", "solving"): await asyncio.sleep(1)
if result["status"] != "ready":
raise RuntimeError("Task failed: " + str(result.get("errorCode", "unknown")))
solution = result["solution"]
# A separate session prevents the API Bearer header reaching the target.
proxy_url = urlsplit(proxy)
netloc = proxy_url.netloc.rsplit("@", 1)[-1]
server = f"{proxy_url.scheme}://{netloc}"
auth = aiohttp.BasicAuth(unquote(proxy_url.username), unquote(proxy_url.password or "")) if proxy_url.username else None
async with aiohttp.ClientSession() as target:
async with target.post("https://accounts.example.com/login", proxy=server, proxy_auth=auth,
headers={"User-Agent": solution["userAgent"], "sec-ch-ua": solution["secChUa"]},
data={"g-recaptcha-response": solution["token"]}, allow_redirects=False) as response:
print("Application HTTP status:", response.status)
except TimeoutError:
print("Timed out; recover requestId", task["requestId"], "taskId", task_id)
raise
asyncio.run(main())Este exemplo usa REST assíncrono diretamente, não um método assíncrono do SDK oficial de Python. Ele faz um único POST de criação para /v1/tasks, salva o id retornado e usa solicitações GET para consultar essa tarefa. pending e solving mantêm o loop; ready permite o envio; uma tarefa com status failed interrompe o loop.
O campo proxy no corpo da tarefa informa ao solvethree qual proxy usar. Os argumentos proxy e proxy_auth do aiohttp aparecem apenas na chamada HTTP ao destino, não nas chamadas à API. O exemplo separa as credenciais do proxy da URL do servidor proxy e envia o token com os valores retornados de userAgent e secChUa.
As sessões são separadas intencionalmente: apenas a sessão da API tem o cabeçalho Authorization. Os redirecionamentos estão desativados, e os redirecionamentos da API são tratados como erros, em vez de serem seguidos.
- Uma solicitação à API retorna um erro HTTP.
O exemplo verifica o status HTTP antes de ler um payload de sucesso.
Experimente: Trate o erro HTTP separadamente da falha da tarefa. Corrija entradas inválidas ou problemas de autorização antes de tentar novamente.
- A tarefa chega ao status failed.
Verifique errorCode e error na resposta da tarefa. O exemplo lança uma exceção apenas com errorCode.
Experimente: Pare de consultar essa tarefa e trate a causa informada. Corrija a causa informada antes de tentar novamente.
- A tarefa está no status ready, mas a aplicação rejeita a solicitação.
Verifique o campo do token enviado, a URL do destino, a identidade do navegador e o proxy retornados, além dos campos de formulário ou cookies necessários.
Experimente: Envie solution.token com a identidade retornada pelo mesmo proxy. Leia a resposta da aplicação usando os critérios de sucesso desse destino — o status HTTP exibido, por si só, não comprova a aceitação.
Recupere-se de um timeout sem comprar outra resolução
Um timeout na criação não prova que ela falhou. O exemplo mantém as entradas originais em task e exibe seu requestId junto com task_id quando o prazo limite expira. Essas variáveis só persistem enquanto o processo está em execução; os IDs exibidos não são um registro completo de recuperação.
- 1.
Salve a solicitação original antes da criação
Para recuperar após reinicializações, armazene com segurança o corpo completo da tarefa, incluindo requestId e proxy. O exemplo gera um novo UUID a cada execução, então simplesmente executá-lo novamente cria uma nova solicitação lógica.
- 2.
Retome a tarefa existente
Se você tem task_id, consulte essa tarefa. Se a criação atingiu o timeout antes de você receber um ID, repita a criação com o corpo da tarefa e o requestId salvos, sem alterações. A API retorna a tarefa existente; alterar as entradas e reutilizar o ID gera um conflito.
- 3.
Verifique se o envio já ocorreu
O prazo limite também abrange o POST ao destino. Se essa solicitação atingiu o timeout, verifique o resultado na aplicação antes de enviar novamente: ela pode ter recebido a solicitação mesmo que seu cliente não tenha recebido uma resposta. Recuperar a tarefa do solvethree não determina o que aconteceu no destino.
Fontes e referência da API
Execute sua primeira tarefa.
Comece com $5 em créditos no espaço de trabalho.