Captcha solver ใน Java ด้วย HttpClient: ตัวอย่างการทำงาน (2026)
captcha solver ใน Java คือ HTTP call หนึ่งครั้ง Java 11 ขึ้นไปมาพร้อม java.net.http.HttpClient ดังนั้นการพึ่งพาเดียวที่คู่มือนี้ต้องใช้คือ Gson สำหรับ JSON คุณส่ง sitekey และ URL ของหน้าไปยัง Scarnox API อ่าน solution.token และ submit token ไปยังฟอร์มของเว็บ คู่มือนี้ครอบคลุม PopularCaptcha ซึ่ง Scarnox แก้ได้ในวันนี้แบบ proxyless
เริ่มด้วยเครดิตทดลองใช้ฟรี ไม่ต้องใช้บัตร และลองโค้ดกับหน้าที่คุณควบคุมก่อนนำไปใช้กับสิ่งอื่น
สิ่งที่ต้องมี
- Java 17 ขึ้นไป (
java -version) - Gson 2.10 ขึ้นไป ใน Maven:
com.google.code.gson:gson:2.10.1 - Scarnox API key ที่อ่านจาก environment variable
- sitekey ของ widget PopularCaptcha ในหน้า หากต้องการความช่วยเหลือในการหา ดูวิธีหา sitekey ของ captcha
คลาส solver
คลาสนี้ห่อ HttpClient หนึ่งตัวที่เก็บ cookie ไว้ เพื่อให้ session ดำเนินต่อไปจนถึงการ submit ฟอร์ม เมธอด solve ตั้ง Bearer header ส่ง JSON body และตรวจ errorId
// ScarnoxSolver.java
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.LinkedHashMap;
import java.util.Map;
public class ScarnoxSolver {
private static final String API_URL = "https://api.scarnox.com/api/tasks/create";
private static final Gson GSON = new Gson();
private final String apiKey;
private final HttpClient http = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.cookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ALL))
.build();
public ScarnoxSolver(String apiKey) {
this.apiKey = apiKey;
}
/** คืนค่า token การเรียกจะรอจนกว่า token จะพร้อม */
public String solve(String sitekey, String pageUrl, boolean invisible) throws Exception {
Map<String, Object> body = new LinkedHashMap<>();
body.put("captcha_type", "PopularCaptchaTaskProxyless");
body.put("site_key", sitekey);
body.put("site_url", pageUrl);
if (invisible) {
body.put("is_invisible", true);
}
HttpRequest request = HttpRequest.newBuilder(URI.create(API_URL))
.timeout(Duration.ofSeconds(185))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(GSON.toJson(body)))
.build();
HttpResponse<String> response = http.send(request, HttpResponse.BodyHandlers.ofString());
JsonObject data;
try {
data = JsonParser.parseString(response.body()).getAsJsonObject();
} catch (RuntimeException e) {
throw new IllegalStateException("HTTP " + response.statusCode() + ": not JSON");
}
if (data.get("errorId").getAsInt() != 0) {
throw new IllegalStateException(
data.get("errorCode").getAsString() + ": "
+ data.get("errorDescription").getAsString());
}
return data.getAsJsonObject("solution").get("token").getAsString();
}
/** ส่ง token ไปยังฟอร์มของเว็บและคืนค่า HTTP status */
public int submit(String pageUrl, String email, String token) throws Exception {
// โหลดหน้าก่อน เพื่อให้ session cookie ถูกตั้งค่า
http.send(HttpRequest.newBuilder(URI.create(pageUrl)).GET().build(),
HttpResponse.BodyHandlers.discarding());
String form = "email=" + enc(email)
+ "&h-captcha-response=" + enc(token)
+ "&g-recaptcha-response=" + enc(token);
HttpRequest request = HttpRequest.newBuilder(URI.create(pageUrl))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(form))
.build();
return http.send(request, HttpResponse.BodyHandlers.discarding()).statusCode();
}
private static String enc(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8);
}
}
header Authorization ใช้คำนำหน้า Bearer timeout ของคำขอคือ 185 วินาที เพราะ API บล็อกจนกว่า token จะพร้อม ไม่มีขั้น polling
โปรแกรมหลัก
เมธอด main แก้ด้วยการลองใหม่ไม่กี่ครั้ง แล้วจึง submit token
// Main.java
public class Main {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("SCARNOX_API_KEY");
if (apiKey == null || apiKey.isBlank()) {
throw new IllegalStateException("Set SCARNOX_API_KEY");
}
String pageUrl = "https://example.com/signup";
String sitekey = "YOUR-SITEKEY-UUID";
ScarnoxSolver solver = new ScarnoxSolver(apiKey);
String token = null;
for (int attempt = 1; attempt <= 3 && token == null; attempt++) {
try {
token = solver.solve(sitekey, pageUrl, false);
} catch (IllegalStateException e) {
System.err.println("Attempt " + attempt + " failed: " + e.getMessage());
Thread.sleep(attempt * 1000L);
}
}
if (token == null) {
throw new IllegalStateException("No token after 3 attempts");
}
int status = solver.submit(pageUrl, "you@example.com", token);
System.out.println("Status: " + status);
}
}
รันโปรแกรม:
export SCARNOX_API_KEY=scarnox_YOURAPIKEY
javac -cp gson-2.10.1.jar *.java
java -cp .:gson-2.10.1.jar Main
ทำไมจึงจัดโครงสร้างแบบนี้
หนึ่ง client ต่อหนึ่ง solver HttpClient ปลอดภัยต่อการใช้จากหลายเธรดและถูกออกแบบให้ใช้ซ้ำ การสร้างใหม่ทุกคำขอสิ้นเปลือง connection
เปิด cookie CookieManager บน client เก็บ session ที่โหลดฟอร์ม เพื่อให้ token ถูกส่งพร้อม cookie ที่เว็บคาดหวัง
การตรวจ error อย่างชัดเจน API ส่ง errorId เป็น 0 เมื่อสำเร็จ ค่าอื่นใดมี errorCode และ errorDescription ซึ่ง solver โยนพร้อมข้อความนั้น token อยู่ที่ solution.token
ฟิลด์ captcha ทั้งสอง ฟอร์มได้รับ h-captcha-response และ g-recaptcha-response เว็บส่วนใหญ่อ่านอย่างใดอย่างหนึ่ง
การจับเวลา
token หมดอายุภายในประมาณสองนาที ให้ solve ทันทีก่อน submit ไม่ใช่ตอนเริ่มงานยาว ๆ อายุของ captcha token อธิบายวิธีกำหนดช่วงเวลา และวิธีแยกแยะ token ที่หมดอายุออกจาก token ที่ถูกปฏิเสธ
widget แบบ invisible
ส่ง true เป็นอาร์กิวเมนต์ที่สามของ solve เมื่อ widget เป็นแบบ invisible คำขอจะมี is_invisible: true หากหน้าต้องการ JavaScript callback พร้อม token ไคลเอนต์ฝั่งเซิร์ฟเวอร์ไม่สามารถเรียกได้ และเครื่องมือ browser automation เป็นตัวเลือกที่ดีกว่า คู่มือ invisible captcha แสดงรูปแบบต่าง ๆ
การจัดการข้อผิดพลาด
การลองใหม่ครอบคลุมความล้มเหลวชั่วคราว หยุดลองใหม่กับข้อผิดพลาดที่จะไม่เปลี่ยนแปลง เช่น sitekey ผิด หรือ URL ของหน้าที่ widget ไม่ทำงาน และบันทึกไว้เพื่อทบทวน นโยบายฉบับเต็ม รวมถึงรหัสที่ควรหยุด อยู่ในการจัดการข้อผิดพลาดของ captcha solver
การ scrape อย่างรับผิดชอบ
หากโปรแกรมของคุณ scrape หน้าสาธารณะ ให้ตรวจสอบ robots.txt และข้อกำหนดของเว็บก่อน เพิ่มการหน่วงเวลาระหว่างคำขอ และเก็บเฉพาะข้อมูลส่วนบุคคลที่จำเป็น สำหรับแง่กฎหมาย ดู การ scrape เว็บถูกกฎหมายหรือไม่
ราคา
คุณจ่ายต่อการแก้ที่สำเร็จ การแก้ที่ล้มเหลวไม่มีค่าใช้จ่าย ดูราคาปัจจุบัน สำหรับอัตรา และเพื่อเริ่มต้นเริ่มด้วยเครดิตทดลองใช้ฟรี ไม่ต้องใช้บัตร