Решение reCAPTCHA Enterprise с Java
Используйте HttpClient из Java для запроса токена, а Gson — для чтения JSON-ответа. Этот пример вызывает REST API, ждёт завершения задачи и возвращает решение reCAPTCHA Enterprise.
На этой странице
Настройте сайт и окружение
Используйте Java 21 или новее. Создайте в консоли активный профиль сайта для целевого ресурса, затем задайте SOLVETHREE_API_KEY и SOLVETHREE_PROXY в окружении, из которого запускается Java.
Замените accounts.example.com на имя хоста, для которого создан профиль, а login — на действие, используемое страницей. Поле site принимает имя хоста без схемы и пути.
Сохраните и запустите Solve.java
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());
}
}В каталоге, содержащем Solve.java, скачайте JAR-файл Gson, скомпилируйте и запустите программу:
curl --fail --location --output gson-2.15.0.jar \
https://repo.maven.apache.org/maven2/com/google/code/gson/gson/2.15.0/gson-2.15.0.jar
javac -cp gson-2.15.0.jar Solve.java
java -cp .:gson-2.15.0.jar SolveЭти команды используют разделитель classpath для macOS/Linux — :. В Windows используйте ; между текущим каталогом и JAR-файлом Gson.
Прочитайте токен из результата
При создании используется waitMs=0. Цикл получает задачу с тем же ID, пока её статус — pending или solving, и останавливается при ready или failed. Каждый GET может ждать до 15 секунд; общий лимит времени вызывающего кода — 180 секунд.
Прочитайте токен с помощью solution.get("token").getAsString(). Используйте возвращённые userAgent и secChUa в запросе к целевому приложению через тот же прокси. Программа выводит ID задачи, а не токен.
После отправки проверьте ответ целевого приложения. Готовая задача означает, что решение сгенерировано; это не подтверждает, что приложение его приняло.
Ошибки и прерванные запросы
Вспомогательная функция останавливается при неуспешном HTTP-ответе. Задача, завершившаяся неудачей, сообщает errorCode и error, а стоимость неудачного решения возвращается. Используйте справочник ошибок API, чтобы определить, что нужно исправить.
Сохраните сгенерированный requestId и точные входные данные, если требуется восстановление после перезапусков. Если создание завершилось тайм-аутом, повторно отправьте эти данные с тем же ID. Если ID задачи уже известен, получите её. Перезапуск этой программы создаёт другой UUID и может создать ещё одну платную задачу.
Источники и справочник API
Запустите первую задачу.
Начните с $5 на балансе рабочего пространства.