Use a API de CAPTCHA com Selenium em C#

Por solvethree5 min de leitura

Chame o solvethree com HttpClient, aguarde a tarefa ficar pronta e coloque solution.token no campo de CAPTCHA da sua aplicação. O Chrome deve usar o mesmo proxy e a identidade de navegador retornada antes de abrir a página de destino.

O exemplo abaixo usa .NET 8 e Selenium Chrome para enviar um formulário sob seu controle. É uma integração REST direta, não um SDK oficial de C# nem um plugin do Selenium.

Nesta página

Prepare o projeto e o destino

  • Use um projeto de console .NET 8 com os usings implícitos padrão habilitados. Adicione os pacotes NuGet Selenium.WebDriver e Selenium.Support, ambos na versão 4.52.0.
  • Instale o Chrome localmente. O Selenium Manager fornece um driver compatível com o Chrome.
  • Confirme que o hostname de destino tem um perfil de site ativo disponível para seu workspace. Enviar um hostname e uma ação não cria um perfil; siga primeiro as instruções de configuração do perfil de site.
  • Use um proxy com IP autorizado e sem credenciais na URL. O exemplo passa esse mesmo proxy ao solvethree e ao Chrome.
Variáveis de ambiente usadas pelo exemplo
Variáveis de ambiente usadas pelo exemplo
VariávelO que fornecer
SOLVETHREE_API_KEYA chave de API do seu workspace. Mantenha-a na máquina confiável que executa a automação, não na página.
SOLVETHREE_PROXYA URL do proxy com IP autorizado usada tanto na resolução quanto no envio pelo navegador.
TARGET_URLA URL completa da página do formulário da sua aplicação. O exemplo extrai o hostname dela para o campo site da tarefa.

Altere a action do exemplo de login se sua integração usar outra ação. Ele usa o recaptchaType padrão, enterprise-v3; a requisição da tarefa não precisa de um campo type ou url.

Crie a tarefa e envie o formulário

O helper da API autentica com a chave do seu workspace e rejeita respostas HTTP sem sucesso antes de analisar um payload de sucesso. O programa cria uma tarefa, consulta seu ID enquanto o status é pending ou solving e inicia o Chrome somente depois que a tarefa está ready.

C# · criar uma tarefa e enviar o formulário próprio
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.

O tempo limite HTTP de 30 segundos, o prazo da API de 180 segundos e a espera do Selenium de 20 segundos são configurações deste exemplo, não garantias de tempo do serviço. Ajuste-os à política de tempo limite da sua aplicação.

Adapte a passagem do token à sua aplicação

  1. 1.

    Mantenha o proxy e a identidade retornada juntos

    ChromeOptions aplica o proxy original e solution.userAgent. Os comandos CDP habilitam a rede e definem sec-ch-ua a partir de solution.secChUa antes da navegação. Mantenha essa ordem; não abra a página primeiro para alterar a identidade depois.

  2. 2.

    Grave o token onde a aplicação o lê

    O exemplo localiza um campo chamado g-recaptcha-response, atribui solution.token e dispara um evento de entrada. Substitua essa passagem se sua aplicação ler o token de outro lugar. Preencher um campo só ajuda se a requisição de saída da aplicação realmente incluir seu valor.

  3. 3.

    Substitua os seletores de envio e sucesso

    O exemplo clica em button[type=submit] e aguarda um elemento com o ID success. Use seletores da sua aplicação real e escolha um indicador de sucesso que confirme que a operação enviada foi bem-sucedida — não apenas que o botão foi clicado.

Uma tarefa pronta significa que uma solução está disponível. A verificação após o envio é separada: o destino ainda decide se aceita a requisição da aplicação.

Trate falhas sem criar tarefas desnecessárias

O helper da API lança uma exceção ao receber uma resposta HTTP.

Inspecione o status HTTP e a resposta de erro. Isso é diferente de uma tarefa chegar a failed.

Experimente: Corrija o problema de requisição ou autenticação informado antes de tentar novamente. Não continue reenviando os mesmos dados inválidos.

A tarefa chega ao status failed.

Leia errorCode e error; site-unreachable é um dos possíveis erros de tarefa.

Experimente: Pare de consultar essa tarefa e resolva a causa informada. Resoluções com falha são reembolsadas.

A tarefa está pronta, mas o destino rejeita o envio.

Inspecione primeiro a requisição de saída da aplicação: ela contém solution.token, e não o ID da tarefa ou um token antigo? Depois, verifique o proxy, o user agent, os client hints e a URL de destino.

Experimente: Corrija a passagem do token ou a incompatibilidade de identidade antes de pagar por outra resolução.

O Selenium excede o tempo limite após clicar em enviar.

Inspecione a página e a resposta da aplicação. O seletor success é um recurso do exemplo, não um sinal universal de aceitação.

Experimente: Substitua-o pela condição real de sucesso da sua aplicação ou trate a rejeição retornada pela aplicação.

O exemplo gera um requestId, mas não o persiste para você. Salve-o com os dados exatos de entrada da tarefa antes da criação se precisar de recuperação após um tempo limite. Se a criação exceder o tempo limite, reenvie os mesmos dados com esse mesmo ID para recuperar a tarefa existente; não gere um novo ID só porque a resposta foi perdida. Reutilizar um ID com dados diferentes gera um conflito. Se você já tem o ID da tarefa, consulte essa tarefa.

Execute sua primeira tarefa.

Comece com $5 em créditos no espaço de trabalho.

Criar um espaço de trabalho
Use a API de CAPTCHA com Selenium em C# · solvethree