Отправка решения CAPTCHA с помощью Playwright для Python
Сначала решите CAPTCHA, затем создайте контекст Playwright с тем же прокси и возвращёнными данными браузера. Отправьте solution.token через поле, которое ваше приложение действительно передаёт в запросе.
Пример ниже отправляет форму на странице, которой вы управляете. Он ожидает POST-ответ приложения; он не перехватывает reCAPTCHA и не зависит от универсального обратного вызова CAPTCHA.
На этой странице
Подготовьте целевой сайт и окружение
Используйте Python 3.10+, установите Playwright и его браузер Chromium, а также официальный wheel-пакет SDK solvethree для Python. Храните API-ключ рабочего пространства в процессе Python, а не в браузерном JavaScript.
TARGET_URL: полный URL страницы с формой. Пример извлекает из него имя хоста для запроса на решение.SOLVETHREE_PROXY: URL прокси, включая учётные данные для аутентификации, если они требуются. Для решения и браузерного трафика используется один и тот же прокси.SOLVETHREE_API_KEY: API-ключ вашего рабочего пространства.
Для целевого имени хоста нужен активный профиль, доступный вашему рабочему пространству. Настройте профиль сайта перед запуском примера. Замените действие login в примере на действие, нужное вашей интеграции; отправка имени хоста и действия не создаёт профиль. По умолчанию запрос использует reCAPTCHA Enterprise v3.
Решите CAPTCHA, настройте Chromium и отправьте форму
# Install playwright and the official Python SDK; run playwright install chromium.
import asyncio
import os
from urllib.parse import urlsplit, unquote
from playwright.async_api import async_playwright
from solvethree import Solvethree
async def main():
target = os.environ["TARGET_URL"]
proxy = urlsplit(os.environ["SOLVETHREE_PROXY"])
client = Solvethree(os.environ["SOLVETHREE_API_KEY"])
task = {"site": urlsplit(target).hostname, "action": "login", "proxy": os.environ["SOLVETHREE_PROXY"]}
result = await asyncio.to_thread(client.solve, task, timeout=180)
solution = result["solution"]
async with async_playwright() as playwright:
browser = await playwright.chromium.launch()
try:
netloc = proxy.netloc.rsplit("@", 1)[-1]
context = await browser.new_context(
proxy={"server": f"{proxy.scheme}://{netloc}", "username": unquote(proxy.username or ""), "password": unquote(proxy.password or "")},
user_agent=solution["userAgent"], extra_http_headers={"sec-ch-ua": solution["secChUa"]})
page = await context.new_page()
await page.goto(target)
field = page.locator('[name="g-recaptcha-response"]')
await field.wait_for(state="attached")
await field.evaluate("(field, token) => { field.value=token; field.dispatchEvent(new Event('input',{bubbles:true})); }", solution["token"])
async with page.expect_response(lambda r: r.request.method == "POST" and urlsplit(r.url).netloc == urlsplit(target).netloc) as outcome:
await page.get_by_role("button", name="Submit", exact=True).click()
print("Application HTTP status:", (await outcome.value).status)
# Check the application's actual response; adapt form/CSRF/session setup.
await context.close()
finally:
await browser.close()
asyncio.run(main())Solvethree работает синхронно. Вызов client.solve через asyncio.to_thread не даёт операции создания и опроса задачи блокировать цикл событий Playwright. Метод возвращает готовый результат или выбрасывает исключение; в SDK нет нативного асинхронного клиента.
Контекст браузера использует solution.userAgent и solution.secChUa. Пример также отделяет адрес прокси-сервера от имени пользователя и пароля, декодируя учётные данные перед передачей в Playwright. Поскольку в этой задаче используется один прокси, этапа выбора кандидата нет.
- 1.
Используйте нужное приложению поле токена
Пример ожидает добавления поля в DOM, присваивает ему solution.token и отправляет событие input. Видимость поля не требуется. Если приложение отправляет другое поле или считывает состояние токена из другого места, адаптируйте передачу токена под его исходящий запрос.
- 2.
Учтите требования формы к сессии
Пример начинает работу с новым контекстом браузера. Перед отправкой добавьте необходимые вашему приложению действия с сессией, подготовку формы или обработку CSRF.
- 3.
Дождитесь нужного POST-запроса
Ожидание ответа регистрируется до нажатия Submit. Его предикат выбирает POST-запрос к сетевому адресу целевого URL. Если страница отправляет туда другие POST-запросы, сузьте предикат до конечной точки отправки формы.
Прочитайте ответ приложения
Выведенный HTTP-статус подтверждает получение подходящего ответа. Проверьте тело ответа приложения или итоговое состояние страницы, чтобы определить, приняло ли оно отправленные данные. Готовая задача solvethree означает, что решение сгенерировано, а не что целевой сайт его принял.
- Приложение отклоняет готовый токен.
Проверьте исходящий запрос формы, прежде чем оплачивать ещё одно решение.
Попробуйте: Убедитесь, что он содержит solution.token, а не идентификатор задачи или старое значение. Проверьте, что при отправке используются прокси из запроса на решение, возвращённые user agent и client hints, а также нужный целевой сайт.
- Ожидание ответа перехватывает посторонний запрос.
Сравните URL перехваченного POST-запроса с фактической конечной точкой формы.
Попробуйте: Настройте предикат ответа именно на эту конечную точку, а не на все POST-запросы к тому же сетевому адресу.
- Вызов решения выбрасывает исключение до отправки из браузера.
Различайте ошибку HTTP-запроса и окончательный сбой задачи.
Попробуйте: Обрабатывайте неуспешные HTTP-ответы отдельно. Если задача завершилась с ошибкой, проверьте errorCode и error и устраните причину, а не повторяйте запрос с неизменёнными входными данными. Метод solve в SDK уже прекращает работу при сбое.
Источники и справочник API
Запустите первую задачу.
Начните с $5 на балансе рабочего пространства.