aiohttp로 reCAPTCHA 해결 및 제출하기
aiohttp로 REST API를 직접 호출하세요. 작업 하나를 생성하고 준비될 때까지 폴링한 다음, solution.token을 대상에 제출하세요. 워크스페이스 Bearer 토큰이 대상에 전달되지 않도록 API 요청과 대상 요청을 별도의 세션으로 분리하세요.
이 예제에는 Python 3.11+가 필요하며, 생성, 폴링, 대상 제출 전체에 하나의 180초 제한 시간을 적용합니다. 이는 애플리케이션의 시간 제한이지 보장된 풀이 시간이 아닙니다.
이 페이지의 내용
사이트, 프록시, 대상 요청 설정
- SOLVETHREE_API_KEY를 워크스페이스 API 키로 설정하세요. 키는 서버에 보관하세요.
- SOLVETHREE_PROXY를 서비스가 풀이에 사용할 프록시 URL로 설정하세요. 대상 제출에도 동일한 프록시를 사용합니다.
- accounts.example.com과 login 작업을 연동에 사용하는 호스트 이름과 작업으로 바꾸세요. 사이트에는 워크스페이스에서 사용할 수 있는 활성 프로필이 필요합니다. 작업을 생성하기 전에 프로필을 설정하세요.
- 대상 로그인 URL과 폼 데이터를 실제 애플리케이션 요청으로 바꾸세요. 이 예제는 g-recaptcha-response만 전송합니다. 대상에 필요한 다른 필드를 추가하고 대상이 기대하는 토큰 필드를 사용하세요.
작업은 site, action, 단일 proxy를 전송합니다. 기본값은 reCAPTCHA Enterprise v3이며, type이나 url 필드를 추가하면 안 됩니다. 대상 흐름에 이전 요청의 쿠키가 필요하다면 대상 세션을 통해 해당 요청들을 보내세요. 이 예제는 새 세션으로 시작합니다.
한 번 생성하고 폴링한 뒤 제출
# 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())이는 공식 Python SDK의 비동기 메서드가 아니라 직접 호출하는 비동기 REST 방식입니다. /v1/tasks에 생성 POST 요청을 한 번 보내고, 반환된 id를 저장한 다음, GET 요청으로 해당 작업을 폴링합니다. pending과 solving이면 반복을 계속하고, ready이면 제출할 수 있으며, 작업이 failed이면 반복을 중단합니다.
작업 본문의 proxy는 solvethree가 사용할 프록시를 지정합니다. aiohttp의 proxy와 proxy_auth 인수는 API 호출이 아니라 대상 HTTP 호출에만 사용됩니다. 이 예제는 프록시 자격 증명을 프록시 서버 URL과 분리하고, 반환된 userAgent 및 secChUa와 함께 토큰을 제출합니다.
세션은 의도적으로 분리되어 있으며, API 세션에만 Authorization 헤더가 있습니다. 리디렉션은 비활성화되어 있고, API 리디렉션은 따라가지 않고 오류로 처리합니다.
- API 요청이 HTTP 오류를 반환합니다.
이 예제는 성공 페이로드를 읽기 전에 HTTP 상태를 확인합니다.
다음을 시도해 보세요: HTTP 오류는 작업 실패와 별도로 처리하세요. 재시도하기 전에 잘못된 입력이나 인증 문제를 수정하세요.
- 작업이 failed 상태가 됩니다.
작업 응답의 errorCode와 error를 확인하세요. 이 예제는 errorCode만 포함해 예외를 발생시킵니다.
다음을 시도해 보세요: 해당 작업의 폴링을 중단하고 보고된 원인을 처리하세요. 다시 시도하기 전에 보고된 원인을 해결하세요.
- 작업은 ready 상태이지만 애플리케이션이 요청을 거부합니다.
전송하는 토큰 필드, 대상 URL, 반환된 브라우저 식별 정보와 프록시, 필요한 폼 필드나 쿠키를 확인하세요.
다음을 시도해 보세요: 동일한 프록시를 통해 반환된 식별 정보와 함께 solution.token을 제출하세요. 대상의 성공 기준에 따라 애플리케이션 응답을 확인하세요. 출력된 HTTP 상태만으로는 수락 여부를 알 수 없습니다.
풀이를 추가 구매하지 않고 시간 초과 복구
생성 요청의 시간 초과가 생성 실패를 의미하지는 않습니다. 이 예제는 원래 입력을 task에 유지하고 제한 시간이 지나면 requestId와 task_id를 출력합니다. 이 변수들은 프로세스가 실행 중일 때만 유지되며, 출력된 ID만으로는 완전한 복구 기록이 되지 않습니다.
- 1.
생성 전에 원래 요청 저장
재시작 후에도 복구하려면 requestId와 proxy를 포함한 전체 작업 본문을 안전하게 보관하세요. 이 예제는 실행할 때마다 새 UUID를 생성하므로, 단순히 다시 실행하면 새로운 논리적 요청이 생성됩니다.
- 2.
기존 작업 재개
task_id가 있다면 해당 작업을 조회하세요. ID를 받기 전에 생성 요청이 시간 초과되었다면, 저장해 둔 작업 본문과 requestId를 변경하지 않고 생성 요청을 반복하세요. API는 기존 작업을 반환합니다. 같은 ID를 재사용하면서 입력을 변경하면 충돌이 발생합니다.
- 3.
이미 제출되었는지 확인
제한 시간에는 대상 POST 요청도 포함됩니다. 해당 요청이 시간 초과되었다면 다시 제출하기 전에 애플리케이션의 처리 결과를 확인하세요. 클라이언트가 응답을 받지 못했더라도 애플리케이션은 요청을 받았을 수 있습니다. solvethree 작업을 복구해도 대상에서 무슨 일이 있었는지는 알 수 없습니다.
출처 및 API 레퍼런스
첫 작업을 실행하세요.
워크스페이스 크레딧 $5로 시작하세요.