Captcha solver ใน PHP ด้วย cURL: ตัวอย่างการทำงาน (2026)
PHP ต้องใช้เพียงส่วนขยาย cURL ซึ่งมาพร้อมการติดตั้งส่วนใหญ่ เพื่อแก้ captcha คุณส่ง JSON POST หนึ่งครั้งไปยัง Scarnox API อ่าน solution.token จากการตอบกลับ แล้วส่ง token นั้นไปยังฟอร์มของเว็บ คู่มือนี้พาดูโฟลว์ PHP ฉบับเต็มสำหรับ PopularCaptcha ซึ่ง Scarnox แก้ได้ในวันนี้แบบ proxyless
เริ่มด้วยเครดิตทดลองใช้ฟรี ไม่ต้องใช้บัตร และลองสคริปต์กับหน้าที่คุณควบคุมก่อนนำไปใช้กับสิ่งอื่น
สิ่งที่ต้องมี
- PHP 8.0 ขึ้นไป พร้อมเปิดส่วนขยาย
curlและjsonตรวจด้วยphp -m - Scarnox API key
- sitekey ของ widget PopularCaptcha ในหน้า หากต้องการความช่วยเหลือในการหา ดูวิธีหา sitekey ของ captcha
ฟังก์ชัน solver
ฟังก์ชันนี้ POST ไปยัง API ตรวจ errorId และคืน token มันโยน exception เมื่อมีความล้มเหลวใด ๆ เพื่อให้ผู้เรียกตัดสินใจว่าจะลองใหม่หรือไม่
<?php
declare(strict_types=1);
const SCARNOX_API_KEY = 'scarnox_YOURAPIKEY';
const SCARNOX_API_URL = 'https://api.scarnox.com/api/tasks/create';
function solveCaptcha(string $sitekey, string $pageUrl, bool $invisible = false): string
{
$body = [
'captcha_type' => 'PopularCaptchaTaskProxyless',
'site_key' => $sitekey,
'site_url' => $pageUrl,
];
if ($invisible) {
$body['is_invisible'] = true;
}
$ch = curl_init(SCARNOX_API_URL);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($body, JSON_THROW_ON_ERROR),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . SCARNOX_API_KEY,
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 185, // การเรียกจะส่งกลับเมื่อ token พร้อมแล้ว
]);
$raw = curl_exec($ch);
if ($raw === false) {
$error = curl_error($ch);
throw new RuntimeException('cURL error: ' . $error);
}
$data = json_decode((string) $raw, true);
if (!is_array($data)) {
throw new RuntimeException('Response was not JSON');
}
if (($data['errorId'] ?? 1) !== 0) {
throw new RuntimeException(
($data['errorCode'] ?? 'ERROR') . ': ' . ($data['errorDescription'] ?? 'unknown')
);
}
return (string) $data['solution']['token'];
}
header Authorization ใช้คำนำหน้า Bearer timeout คือ 185 วินาที เพราะ API บล็อกจนกว่า token จะพร้อม ไม่มีขั้น polling
ลองใหม่เมื่อล้มเหลวชั่วคราว
การแก้ที่ล้มเหลวไม่ถูกเรียกเก็บเงิน ดังนั้นการลองซ้ำไม่กี่ครั้งจึงถูก ใส่ลูปรอบการเรียกและรอนานขึ้นหลังทุกความล้มเหลว
function solveWithRetry(string $sitekey, string $pageUrl, int $attempts = 3): string
{
$lastError = null;
for ($i = 1; $i <= $attempts; $i++) {
try {
return solveCaptcha($sitekey, $pageUrl);
} catch (RuntimeException $e) {
$lastError = $e;
fwrite(STDERR, "Attempt $i failed: " . $e->getMessage() . PHP_EOL);
sleep($i);
}
}
throw $lastError;
}
สำหรับนโยบายข้อผิดพลาดที่สมบูรณ์ รวมถึงความล้มเหลวที่ควรหยุด ดูการจัดการข้อผิดพลาดของ captcha solver
submit token ด้วย cookie jar
หลายเว็บผูก captcha กับ session ที่โหลดฟอร์ม ไฟล์ cookie ช่วยให้ cURL ส่ง cookie เดียวกันทั้งใน GET และ POST ฟังก์ชันด้านล่าง submit token ไปยังฟอร์มของหน้า
function submitToken(string $pageUrl, string $token): string
{
$cookieFile = sys_get_temp_dir() . '/scarnox-cookies.txt';
// GET ก่อน เพื่อให้เว็บตั้งค่า session cookie
$ch = curl_init($pageUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_COOKIEFILE => $cookieFile,
CURLOPT_COOKIEJAR => $cookieFile,
CURLOPT_TIMEOUT => 60,
]);
curl_exec($ch);
// จากนั้น POST ฟอร์มพร้อม token ในฟิลด์ captcha ทั้งสองฟิลด์
$fields = http_build_query([
'email' => 'you@example.com',
'h-captcha-response' => $token,
'g-recaptcha-response' => $token,
]);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $fields,
CURLOPT_TIMEOUT => 60,
]);
$body = curl_exec($ch);
if ($body === false) {
throw new RuntimeException('Form submit failed: ' . curl_error($ch));
}
return (string) $body;
}
มีสองเรื่องที่สำคัญ GET ทำงานก่อนการแก้ เพื่อให้ cookie อยู่ในที่ และ token ถูกส่งออกไปทันทีหลังการแก้ เพราะ token หมดอายุภายในประมาณสองนาที วางการเรียกแก้ไว้ก่อนฟังก์ชันนี้โดยตรง ไม่ใช่ตอนเริ่มชุดงานยาว ๆ
ไฟล์ cookie ถูกใช้ร่วมกันโดยทุกการเรียกในโปรเซสเดียวกัน ดังนั้นให้แต่ละบัญชีหรือ session มีไฟล์ของตัวเองหากคุณรันการสมัครสมาชิกหลายรายการพร้อมกัน มิฉะนั้น session หนึ่งอาจเขียนทับ cookie ของอีก session และ POST ที่สองจะล้มเหลวด้วยเหตุผลที่ดูเหมือนปัญหาของ captcha แต่จริง ๆ ไม่ใช่
รวมเข้าด้วยกัน
$pageUrl = 'https://example.com/signup';
$token = solveWithRetry('YOUR-SITEKEY-UUID', $pageUrl);
$html = submitToken($pageUrl, $token);
echo strlen($html) . " bytes returned\n";
รันจากบรรทัดคำสั่ง:
php signup.php
widget แบบ invisible
หาก widget เป็นแบบ invisible ให้เรียก solveCaptcha($sitekey, $pageUrl, true) ฟิลด์ is_invisible จะถูกส่งไปพร้อมคำขอ บางหน้าต้องมี JavaScript callback ที่รับ token ซึ่งสคริปต์ฝั่งเซิร์ฟเวอร์เรียกไม่ได้ ในกรณีนั้นให้ใช้เครื่องมือเบราว์เซอร์แทน คู่มือ invisible captcha ครอบคลุมกรณีต่าง ๆ
จับเวลาและการหมดอายุ
token ใช้ได้ประมาณสองนาที ให้การแก้และการ submit อยู่ใกล้กันในเวลา อายุของ captcha token อธิบายวิธีแยก token ที่หมดอายุออกจาก token ที่ถูกปฏิเสธ
การ scrape อย่างรับผิดชอบ
หากสคริปต์ PHP ของคุณ scrape หน้าสาธารณะ ให้ตรวจสอบ robots.txt และข้อกำหนดของเว็บก่อนเริ่ม เพิ่มการหน่วงเวลาระหว่างคำขอ และอย่าเก็บข้อมูลส่วนบุคคลที่ไม่จำเป็น การแก้ captcha ไม่ได้เปลี่ยนสิ่งที่คุณได้รับอนุญาตให้เก็บ สำหรับด้านกฎหมาย ดู การ scrape เว็บถูกกฎหมายหรือไม่
ราคา
คุณจ่ายต่อการแก้ที่สำเร็จ การแก้ที่ล้มเหลวไม่ถูกเรียกเก็บเงิน ดูหน้าราคา สำหรับอัตราปัจจุบัน และเริ่มด้วยเครดิตทดลองใช้ฟรี ไม่ต้องใช้บัตร