Использование CAPTCHA API с Selenium в C#

Автор: solvethree4 мин на чтение

Вызовите solvethree через HttpClient, дождитесь готовности задачи, затем поместите solution.token в поле CAPTCHA вашего приложения. Chrome должен использовать тот же прокси и полученные параметры идентификации браузера до открытия целевой страницы.

Пример ниже использует .NET 8 и Selenium Chrome для отправки вашей собственной формы. Это прямая REST-интеграция, а не официальный SDK для C# или плагин Selenium.

На этой странице

Подготовьте проект и целевое приложение

  • Используйте консольный проект .NET 8 со включёнными по умолчанию неявными директивами using. Добавьте NuGet-пакеты Selenium.WebDriver и Selenium.Support, оба версии 4.52.0.
  • Установите Chrome локально. Selenium Manager предоставит совместимый драйвер Chrome.
  • Убедитесь, что для целевого имени хоста есть активный профиль сайта, доступный вашему рабочему пространству. Отправка имени хоста и действия не создаёт профиль; сначала выполните инструкции по настройке профиля сайта.
  • Используйте прокси с разрешённым IP-адресом и без учётных данных в URL. Пример передаёт один и тот же прокси в solvethree и Chrome.
Переменные окружения, используемые в примере
Переменные окружения, используемые в примере
ПеременнаяЧто указать
SOLVETHREE_API_KEYAPI-ключ вашего рабочего пространства. Храните его на доверенном компьютере, где выполняется автоматизация, а не на странице.
SOLVETHREE_PROXYURL прокси с разрешённым IP-адресом, используемого и для решения, и для отправки через браузер.
TARGET_URLПолный URL страницы формы вашего приложения. Пример извлекает из него имя хоста для поля site задачи.

Измените action в примере с login на другое действие, если его использует ваша интеграция. Пример использует значение recaptchaType по умолчанию — enterprise-v3; поля type и url в запросе задачи не нужны.

Создайте задачу и отправьте форму

Вспомогательный метод API выполняет аутентификацию с ключом рабочего пространства и отклоняет HTTP-ответы с кодами, не означающими успех, до разбора данных успешного ответа. Программа создаёт одну задачу, опрашивает её по ID, пока статус равен pending или solving, и запускает Chrome только после перехода задачи в статус ready.

C# · создание задачи и отправка собственной формы
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json.Nodes;

var key = Environment.GetEnvironmentVariable("SOLVETHREE_API_KEY")
    ?? throw new Exception("Set SOLVETHREE_API_KEY");
var proxy = Environment.GetEnvironmentVariable("SOLVETHREE_PROXY")
    ?? throw new Exception("Set SOLVETHREE_PROXY");
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", key);
using var deadline = new CancellationTokenSource(TimeSpan.FromSeconds(180));

async Task<JsonObject> Api(HttpMethod method, string path, JsonObject? body = null)
{
    using var request = new HttpRequestMessage(method, "https://api.solvethree.com/v1" + path);
    if (body is not null)
        request.Content = new StringContent(body.ToJsonString(), Encoding.UTF8, "application/json");
    using var response = await http.SendAsync(request, deadline.Token);
    response.EnsureSuccessStatusCode();
    return JsonNode.Parse(await response.Content.ReadAsStringAsync(deadline.Token))!.AsObject();
}

var requestId = Guid.NewGuid().ToString(); // Save with these inputs for recovery.
var input = new JsonObject {
    ["site"] = new Uri(Environment.GetEnvironmentVariable("TARGET_URL") ?? throw new Exception("Set TARGET_URL")).Host, ["action"] = "login",
    ["proxy"] = proxy, ["requestId"] = requestId
};
var task = await Api(HttpMethod.Post, "/tasks?waitMs=0", input);
while (task["status"]!.GetValue<string>() is "pending" or "solving")
{
    var id = Uri.EscapeDataString(task["id"]!.GetValue<string>());
    task = await Api(HttpMethod.Get, "/tasks/" + id + "?waitMs=15000");
    if (task["status"]!.GetValue<string>() is "pending" or "solving")
        await Task.Delay(1000, deadline.Token);
}
if (task["status"]!.GetValue<string>() != "ready")
    throw new Exception("Task failed: " + task["errorCode"]?.GetValue<string>()
        + ": " + task["error"]?.GetValue<string>());
var solution = task["solution"]!.AsObject();
// Use solution["token"], ["userAgent"] and ["secChUa"] with the original proxy.
Console.WriteLine("Ready task: " + task["id"]!.GetValue<string>());
var target = Environment.GetEnvironmentVariable("TARGET_URL") ?? throw new Exception("Set TARGET_URL");
if (!string.IsNullOrEmpty(new Uri(proxy).UserInfo)) throw new Exception("Use an IP-allowlisted proxy");
var options = new ChromeOptions();
options.AddArgument("--proxy-server=" + proxy);
options.AddArgument("--user-agent=" + solution["userAgent"]!.GetValue<string>());
using var browser = new ChromeDriver(options);
browser.ExecuteCdpCommand("Network.enable", new Dictionary<string, object>());
browser.ExecuteCdpCommand("Network.setExtraHTTPHeaders", new Dictionary<string, object> {
    ["headers"] = new Dictionary<string, object> { ["sec-ch-ua"] = solution["secChUa"]!.GetValue<string>() }
});
browser.Navigate().GoToUrl(target);
var wait = new WebDriverWait(browser, TimeSpan.FromSeconds(20));
var field = wait.Until(driver => driver.FindElement(By.Name("g-recaptcha-response")));
browser.ExecuteScript("arguments[0].value=arguments[1]; arguments[0].dispatchEvent(new Event('input',{bubbles:true}));",
    field, solution["token"]!.GetValue<string>());
browser.FindElement(By.CssSelector("button[type=submit]")).Click();
wait.Until(driver => driver.FindElement(By.Id("success"))); // Your application's success marker.

HTTP-тайм-аут в 30 секунд, предельный срок API в 180 секунд и ожидание Selenium в 20 секунд — настройки этого примера, а не гарантии времени работы сервиса. Настройте их в соответствии с политикой тайм-аутов вашего приложения.

Адаптируйте передачу данных к вашему приложению

  1. 1.

    Используйте прокси вместе с полученными параметрами идентификации

    ChromeOptions применяет исходный прокси и solution.userAgent. Команды CDP включают работу с сетью и задают sec-ch-ua из solution.secChUa до перехода на страницу. Соблюдайте этот порядок: не открывайте страницу до изменения параметров идентификации.

  2. 2.

    Запишите токен туда, откуда его читает приложение

    Пример находит поле с именем g-recaptcha-response, присваивает ему solution.token и отправляет событие input. Замените этот механизм передачи, если ваше приложение читает токен из другого места. Заполнение поля помогает только в том случае, если исходящий запрос приложения действительно содержит его значение.

  3. 3.

    Замените селекторы отправки и успешного выполнения

    Пример нажимает button[type=submit] и ожидает появления элемента с ID success. Используйте селекторы из вашего реального приложения и выберите маркер успеха, который подтверждает успешное выполнение отправленной операции, а не просто нажатие кнопки.

Готовая задача означает, что решение доступно. Проверка после отправки выполняется отдельно: целевое приложение по-прежнему само решает, принимать ли запрос.

Обрабатывайте ошибки без создания лишних задач

Вспомогательный метод API выбрасывает исключение при получении HTTP-ответа.

Проверьте HTTP-статус и ответ с ошибкой. Это не то же самое, что переход задачи в статус failed.

Попробуйте: Исправьте указанную проблему с запросом или аутентификацией перед повторной попыткой. Не отправляйте повторно те же некорректные данные.

Задача переходит в статус failed.

Прочитайте errorCode и error; site-unreachable — одна из возможных ошибок задачи.

Попробуйте: Прекратите опрос этой задачи и устраните указанную причину. Средства за неудачные решения возвращаются.

Задача готова, но целевое приложение отклоняет отправку.

Сначала проверьте исходящий запрос приложения: содержит ли он solution.token, а не ID задачи или старый токен? Затем проверьте прокси, user agent, клиентские подсказки и целевой URL.

Попробуйте: Исправьте передачу токена или несовпадение параметров идентификации, прежде чем платить за ещё одно решение.

После нажатия кнопки отправки истекает время ожидания Selenium.

Проверьте страницу и ответ приложения. Селектор success — условный элемент примера, а не универсальный сигнал принятия запроса.

Попробуйте: Замените его фактическим условием успешного выполнения в вашем приложении или обработайте отказ, возвращённый приложением.

Пример генерирует requestId, но не сохраняет его за вас. Если нужно восстановление после тайм-аута, сохраните его вместе с точными входными данными задачи до создания. Если время ожидания создания истекло, повторно отправьте те же данные с тем же ID, чтобы восстановить существующую задачу; не генерируйте новый ID лишь потому, что ответ был потерян. Повторное использование ID с другими входными данными вызывает конфликт. Если у вас уже есть ID задачи, вместо этого получите эту задачу.

Запустите первую задачу.

Начните с $5 на балансе рабочего пространства.

Создать рабочее пространство
Использование CAPTCHA API с Selenium в C# · solvethree