Java로 reCAPTCHA Enterprise 해결하기
Java의 HttpClient로 토큰을 요청하고 Gson으로 JSON 응답을 읽으세요. 이 예제는 REST API를 호출하고 작업이 완료될 때까지 기다린 뒤 reCAPTCHA Enterprise 솔루션을 반환합니다.
이 페이지의 내용
사이트 및 환경 설정
Java 21 이상을 사용하세요. 콘솔에서 대상의 활성 사이트 프로필을 생성한 다음, Java를 실행하는 환경에 SOLVETHREE_API_KEY와 SOLVETHREE_PROXY를 설정하세요.
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가 있는 디렉터리에서 Gson JAR을 다운로드하고 컴파일한 뒤 실행하세요.
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이 명령은 macOS/Linux의 클래스 경로 구분자인 :를 사용합니다. Windows에서는 현재 디렉터리와 Gson JAR 사이에 ;를 사용하세요.
결과에서 토큰 읽기
생성 시 waitMs=0을 사용합니다. 루프는 pending 또는 solving 상태인 동안 동일한 작업 ID를 조회하며, ready 또는 failed 상태에서 중단됩니다. 각 GET은 최대 15초 동안 대기할 수 있으며, 호출 측의 전체 제한 시간은 180초입니다.
solution.get("token").getAsString()으로 토큰을 읽으세요. 동일한 프록시를 통해 보내는 대상 요청에 반환된 userAgent와 secChUa를 사용하세요. 프로그램은 토큰이 아닌 작업 ID를 출력합니다.
제출 후 대상의 응답을 확인하세요. 준비된 작업은 솔루션이 생성되었음을 나타낼 뿐, 애플리케이션이 이를 수락했다는 뜻은 아닙니다.
오류 및 중단된 요청
헬퍼는 성공이 아닌 HTTP 응답을 받으면 중단합니다. 최종 실패 상태인 작업은 errorCode와 error를 보고하며, 실패한 해결 건은 환불됩니다. API 오류 레퍼런스를 사용해 수정할 사항을 판단하세요.
재시작 후에도 복구해야 한다면 생성된 requestId와 정확한 입력값을 저장하세요. 생성 요청이 시간 초과되면 동일한 ID로 해당 입력값을 다시 보내세요. 작업 ID가 이미 있으면 해당 작업을 조회하세요. 이 프로그램을 재시작하면 다른 UUID가 생성되어 추가로 과금되는 작업이 만들어질 수 있습니다.
첫 작업을 실행하세요.
워크스페이스 크레딧 $5로 시작하세요.