Эта статья была полезной?
Как обойти FunCaptcha (Arkose Labs) с помощью Playwright
Технический специалист
FunCaptcha — интерактивная капча: вместо галочки сервис показывает задание, например повернуть объект или выбрать картинку, подходящую под описание. Пройти его может только человек, поэтому в скриптах для веб-скрапинга и автотестов капчу отдают на решение сервису и получают готовый токен.
В этом руководстве мы разберём полный цикл обхода FunCaptcha в Playwright на Python: извлечём публичный ключ со страницы, получим решённый токен через API RuCaptcha и запишем его в поле, которое проверяет форма.
Что понадобится
- Python 3.7 или выше
- Установленный Playwright
- Аккаунт и API-ключ от RuCaptcha
- URL целевой страницы
- Опционально: прокси, если целевой сайт блокирует запросы с IP-адресов дата-центров
Шаг 1. Установка зависимостей
Установите необходимые библиотеки и браузеры Playwright:
bash
pip install playwright 2captcha-python
playwright install chromium
Шаг 2. Инициализация браузера и переход на страницу
Для отладки всегда начинайте с видимого режима headless=False. Это позволит визуально контролировать процесс появления виджета и внедрения токена.
python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
# Переход на целевую страницу
page.goto("https://mysite.com/page/with/funcaptcha")
Шаг 3. Извлечение публичного ключа
Публичный ключ сайта находится в одном из двух мест. Основное — атрибут data-pkey у элемента div с виджетом. Запасное — поле fc-token: в его значении ключ идёт после pk, а адрес сервиса после surl.
python
import re
widget = page.locator("[data-pkey]").first
surl = None
if widget.count() > 0:
pkey = widget.get_attribute("data-pkey")
else:
fc_token = page.locator('[name="fc-token"]').first.get_attribute("value")
pk_match = re.search(r"pk=([^|]+)", fc_token)
if not pk_match:
raise RuntimeError("В значении fc-token нет параметра pk")
pkey = pk_match.group(1)
surl_match = re.search(r"surl=([^|]+)", fc_token)
surl = surl_match.group(1) if surl_match else None
page_url = page.url
print(f"Публичный ключ: {pkey}")
Важно: проверка count() здесь обязательна. Без неё вызов get_attribute на отсутствующем элементе завершится не пустым значением, а таймаутом, и до запасного способа выполнение не дойдёт. По той же причине у обоих локаторов стоит .first: локаторы Playwright работают в строгом режиме и на двух совпадениях выдают ошибку вместо первого элемента.
Адрес сервиса в fc-token записан со схемой, и SDK ждёт значение именно в таком виде.
Шаг 4. Отправка задачи в API и получение токена
Самый простой способ — использовать официальный Python SDK. Он автоматически создаёт задачу и опрашивает сервер до получения результата.
python
import os
from twocaptcha import TwoCaptcha
api_key = os.getenv('APIKEY_RUCAPTCHA', 'ВАШ_API_КЛЮЧ')
solver = TwoCaptcha(api_key, server='rucaptcha.com')
result = solver.funcaptcha(
sitekey=pkey,
url=page_url,
surl=surl or 'https://client-api.arkoselabs.com'
)
token = result['code']
print(f"Токен получен: {token[:20]}...")
Параметр surl — адрес сервиса, с которого загружается виджет. Необязательный: если его не передать, используется значение по умолчанию, которое подходит в большинстве случаев. Передавать всё равно рекомендуется.
Некоторым сайтам нужен ещё один параметр — blob. Как найти его на странице и убедиться, что он верный, разобрано в отдельной статье: Как найти и проверить параметр blob. Если сайт использует blob, передайте в задачу то же значение, что ушло в виджет. Значение действует ограниченное время, новое получают перезагрузкой страницы.
python
result = solver.funcaptcha(
sitekey=pkey,
url=page_url,
surl='https://client-api.arkoselabs.com',
userAgent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
proxy={'type': 'HTTPS', 'uri': 'login:[email protected]:8080'},
**{'data[blob]': 'BLOB_DATA_VALUE'}
)
Альтернатива (прямой HTTP-запрос):
Если вы не используете SDK, отправьте запрос напрямую через curl или библиотеку requests. Форма записи там другая: адрес сервиса передаётся полем funcaptchaApiJSSubdomain без схемы, а blob — полем data строкой JSON.
bash
curl -X POST https://api.rucaptcha.com/createTask \
-H "Content-Type: application/json" \
-d '{
"clientKey": "ВАШ_API_КЛЮЧ",
"task": {
"type": "FunCaptchaTaskProxyless",
"websiteURL": "https://mysite.com/page/with/funcaptcha",
"websitePublicKey": "6220FF23-9856-3A6F-9FF1-A14F88123F55",
"funcaptchaApiJSSubdomain": "client-api.arkoselabs.com",
"data": "{\"blob\":\"BLOB_DATA_VALUE\"}"
}
}'
Если сайт требует привязки к конкретному IP, используйте тип задачи FunCaptchaTask и добавьте параметры прокси: proxyType, proxyAddress, proxyPort, proxyLogin, proxyPassword.
Прежде чем встраивать вызов в скрипт, параметры удобно проверить в режиме песочницы. Работает он не так, как обычная задача: капча не уходит работникам сервиса, а возвращается вам. Вы переключаете роль на работника, входите в приложение с ключом этой роли и решаете собственную капчу вручную, без списания средств.
Проверяются при этом именно параметры. Капча открылась в приложении — websiteURL, публичный ключ и blob найдены верно. Не открылась — ошибка в одном из них, например устарел blob или взят не тот публичный ключ. Режим включается в настройках аккаунта и доступен после первого пополнения. После проверки его нужно выключить, иначе новые задачи так и будут приходить вам, а не работникам. Подробнее на странице Отладка.
Шаг 5. Внедрение токена в страницу (Критический этап)
Токен записывают в поле fc-token. Проверяйте несколько вариантов, как в примере ниже.
Токен приходит длинной строкой со знаками |, = и %, поэтому передавайте его в страницу аргументом функции, а не подстановкой в текст скрипта: склейка строки способна сломать сам скрипт.
python
page.evaluate("""(token) => {
const field = document.querySelector('[name="fc-token"]')
|| document.querySelector('#fc-token');
if (!field) {
throw new Error('Поле fc-token на странице не найдено');
}
field.value = token;
}""", token)
Ошибка в этой функции нужна. Без неё скрипт молча пропустит запись, отправит форму с пустым полем и напечатает, что всё прошло успешно.
Кроме того, часть сайтов использует callback-функцию, которая срабатывает при успешном решении и разблокирует кнопку отправки. Её имя зависит от сайта, ищите его в коде страницы и вызывайте через page.evaluate тем же способом.
Шаг 6. Отправка формы
После успешного внедрения токена форма должна считать себя валидной. Селектор кнопки подставьте свой: button[type='submit'] подходит не всякой форме.
python
page.click("button[type='submit']")
page.wait_for_load_state("networkidle")
browser.close()
Результат решения стоит подтверждать: в SDK для этого существует метод report, а в API — методы reportCorrect и reportIncorrect. Идентификатор задачи лежит в том же ответе, что и токен: solver.report(result['captchaId'], True).
Полный рабочий пример (Python)
python
import os
import re
from playwright.sync_api import sync_playwright
from twocaptcha import TwoCaptcha
API_KEY = os.getenv('APIKEY_RUCAPTCHA', 'ВАШ_API_КЛЮЧ')
TARGET_URL = "https://mysite.com/page/with/funcaptcha"
def solve_funcaptcha():
solver = TwoCaptcha(API_KEY, server='rucaptcha.com')
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
try:
page.goto(TARGET_URL)
# 1. Извлекаем публичный ключ и адрес сервиса
widget = page.locator("[data-pkey]").first
surl = None
if widget.count() > 0:
pkey = widget.get_attribute("data-pkey")
else:
fc_token = page.locator('[name="fc-token"]').first.get_attribute("value")
pk_match = re.search(r"pk=([^|]+)", fc_token)
if not pk_match:
raise RuntimeError("В значении fc-token нет параметра pk")
pkey = pk_match.group(1)
surl_match = re.search(r"surl=([^|]+)", fc_token)
surl = surl_match.group(1) if surl_match else None
print(f"Публичный ключ: {pkey}")
# 2. Решаем капчу через API
print("Отправка задачи в API...")
result = solver.funcaptcha(
sitekey=pkey,
url=TARGET_URL,
surl=surl or 'https://client-api.arkoselabs.com'
)
token = result['code']
print("Токен получен!")
# 3. Внедряем токен в поле fc-token
page.evaluate("""(token) => {
const field = document.querySelector('[name="fc-token"]')
|| document.querySelector('#fc-token');
if (!field) {
throw new Error('Поле fc-token на странице не найдено');
}
field.value = token;
}""", token)
# 4. Отправляем форму
page.click("button[type='submit']")
page.wait_for_load_state("networkidle")
print("Форма отправлена.")
page.wait_for_timeout(3000) # Пауза для визуальной проверки
except Exception as e:
print(f"Ошибка: {e}")
finally:
browser.close()
if __name__ == "__main__":
solve_funcaptcha()
Решение частых проблем
- Публичный ключ не находится (возвращает пустое значение): атрибута
data-pkeyв разметке нет. Возьмите ключ из значения поляfc-token, как показано в Шаге 3. - Скрипт не находит элемент капчи: виджет может находиться внутри iframe. Обращайтесь к нему через
page.frame_locator. - Задача создана, но решение не приходит: возможно, сайту требуется
blob, а он не передан или устарел. Перезагрузите страницу и возьмите новое значение. - Токен записан, но форма не принимает его: сайт проверяет решение своим обработчиком, а не только содержимым поля. Найдите этот обработчик в коде страницы и вызовите его через
page.evaluate, как показано в Шаге 5.
Остальные коды ошибок перечислены на странице «Коды ошибок», ссылка в конце.
Заключение
Главная сложность этой капчи в том, что её задание нельзя разобрать программно: сервис показывает интерактивную сцену, а не текст или сетку картинок. Метод FunCaptcha снимает эту сложность целиком — задание решает работник, а вашему коду остаются три действия.
Найти публичный ключ, дождаться токена и записать его в поле fc-token. Из них внимания требует последнее: запись должна проверяться, иначе пустое поле уходит вместе с формой незаметно для скрипта.
Отправляйте отчёты методами reportCorrect и reportIncorrect: по ним сервис определяет, какие решения не подошли.
Полезные ссылки
- Документация API RuCaptcha по Arkose Labs captcha: https://rucaptcha.com/api-docs/arkoselabs-funcaptcha
- Как обойти Arkose Labs captcha: https://rucaptcha.com/p/funcaptcha
- Как найти и проверить параметр blob: https://rucaptcha.com/h/funcaptcha-blob
- Коды ошибок: https://rucaptcha.com/api-docs/error-codes
- Отладка и песочница: https://rucaptcha.com/api-docs/debugging
- Python SDK RuCaptcha на GitHub: https://github.com/2captcha/2captcha-python