Use a API de CAPTCHA com Selenium em Java
Solicite o token primeiro e depois configure o Chrome com o mesmo proxy e os valores de userAgent e secChUa retornados antes de navegar. Coloque solution.token no campo de CAPTCHA da aplicação, envie o formulário e aguarde o estado de sucesso da aplicação — não apenas uma tarefa pronta.
Os exemplos usam um auxiliar REST em Java e o Selenium ChromeDriver. Não há detecção automática de CAPTCHA nem plugin de navegador envolvido.
Nesta página
Prepare o projeto Java e o site de destino
- 1.
Configure o projeto
Use Java 21 ou posterior. Em um projeto Maven, defina o nível de compilação Java como 21 e adicione Gson 2.15.0 e
org.seleniumhq.selenium:selenium-java:4.52.0. Configure o Chrome e o ChromeDriver usando a documentação do Selenium para Chrome. - 2.
Salve os dois arquivos Java
Salve o primeiro exemplo como
src/main/java/Solve.javae o segundo comosrc/main/java/BrowserSolve.java. Mantenha-os no mesmo pacote; os arquivos fornecidos não têm declaração de pacote.BrowserSolvechamaSolve.api, nãoSolve.main. - 3.
Ative o perfil do site
Configure o hostname de destino no console do solvethree e verifique se o perfil está ativo para seu espaço de trabalho. Enviar um hostname e uma ação não cria um perfil. Consulte a configuração do perfil do site.
- 4.
Configure o ambiente
Configure as três variáveis de ambiente abaixo no processo que executará
BrowserSolve. Mantenha a chave de API do espaço de trabalho no seu processo Java confiável, não na página nem no JavaScript do navegador.
| Variável | Valor |
|---|---|
SOLVETHREE_API_KEY | A chave de API do seu espaço de trabalho. |
SOLVETHREE_PROXY | Uma URL de proxy HTTP com lista de IPs permitidos, sem nome de usuário ou senha incorporados, caminho, consulta ou fragmento. |
TARGET_URL | A URL completa da página da aplicação que contém o formulário. |
Este exemplo exige um proxy com lista de IPs permitidos porque não oferece suporte à passagem de credenciais de proxy pela URL de proxy do Chrome. O mesmo valor de proxy é passado à API de tarefas e ao Chrome.
Adicione Solve.java para solicitações à API
Solve.api envia solicitações autenticadas para https://api.solvethree.com/v1, verifica o status HTTP antes de analisar uma resposta de sucesso e limita cada solicitação ao tempo restante do prazo local.
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.*;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.UUID;
public class Solve {
static final HttpClient HTTP = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(15)).build();
static final String KEY = System.getenv("SOLVETHREE_API_KEY");
static JsonObject api(String path, JsonObject body, long deadline) throws Exception {
long remaining = deadline - System.nanoTime();
if (remaining <= 0) throw new IllegalStateException("Keep the task ID and resume polling");
var builder = HttpRequest.newBuilder(URI.create("https://api.solvethree.com/v1" + path))
.timeout(Duration.ofNanos(Math.min(remaining, Duration.ofSeconds(30).toNanos())))
.header("Authorization", "Bearer " + KEY)
.header("Content-Type", "application/json");
if (body == null) builder.GET();
else builder.POST(HttpRequest.BodyPublishers.ofString(body.toString()));
var response = HTTP.send(builder.build(), HttpResponse.BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300)
throw new IllegalStateException("API HTTP " + response.statusCode());
return JsonParser.parseString(response.body()).getAsJsonObject();
}
public static void main(String[] args) throws Exception {
String proxy = System.getenv("SOLVETHREE_PROXY");
if (KEY == null || proxy == null) throw new IllegalArgumentException("Set the API key and proxy");
var input = new JsonObject();
input.addProperty("site", "accounts.example.com");
input.addProperty("action", "login");
input.addProperty("proxy", proxy);
input.addProperty("requestId", UUID.randomUUID().toString());
// Save input before creation if the task must be recovered after restart.
long deadline = System.nanoTime() + Duration.ofSeconds(180).toNanos();
var task = api("/tasks?waitMs=0", input, deadline);
while (task.get("status").getAsString().equals("pending") || task.get("status").getAsString().equals("solving")) {
String id = URLEncoder.encode(task.get("id").getAsString(), StandardCharsets.UTF_8);
task = api("/tasks/" + id + "?waitMs=15000", null, deadline);
if (task.get("status").getAsString().equals("pending") || task.get("status").getAsString().equals("solving"))
Thread.sleep(1000);
}
if (!task.get("status").getAsString().equals("ready"))
throw new IllegalStateException("Task failed: " + task.get("errorCode")
+ ": " + task.get("error"));
var solution = task.getAsJsonObject("solution");
// Submit solution.token with userAgent/secChUa and the original proxy.
System.out.println("Ready task: " + task.get("id").getAsString());
}
}O método main independente demonstra a criação de tarefas e as consultas periódicas. Seu hostname accounts.example.com e sua ação login são valores de exemplo. Para a integração com Selenium, use esse arquivo como auxiliar e execute BrowserSolve em vez dele; executar os dois métodos main criaria tarefas separadas.
Uma solicitação de reCAPTCHA precisa de um hostname em site, da action da aplicação e de exatamente um dos campos proxy ou proxyCandidates. Não adicione type nem url. Omitir recaptchaType seleciona enterprise-v3, que é o valor usado nestes exemplos.
Inicie o Chrome com a identidade da solução pronta
BrowserSolve deriva site de TARGET_URL, cria a tarefa e faz consultas periódicas enquanto o status é pending ou solving. Somente uma tarefa ready fornece a solução usada pelo navegador.
// Save as BrowserSolve.java beside Solve.java from the Java REST quickstart.
// Add Selenium Java 4.52.0 and Gson 2.15.0 to your Maven dependencies; Java 21+.
import com.google.gson.JsonObject;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Map;
import java.util.UUID;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class BrowserSolve {
public static void main(String[] args) throws Exception {
String target = System.getenv("TARGET_URL");
String proxy = System.getenv("SOLVETHREE_PROXY");
URI proxyUri = URI.create(proxy);
if (proxyUri.getUserInfo() != null) throw new IllegalArgumentException("Use an IP-allowlisted proxy");
var input = new JsonObject();
input.addProperty("site", URI.create(target).getHost());
input.addProperty("action", "login");
input.addProperty("proxy", proxy);
input.addProperty("requestId", UUID.randomUUID().toString());
long deadline = System.nanoTime() + Duration.ofSeconds(180).toNanos();
var task = Solve.api("/tasks?waitMs=0", input, deadline);
while (task.get("status").getAsString().matches("pending|solving")) {
String id = URLEncoder.encode(task.get("id").getAsString(), StandardCharsets.UTF_8);
task = Solve.api("/tasks/" + id + "?waitMs=15000", null, deadline);
if (task.get("status").getAsString().matches("pending|solving")) Thread.sleep(1000);
}
if (!task.get("status").getAsString().equals("ready")) throw new IllegalStateException("Task failed");
var solution = task.getAsJsonObject("solution");
var options = new ChromeOptions();
options.addArguments("--proxy-server=" + proxy, "--user-agent=" + solution.get("userAgent").getAsString());
var browser = new ChromeDriver(options);
try {
browser.executeCdpCommand("Network.enable", Map.of());
browser.executeCdpCommand("Network.setExtraHTTPHeaders", Map.of("headers",
Map.of("sec-ch-ua", solution.get("secChUa").getAsString())));
browser.get(target);
var wait = new WebDriverWait(browser, Duration.ofSeconds(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.get("token").getAsString());
browser.findElement(By.cssSelector("button[type=submit]")).click();
wait.until(driver -> driver.findElement(By.id("success"))); // Your application's success marker.
} finally { browser.quit(); }
}
}A ordem importa: ChromeOptions define o proxy e o user agent retornado; depois, ChromeDriver define o cabeçalho sec-ch-ua retornado via CDP antes de browser.get(target). Não navegue primeiro com uma identidade diferente para alterá-la apenas ao enviar o token.
Este exemplo envia deliberadamente um único proxy, para que o Chrome possa usar esse mesmo proxy sem precisar escolher entre candidatos. Mantenha a URL de destino consistente com o hostname e a ação usados na tarefa.
Adapte o formulário antes de executar BrowserSolve
O exemplo de navegador usa um formulário sob seu controle com um campo de resposta do CAPTCHA, um botão de envio e um elemento de sucesso. Altere esses valores específicos da aplicação antes de executar BrowserSolve.main com as dependências do Maven no classpath.
action: substitualoginpela ação que sua aplicação usa neste envio.g-recaptcha-response: confirme o nome do campo que seu formulário realmente envia. O exemplo atribuisolution.tokene dispara um eventoinputcom propagação.button[type=submit]: substitua este seletor se ele não identificar o botão de envio do formulário desejado.success: substitua este ID de elemento por um estado que apareça somente após o envio atual ser bem-sucedido.
Definir um campo e disparar um evento não é um callback universal de CAPTCHA. Se a lógica do formulário da sua aplicação não consumir esse campo ou evento, adapte a etapa de envio à vinculação real. Inspecione a requisição de saída para confirmar que ela contém solution.token, e não o ID da tarefa ou um token antigo.
A espera final do WebDriver verifica a presença de um elemento de sucesso da aplicação. Escolha esse indicador com cuidado: um elemento já presente antes do envio não comprova nada sobre a nova requisição. Uma tarefa pronta significa que o solvethree gerou uma solução; a aceitação pelo destino é confirmada pela resposta da aplicação.
Trate falhas sem criar outra tarefa desnecessariamente
- A API retorna uma resposta HTTP sem sucesso.
Verifique a resposta HTTP separadamente do status da tarefa. Solve.api lança uma exceção antes de tratá-la como um payload de sucesso.
Experimente: Diagnostique o erro da requisição antes de tentar novamente. Confirme os campos da requisição e o perfil de site ativo, em vez de enviar repetidamente os mesmos dados inválidos.
- A tarefa chega ao status failed.
Leia errorCode e error na resposta da tarefa. A exceção genérica de BrowserSolve não os exibe, embora o exemplo independente Solve.java os exiba.
Experimente: Pare de consultar essa tarefa e exponha esses campos no tratamento de erros. Resoluções com falha são reembolsadas; não presuma que toda falha é um problema de créditos.
- A criação excede o tempo limite ou o prazo local expira.
Verifique se você já tem um ID de tarefa ou se salvou o corpo original da requisição e o requestId. Um tempo limite de conexão não comprova que a criação falhou.
Experimente: Retome a consulta usando o ID da tarefa ou recupere a criação com o mesmo requestId e dados de entrada idênticos. Salve o corpo antes da criação se a recuperação precisar funcionar após uma reinicialização; executar novamente o método main fornecido gera um novo requestId.
- A tarefa está pronta, mas a aplicação rejeita o envio.
Inspecione o token enviado, a ação, a URL de destino, o proxy, o user agent e sec-ch-ua. Confirme que a aplicação realmente enviou o valor recém-atribuído ao campo.
Experimente: Corrija o valor incompatível ou a vinculação do envio antes de pagar por outra resolução. Mantenha juntos o proxy que funcionou e a identidade retornada.
O prazo de 180 segundos da API e a espera de 20 segundos da aplicação são limites locais escolhidos pelos exemplos, não garantias do serviço. Para mais detalhes sobre erros da API, consulte Erros da API de CAPTCHA.
Fontes e referência da API
Execute sua primeira tarefa.
Comece com $5 em créditos no espaço de trabalho.