CAPSOLVER
Blog
How to solve AWS Captcha / Challenge with PHP

How to Solve AWS Captcha / Challenge with PHP: A Comprehensive Guide

Logo of CapSolver

Rajinder Singh

Deep Learning Researcher

10-Dec-2025

TLDR (Too Long; Didn't Read)

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.

Introduction

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.

What is AWS WAF CAPTCHA and Challenge?

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.

Overview of AWS WAF Actions

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.

🔎 Solving AWS Captcha / Challenge using PHP and CapSolver

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.

📕 Requirements

  • PHP (with cURL extension enabled)
  • cURL
  • CapSolver API Key (You can get one by signing up with CapSolver)

🛠️ Step 1: Setting up the Environment and Helper Functions

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 Copy
<?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;
}

⚡ Step 2: Implementing the WAF Detection and Solving Logic

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.

PHP Copy
// --- 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");
}

?>

Code Optimization Notes

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.

Conclusion

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.

Key Takeaways

  • AWS WAF Actions: AWS WAF uses a silent Challenge (HTTP 202) or a visual CAPTCHA (HTTP 405) to block bots.
  • The Goal: The ultimate objective is to obtain the aws-waf-token cookie value.
  • CapSolver API: The AntiAwsWafTask task type handles both Challenge and CAPTCHA solving, with the required parameters determining the specific solution.
  • PHP Implementation: PHP's cURL is used for requests, and preg_match is essential for extracting dynamic parameters like awsChallengeJS, awsKey, awsIv, and awsContext from the HTML source.
  • Reliability: For stable, high-volume automation, integrating a specialized solver like CapSolver is crucial, as detailed in resources like AWS WAF CAPTCHA Solver: Token & Image Solution for Scraper

FAQ: Frequently Asked Questions

Q1: Why do I need to check the HTTP status code (202 or 405)?

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.

Q2: What is the difference between 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.

Q3: My script is failing to find the 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.

Q4: Can I solve AWS WAF without using a third-party service?

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.

Q5: How long is the 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.

Compliance Disclaimer: The information provided on this blog is for informational purposes only. CapSolver is committed to compliance with all applicable laws and regulations. The use of the CapSolver network for illegal, fraudulent, or abusive activities is strictly prohibited and will be investigated. Our captcha-solving solutions enhance user experience while ensuring 100% compliance in helping solve captcha difficulties during public data crawling. We encourage responsible use of our services. For more information, please visit our Terms of Service and Privacy Policy.

More