
Rajinder Singh
Deep Learning Researcher

This guide provides a comprehensive, step-by-step tutorial on how to bypass AWS WAF CAPTCHA and Challenge pages using PHP and the CapSolver API. We detail the logic for detecting both CAPTCHA (HTTP 405) and Challenge (HTTP 202) responses, extracting the necessary parameters, and using the resulting aws-waf-token cookie to access the protected resource.
Welcome to this comprehensive guide where we'll delve into the world of AWS CAPTCHA and how to implement a PHP solver for it. For developers and web scrapers, encountering a CAPTCHA can be a significant roadblock, but with the right tools, it becomes a manageable task.
AWS WAF (Web Application Firewall) is a security service that helps protect web applications from common web exploits. It offers two primary actions to verify that a request originates from a legitimate human user rather than a bot: CAPTCHA and Challenge.
| Action | Purpose | HTTP Status Code | Required Solution |
|---|---|---|---|
| Challenge | Runs a silent, background verification to confirm the client session is a standard browser. | 202 Accepted |
Requires solving a JavaScript challenge to obtain a token. |
| CAPTCHA | Requires the end user to solve a visual puzzle to prove they are human. | 405 Method Not Allowed |
Requires solving a visual CAPTCHA, which involves extracting specific parameters from the page. |
Once either the CAPTCHA or Challenge is successfully solved, AWS WAF issues a valid token, which is returned as the value of a cookie named aws-waf-token. This token must be included in subsequent requests to bypass the WAF protection.
CapSolver provides a robust API solution to handle both the silent Challenge and the visual CAPTCHA presented by AWS WAF. This guide focuses on using PHP's cURL library to implement the necessary logic.
The core of our solution involves two main API calls to CapSolver: createTask to submit the CAPTCHA/Challenge and getTaskResult to retrieve the solution.
<?php
// --- Configuration ---
$PROXY = "http://username:password@host:port"; // OPTIONAL: Replace with your proxy details (e.g., for AntiAwsWafTask)
$PAGE_URL = "https://norway-meetup.aws.wslab.no/"; // Replace with the target URL protected by AWS WAF
$CLIENT_KEY = "YourPayPerUsage"; // Replace with your CAPSOLVER API Key
/**
* Submits a task to the CapSolver API.
* @param array $payload The task payload containing type and parameters.
* @return array The API response, including the taskId.
*/
function createTask($payload) {
global $CLIENT_KEY;
$ch = curl_init();
echo("Creating task...\n");
curl_setopt($ch, CURLOPT_URL, 'https://api.capsolver.com/createTask');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['clientKey' => $CLIENT_KEY, 'task' => $payload]));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
/**
* Polls the CapSolver API for the task result.
* @param string $taskId The ID of the task to check.
* @return array The API response containing the solution.
*/
function getTaskResult($taskId) {
global $CLIENT_KEY;
do {
echo("Waiting for solution...\n");
sleep(1);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.capsolver.com/getTaskResult');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['clientKey' => $CLIENT_KEY, 'taskId' => $taskId]));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
if (isset($data['status']) && $data['status'] == "ready") {
return $data;
}
// Handle potential errors from getTaskResult
if (isset($data['errorId']) && $data['errorId'] != 0) {
echo("Error retrieving task result: " . $data['errorDescription'] . "\n");
return null;
}
} while(true);
}
/**
* Solves the AWS WAF Challenge or Captcha using the appropriate task type.
* @param string $taskType The CapSolver task type (AntiAwsWafTask or AwsCaptchaTask).
* @param array $params The parameters required for the task.
* @return string|null The aws-waf-token cookie value or null on failure.
*/
function solveAwsWaf($taskType, $params) {
global $PAGE_URL, $PROXY;
$payload = [
'type' => $taskType,
'websiteURL' => $PAGE_URL,
'proxy' => $PROXY,
];
// Merge specific parameters for the task
$payload = array_merge($payload, $params);
// Clean up empty values for a cleaner request
$payload = array_filter($payload, function($value) {
return $value !== "" && $value !== null;
});
$taskData = createTask($payload);
if (isset($taskData['taskId'])) {
$result = getTaskResult($taskData['taskId']);
if ($result && isset($result['solution']['cookie'])) {
return $result['solution']['cookie'];
}
}
return null;
}
The main logic involves making an initial request to the protected page and checking the HTTP status code to determine if a Challenge (202) or CAPTCHA (405) is required. We then use regular expressions to extract the necessary parameters from the HTML response body.
// --- Main Execution Logic ---
// 1. Initial request to the protected page
$ch = curl_init($PAGE_URL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$cookie = null;
echo("Initial HTTP Code: " . $httpCode . "\n");
if ($httpCode == 202) {
// --- Challenge (202) Handling ---
echo("Challenge detected (HTTP 202). Extracting parameters...\n");
// Extract the challenge.js URL
preg_match('/<script src="([^"]*token.awswaf.com[^"]*)"/', $response, $matches);
$awsChallengeJS = $matches[1] ?? null;
if ($awsChallengeJS) {
$params = ['awsChallengeJS' => $awsChallengeJS];
$cookie = solveAwsWaf("AntiAwsWafTask", $params);
} else {
echo("Error: awsChallengeJS not found for Challenge.\n");
}
} elseif ($httpCode == 405) {
// --- CAPTCHA (405) Handling ---
echo("CAPTCHA detected (HTTP 405). Extracting parameters...\n");
// Extract parameters from the page content
preg_match('/<script src="([^"]*token.awswaf.com[^"]*)"/', $response, $matches);
$awsChallengeJS = $matches[1] ?? null;
preg_match('/"key":"(.*?)"/', $response, $matches);
$awsKey = $matches[1] ?? null;
preg_match('/"iv":"(.*?)"/', $response, $matches);
$awsIv = $matches[1] ?? null;
preg_match('/"context":"(.*?)"/', $response, $matches);
$awsContext = $matches[1] ?? null;
if ($awsKey && $awsIv && $awsContext) {
$params = [
'awsKey' => $awsKey,
'awsIv' => $awsIv,
'awsContext' => $awsContext,
'awsChallengeJS' => $awsChallengeJS // Optional but recommended
];
// Note: The task type for visual CAPTCHA is often still AntiAwsWafTask,
// but the parameters passed are what determine the solution type on CapSolver's side.
$cookie = solveAwsWaf("AntiAwsWafTask", $params);
} else {
echo("Error: Key, IV, or Context parameters not found for CAPTCHA.\n");
}
}
// 3. Use the token to access the protected resource
if ($cookie) {
echo("Successfully obtained aws-waf-token. Making final request...\n");
$ch = curl_init($PAGE_URL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// Set the aws-waf-token cookie
curl_setopt($ch, CURLOPT_COOKIE, "aws-waf-token=" . $cookie);
$finalResponse = curl_exec($ch);
curl_close($ch);
echo "\n--- Final Page Content ---\n";
echo $finalResponse;
echo "\n--------------------------\n";
} else {
echo("Failed to solve AWS WAF challenge/captcha.\n");
}
?>
The original code used separate functions (solveAwsChallenge, solveAwsCaptcha) and slightly inconsistent parameter naming (key, iv, context vs. awsKey, awsIv, awsContext). The optimized code streamlines this into a single solveAwsWaf function, ensuring consistency with the latest CapSolver API documentation on solving AWS WAF. This approach is more modular and easier to maintain.
This logic is highly effective for web scraping and automation tasks. For those working in other languages, CapSolver also provides guides like "How to Solve AWS Captcha / Challenge with Python" [https://www.capsolver.com/blog/how-to-solve-aws-captcha-challenge-with-python] which follow a similar API pattern.
AWS WAF's Challenge and CAPTCHA mechanisms are effective anti-bot measures, but they are not insurmountable. By implementing a robust detection and solving logic in PHP, leveraging the power of the CapSolver API, developers can reliably obtain the necessary aws-waf-token to continue their web scraping or automation tasks uninterrupted. The key lies in correctly identifying the WAF action via the HTTP status code and accurately extracting the required parameters from the page source.
aws-waf-token cookie value.AntiAwsWafTask task type handles both Challenge and CAPTCHA solving, with the required parameters determining the specific solution.preg_match is essential for extracting dynamic parameters like awsChallengeJS, awsKey, awsIv, and awsContext from the HTML source.A: The HTTP status code is the most reliable indicator of the type of WAF action required. A 202 Accepted status code indicates a silent Challenge is active, which requires minimal parameters. A 405 Method Not Allowed status code indicates a visual CAPTCHA is active, which requires more specific parameters (key, iv, context) to be extracted from the page's JavaScript variables.
AntiAwsWafTask and AntiAwsWafTaskProxyLess?A: Both task types are designed to solve AWS WAF challenges. The primary difference is the proxy requirement. AntiAwsWafTask requires you to provide your own proxy in the request payload. AntiAwsWafTaskProxyLess does not require a proxy, as CapSolver handles the proxy usage internally. Using a proxy is often recommended for large-scale web scraping to maintain anonymity and avoid IP bans.
key, iv, or context parameters. What should I do?A: These parameters are dynamically generated and embedded within the HTML source, usually within a <script> tag or a hidden input field. If your preg_match fails, it's likely due to changes in the target website's WAF implementation. You should inspect the latest HTML source of the blocked page to update your regular expressions.
A: Solving AWS WAF challenges manually is extremely difficult and impractical for automation. The Challenge action requires executing complex, obfuscated JavaScript, and the CAPTCHA action requires solving image recognition puzzles. Third-party services like CapSolver use advanced AI and large-scale infrastructure to solve these challenges in real-time, making automation feasible. Trying to build an in-house solver for every type of CAPTCHA is generally not cost-effective or reliable.
aws-waf-token valid for?A: The validity period of the aws-waf-token is determined by the AWS WAF configuration of the protected website, but it is typically around 10-30 minutes. Once the token expires, you will need to repeat the solving process (initial request, detection, and task submission) to obtain a new token.