Captcha solving service blog | SolveCaptcha
How to solve Amazon WAF captcha with Python and SolveCaptcha
Amazon WAF captcha solver: Python API example
Amazon WAF captcha can interrupt scraping, browser automation, QA, and data collection workflows protected by AWS Web Application Firewall. Solving it requires more than recognizing an image: the automation must collect several challenge parameters, submit them to a captcha-solving API, and use the returned values before the challenge expires.
This guide explains how to solve Amazon WAF captcha with Python and the [SolveCaptcha Amazon captcha solver](/captcha-solver/amazon-waf-captcha-solver-bypass).
You will learn how to:
- identify an Amazon WAF captcha page;
- extract the site key, initialization vector, context, and script URLs;
- create a SolveCaptcha task;
- poll the API until the result is ready;
- process `captcha_voucher` and `existing_token`;
- preserve the browser session while applying the solution;
- handle expired parameters and API errors.
Use this workflow only on websites you own or are authorized to test, scrape, or automate.
## What is Amazon WAF captcha?
Amazon WAF captcha is a challenge mechanism provided through AWS Web Application Firewall. A website can configure AWS WAF to display a captcha when a request matches selected security rules.
A challenge may appear because of:
- unusual request frequency;
- automated navigation patterns;
- IP reputation;
- missing or inconsistent cookies;
- suspicious browser characteristics;
- custom WAF rules;
- repeated requests to protected endpoints.
Amazon WAF captcha can contain visual or interactive puzzles. The page also loads challenge-specific JavaScript and configuration values used to validate the solution.
These values may include:
```text
key
iv
context
challenge.js URL
captcha.js URL
```
The values are generated for the current challenge and should be collected from the page where the captcha appears.
## Amazon captcha and Amazon WAF captcha
The term “Amazon captcha” can refer to several unrelated verification systems.
This article specifically covers AWS WAF captcha challenges that expose parameters such as:
```text
key
iv
context
```
and load scripts from domains similar to:
```text
*.token.awswaf.com
*.captcha.awswaf.com
```
It does not describe:
- Amazon account login captchas;
- text captchas displayed on Amazon retail pages;
- Amazon Cognito MFA;
- AWS console authentication;
- image captchas that can be solved as ordinary image-recognition tasks.
Confirm the captcha type before choosing the API method.
## How the Amazon WAF captcha workflow works
The complete workflow is:
1. Open the challenged page.
2. Preserve the current browser cookies, IP address, and User-Agent.
3. Extract the Amazon WAF captcha parameters.
4. Send the parameters to SolveCaptcha.
5. Receive a captcha task ID.
6. Wait 15–20 seconds before the first result request.
7. Poll the task every five seconds while it is processing.
8. Receive `captcha_voucher` and `existing_token`.
9. Apply the values through the same page flow used by the target website.
10. Continue the browser or HTTP session after successful validation.
SolveCaptcha expects the following method:
```text
amazon_waf
```
The task is created through:
```text
POST https://api.solvecaptcha.com/in.php
```
The result is retrieved through:
```text
GET https://api.solvecaptcha.com/res.php
```
## Required Amazon WAF parameters
The following values should be collected from the challenged page.
| Parameter | Required | Description |
|---|---:|---|
| `key` | Yes | SolveCaptcha API key |
| `method` | Yes | Must be `amazon_waf` |
| `sitekey` | Yes | Value of the Amazon WAF `key` parameter |
| `iv` | Yes | Challenge initialization vector |
| `context` | Yes | Challenge context value |
| `pageurl` | Yes | Complete URL where the captcha appears |
| `challenge_script` | Optional | Full URL of `challenge.js` |
| `captcha_script` | Optional | Full URL of `captcha.js` |
| `proxy` | Optional | Proxy used for the challenge session |
| `proxytype` | Optional | `HTTP`, `HTTPS`, `SOCKS4`, or `SOCKS5` |
| `json` | Optional | Set to `1` for JSON responses |
The `challenge_script` and `captcha_script` fields are optional in the SolveCaptcha API, but submitting them is useful when the challenge provides nonstandard or dynamically generated script URLs.
## How to find Amazon WAF captcha parameters
Open the challenged page in a browser and inspect it with developer tools.
### Find the site key
The SolveCaptcha `sitekey` value corresponds to the Amazon WAF `key` parameter.
Search the page source and loaded JavaScript for:
```text
key
```
```text
sitekey
```
```text
AwsWafCaptcha
```
```text
AwsWafIntegration
```
A page configuration may resemble:
```javascript
{
key: "AQIDAHjcYuExample...",
iv: "CgAHbCe2GgAAAAAj",
context: "9BUgmlm48F92WUoq..."
}
```
Use the value of `key` as:
```text
sitekey
```
in the SolveCaptcha request.
### Find iv
Search the page source, inline scripts, and Network response bodies for:
```text
iv
```
Example:
```javascript
iv: "CgAHbCe2GgAAAAAj"
```
Copy the complete value without truncating or decoding it.
### Find context
The `context` value is usually a long encoded string.
Example:
```javascript
context: "9BUgmlm48F92WUoqv97a49ZuEJJ50TCk9..."
```
The value can contain:
- letters;
- digits;
- plus signs;
- forward slashes;
- equals signs.
When sending it as form data through Requests, URL encoding is handled automatically.
### Find challenge_script
Open the Network panel and search for:
```text
challenge.js
```
Example:
```text
https://example.token.awswaf.com/path/challenge.js
```
Copy the complete URL, including the host and path.
### Find captcha_script
Search the Network panel for:
```text
captcha.js
```
Example:
```text
https://example.captcha.awswaf.com/path/captcha.js
```
Do not replace these URLs with values from a different challenge or domain.
### Find pageurl
Use the complete URL where the challenge appeared:
```text
https://example.com/protected/path?query=value
```
Preserve:
- scheme;
- hostname;
- path;
- query string.
Do not use only the website homepage when the captcha appeared on another URL.
## Find parameters with the browser console
The following script searches the current HTML for common Amazon WAF values:
```javascript
(() => {
const source = document.documentElement.innerHTML;
const patterns = {
sitekey: [
/\bkey\s*[:=]\s*["']([^"']+)["']/i,
/\bsitekey\s*[:=]\s*["']([^"']+)["']/i
],
iv: [
/\biv\s*[:=]\s*["']([^"']+)["']/i
],
context: [
/\bcontext\s*[:=]\s*["']([^"']+)["']/i
]
};
const result = {
sitekey: null,
iv: null,
context: null,
challenge_script: null,
captcha_script: null,
pageurl: window.location.href
};
for (const [name, expressions] of Object.entries(patterns)) {
for (const expression of expressions) {
const match = source.match(expression);
if (match) {
result[name] = match[1];
break;
}
}
}
for (const script of document.scripts) {
const src = script.src || "";
if (src.includes("challenge.js")) {
result.challenge_script = src;
}
if (src.includes("captcha.js")) {
result.captcha_script = src;
}
}
console.table(result);
return result;
})();
```
This script is only a starting point. Some pages generate the values dynamically or load them through an API response, so the Network panel may be more reliable than searching the final DOM.
## Extract parameters with Selenium
The following Python function reads the page source and script URLs from an existing Selenium session.
```python
import re
from typing import Any
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webdriver import WebDriver
class AmazonWafParameterError(RuntimeError):
"""Raised when required Amazon WAF values are missing."""
def first_match(
source: str,
patterns: list[str],
) -> str | None:
for pattern in patterns:
match = re.search(
pattern,
source,
flags=re.IGNORECASE,
)
if match:
return match.group(1)
return None
def extract_amazon_waf_parameters(
driver: WebDriver,
) -> dict[str, Any]:
source = driver.page_source
sitekey = first_match(
source,
[
r'\bkey\s*[:=]\s*["\']([^"\']+)["\']',
r'\bsitekey\s*[:=]\s*["\']([^"\']+)["\']',
],
)
iv = first_match(
source,
[
r'\biv\s*[:=]\s*["\']([^"\']+)["\']',
],
)
context = first_match(
source,
[
r'\bcontext\s*[:=]\s*["\']([^"\']+)["\']',
],
)
challenge_script = None
captcha_script = None
for script in driver.find_elements(
By.CSS_SELECTOR,
"script[src]",
):
source_url = script.get_attribute("src")
if not source_url:
continue
if "challenge.js" in source_url:
challenge_script = source_url
if "captcha.js" in source_url:
captcha_script = source_url
parameters = {
"sitekey": sitekey,
"iv": iv,
"context": context,
"challenge_script": challenge_script,
"captcha_script": captcha_script,
"pageurl": driver.current_url,
}
missing = [
name
for name in (
"sitekey",
"iv",
"context",
"pageurl",
)
if not parameters.get(name)
]
if missing:
raise AmazonWafParameterError(
"Missing Amazon WAF parameters: "
+ ", ".join(missing)
)
return parameters
```
If the required values are absent from `driver.page_source`, inspect:
- browser performance logs;
- CDP network events;
- XHR and Fetch responses;
- inline script variables;
- JSON returned by the challenge initialization request.
## Create an Amazon WAF task
Example request:
```bash
curl --request POST \
--url https://api.solvecaptcha.com/in.php \
--data-urlencode "key=YOUR_API_KEY" \
--data-urlencode "method=amazon_waf" \
--data-urlencode "sitekey=AMAZON_WAF_KEY" \
--data-urlencode "iv=AMAZON_WAF_IV" \
--data-urlencode "context=AMAZON_WAF_CONTEXT" \
--data-urlencode "challenge_script=https://example.token.awswaf.com/path/challenge.js" \
--data-urlencode "captcha_script=https://example.captcha.awswaf.com/path/captcha.js" \
--data-urlencode "pageurl=https://example.com/protected-page" \
--data-urlencode "json=1"
```
Successful response:
```json
{
"status": 1,
"request": "2122988149"
}
```
The `request` value is the captcha task ID.
Save it and use it to retrieve the result.
## Retrieve the Amazon captcha result
Wait 15–20 seconds before the first result request:
```text
GET https://api.solvecaptcha.com/res.php
```
Parameters:
```text
key=YOUR_API_KEY
action=get
id=2122988149
json=1
```
Example:
```bash
curl "https://api.solvecaptcha.com/res.php?key=YOUR_API_KEY&action=get&id=2122988149&json=1"
```
If the task is still processing:
```json
{
"status": 0,
"request": "CAPCHA_NOT_READY"
}
```
Wait five seconds and request the result again.
A completed response contains an object:
```json
{
"status": 1,
"request": {
"captcha_voucher": "CAPTCHA_VOUCHER_VALUE",
"existing_token": "EXISTING_TOKEN_VALUE"
}
}
```
Do not expect a single string token. Amazon WAF returns at least two values that must be preserved separately.
## Complete Python Amazon WAF solver
Install Requests:
```bash
python -m pip install requests
```
Set the API key:
```bash
export SOLVECAPTCHA_API_KEY="YOUR_API_KEY"
```
Create `amazon_waf_solver.py`:
```python
#!/usr/bin/env python3
import argparse
import json
import os
import time
from dataclasses import dataclass
from pathlib import Path
from typing import Any
import requests
CREATE_TASK_URL = "https://api.solvecaptcha.com/in.php"
GET_RESULT_URL = "https://api.solvecaptcha.com/res.php"
INITIAL_WAIT_SECONDS = 18
POLL_INTERVAL_SECONDS = 5
DEFAULT_TIMEOUT_SECONDS = 180
class SolveCaptchaError(RuntimeError):
"""Raised when the SolveCaptcha API returns an error."""
@dataclass(frozen=True)
class AmazonWafSolution:
task_id: str
captcha_voucher: str
existing_token: str
def parse_json_response(
response: requests.Response,
) -> dict[str, Any]:
response.raise_for_status()
try:
result = response.json()
except requests.JSONDecodeError as exc:
raise SolveCaptchaError(
"SolveCaptcha returned invalid JSON: "
f"{response.text[:500]}"
) from exc
if not isinstance(result, dict):
raise SolveCaptchaError(
f"Unexpected API response: {result!r}"
)
return result
class SolveCaptchaAmazonWafClient:
def __init__(
self,
api_key: str,
request_timeout: float = 30,
) -> None:
if not api_key:
raise ValueError(
"SolveCaptcha API key is required"
)
self.api_key = api_key
self.request_timeout = request_timeout
self.session = requests.Session()
def create_task(
self,
*,
sitekey: str,
iv: str,
context: str,
pageurl: str,
challenge_script: str | None = None,
captcha_script: str | None = None,
proxy: str | None = None,
proxy_type: str = "http",
) -> str:
required_values = {
"sitekey": sitekey,
"iv": iv,
"context": context,
"pageurl": pageurl,
}
missing = [
name
for name, value in required_values.items()
if not value
]
if missing:
raise ValueError(
"Missing required values: "
+ ", ".join(missing)
)
payload: dict[str, Any] = {
"key": self.api_key,
"method": "amazon_waf",
"sitekey": sitekey,
"iv": iv,
"context": context,
"pageurl": pageurl,
"json": 1,
}
if challenge_script:
payload["challenge_script"] = (
challenge_script
)
if captcha_script:
payload["captcha_script"] = (
captcha_script
)
if proxy:
payload["proxy"] = proxy
payload["proxytype"] = proxy_type
response = self.session.post(
CREATE_TASK_URL,
data=payload,
timeout=self.request_timeout,
)
result = parse_json_response(response)
if result.get("status") != 1:
error_code = str(
result.get("request", "UNKNOWN_ERROR")
)
raise SolveCaptchaError(
"Unable to create Amazon WAF task: "
f"{error_code}"
)
task_id = str(
result.get("request", "")
).strip()
if not task_id:
raise SolveCaptchaError(
"SolveCaptcha did not return a task ID"
)
return task_id
def get_result(
self,
task_id: str,
) -> AmazonWafSolution | None:
response = self.session.get(
GET_RESULT_URL,
params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": 1,
},
timeout=self.request_timeout,
)
result = parse_json_response(response)
if result.get("status") == 1:
answer = result.get("request")
if not isinstance(answer, dict):
raise SolveCaptchaError(
"Amazon WAF result must be "
f"an object, received: {answer!r}"
)
captcha_voucher = str(
answer.get("captcha_voucher", "")
).strip()
existing_token = str(
answer.get("existing_token", "")
).strip()
if not captcha_voucher:
raise SolveCaptchaError(
"Result does not contain "
"captcha_voucher"
)
if not existing_token:
raise SolveCaptchaError(
"Result does not contain "
"existing_token"
)
return AmazonWafSolution(
task_id=task_id,
captcha_voucher=captcha_voucher,
existing_token=existing_token,
)
error_code = str(
result.get("request", "UNKNOWN_ERROR")
)
if error_code == "CAPCHA_NOT_READY":
return None
raise SolveCaptchaError(
f"Amazon WAF task {task_id} failed: "
f"{error_code}"
)
def solve(
self,
*,
sitekey: str,
iv: str,
context: str,
pageurl: str,
challenge_script: str | None = None,
captcha_script: str | None = None,
proxy: str | None = None,
proxy_type: str = "http",
max_wait: float = DEFAULT_TIMEOUT_SECONDS,
) -> AmazonWafSolution:
task_id = self.create_task(
sitekey=sitekey,
iv=iv,
context=context,
pageurl=pageurl,
challenge_script=challenge_script,
captcha_script=captcha_script,
proxy=proxy,
proxy_type=proxy_type,
)
time.sleep(INITIAL_WAIT_SECONDS)
deadline = time.monotonic() + max_wait
while time.monotonic() < deadline:
solution = self.get_result(task_id)
if solution is not None:
return solution
time.sleep(POLL_INTERVAL_SECONDS)
raise TimeoutError(
f"SolveCaptcha task {task_id} "
f"was not completed within "
f"{max_wait:.0f} seconds"
)
def load_parameters(
path: Path,
) -> dict[str, Any]:
try:
result = json.loads(
path.read_text(
encoding="utf-8"
)
)
except FileNotFoundError as exc:
raise SystemExit(
f"Parameter file does not exist: {path}"
) from exc
except json.JSONDecodeError as exc:
raise SystemExit(
f"Invalid JSON in {path}: {exc}"
) from exc
if not isinstance(result, dict):
raise SystemExit(
"Parameter file must contain "
"a JSON object"
)
return result
def main() -> None:
parser = argparse.ArgumentParser(
description=(
"Solve an Amazon WAF captcha "
"through SolveCaptcha."
)
)
parser.add_argument(
"parameters",
type=Path,
help=(
"JSON file containing Amazon WAF "
"challenge parameters"
),
)
parser.add_argument(
"--max-wait",
type=float,
default=DEFAULT_TIMEOUT_SECONDS,
)
args = parser.parse_args()
api_key = os.environ.get(
"SOLVECAPTCHA_API_KEY",
"",
).strip()
if not api_key:
raise SystemExit(
"Set SOLVECAPTCHA_API_KEY"
)
parameters = load_parameters(
args.parameters
)
client = SolveCaptchaAmazonWafClient(
api_key=api_key
)
solution = client.solve(
sitekey=str(
parameters.get("sitekey", "")
),
iv=str(
parameters.get("iv", "")
),
context=str(
parameters.get("context", "")
),
pageurl=str(
parameters.get("pageurl", "")
),
challenge_script=parameters.get(
"challenge_script"
),
captcha_script=parameters.get(
"captcha_script"
),
proxy=parameters.get("proxy"),
proxy_type=str(
parameters.get(
"proxytype",
"http",
)
),
max_wait=args.max_wait,
)
print(
json.dumps(
{
"task_id": solution.task_id,
"captcha_voucher": (
solution.captcha_voucher
),
"existing_token": (
solution.existing_token
),
},
indent=2,
)
)
if __name__ == "__main__":
main()
```
Create `amazon-waf-parameters.json`:
```json
{
"sitekey": "AMAZON_WAF_KEY",
"iv": "AMAZON_WAF_IV",
"context": "AMAZON_WAF_CONTEXT",
"pageurl": "https://example.com/protected-page",
"challenge_script": "https://example.token.awswaf.com/path/challenge.js",
"captcha_script": "https://example.captcha.awswaf.com/path/captcha.js"
}
```
Run the client:
```bash
python amazon_waf_solver.py amazon-waf-parameters.json
```
Example output:
```json
{
"task_id": "2122988149",
"captcha_voucher": "CAPTCHA_VOUCHER_VALUE",
"existing_token": "EXISTING_TOKEN_VALUE"
}
```
## Minimal Python example
For a shorter integration:
```python
import os
import time
import requests
API_KEY = os.environ["SOLVECAPTCHA_API_KEY"]
create_payload = {
"key": API_KEY,
"method": "amazon_waf",
"sitekey": "AMAZON_WAF_KEY",
"iv": "AMAZON_WAF_IV",
"context": "AMAZON_WAF_CONTEXT",
"challenge_script": (
"https://example.token.awswaf.com/"
"path/challenge.js"
),
"captcha_script": (
"https://example.captcha.awswaf.com/"
"path/captcha.js"
),
"pageurl": (
"https://example.com/protected-page"
),
"json": 1,
}
created = requests.post(
"https://api.solvecaptcha.com/in.php",
data=create_payload,
timeout=30,
).json()
if created.get("status") != 1:
raise RuntimeError(
f"Task creation failed: "
f"{created.get('request')}"
)
task_id = created["request"]
time.sleep(18)
while True:
result = requests.get(
"https://api.solvecaptcha.com/res.php",
params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
},
timeout=30,
).json()
if result.get("status") == 1:
solution = result["request"]
break
if result.get("request") != "CAPCHA_NOT_READY":
raise RuntimeError(
f"Task failed: {result.get('request')}"
)
time.sleep(5)
print(
"captcha_voucher:",
solution["captcha_voucher"],
)
print(
"existing_token:",
solution["existing_token"],
)
```
## Using a proxy
A proxy can be submitted with the task:
```python
payload = {
"key": API_KEY,
"method": "amazon_waf",
"sitekey": sitekey,
"iv": iv,
"context": context,
"pageurl": pageurl,
"proxy": (
"login:password@"
"proxy.example.com:8000"
),
"proxytype": "http",
"json": 1,
}
```
Supported proxy types:
```text
HTTP
HTTPS
SOCKS4
SOCKS5
```
When a browser session uses a proxy, keep the proxy stable while:
- loading the challenge;
- extracting the parameters;
- waiting for the solution;
- applying the result;
- continuing to the protected page.
Changing the IP address during the challenge can invalidate the active session.
## How to use captcha_voucher and existing_token
A successful SolveCaptcha result contains:
```json
{
"captcha_voucher": "VALUE",
"existing_token": "VALUE"
}
```
The exact method for applying these values depends on the target website’s AWS WAF integration.
There is no universal HTML field or callback that applies to every Amazon WAF captcha.
To determine the required flow:
1. Open the browser Network panel.
2. Complete the challenge manually in an authorized test session.
3. Find the request sent after successful completion.
4. Inspect its request body, query parameters, headers, and cookies.
5. Identify where `captcha_voucher` and `existing_token` are included.
6. Reproduce the same request structure in the active automation session.
Do not assume the values should be placed in a generic captcha response input.
They may be used through:
- AWS WAF JavaScript functions;
- a verification request;
- browser storage;
- cookies;
- request headers;
- a callback created by the protected application.
Keep the browser page open while SolveCaptcha processes the task. Reloading the page may replace the `iv`, `context`, or other challenge parameters.
## Selenium integration workflow
A Selenium-based integration can combine parameter extraction and solving:
```python
from selenium import webdriver
driver = webdriver.Chrome()
try:
driver.get(
"https://example.com/protected-page"
)
parameters = (
extract_amazon_waf_parameters(
driver
)
)
client = SolveCaptchaAmazonWafClient(
api_key=API_KEY
)
solution = client.solve(
sitekey=parameters["sitekey"],
iv=parameters["iv"],
context=parameters["context"],
pageurl=parameters["pageurl"],
challenge_script=parameters[
"challenge_script"
],
captcha_script=parameters[
"captcha_script"
],
)
print(solution)
/*
* Apply captcha_voucher and existing_token
* through the website-specific AWS WAF
* verification flow discovered in DevTools.
*/
finally:
driver.quit()
```
Replace the comment with the target application’s actual verification logic.
Do not close, refresh, or replace the browser session before the returned values are applied.
## Extract parameters from Network responses
Some challenged pages do not expose all parameters in `page_source`.
With Chromium-based Selenium, enable performance logging:
```python
import json
from selenium import webdriver
options = webdriver.ChromeOptions()
options.set_capability(
"goog:loggingPrefs",
{
"performance": "ALL",
},
)
driver = webdriver.Chrome(
options=options
)
```
Read network events:
```python
for entry in driver.get_log(
"performance"
):
message = json.loads(
entry["message"]
)["message"]
if (
message["method"]
== "Network.responseReceived"
):
response = message[
"params"
]["response"]
url = response["url"]
if "challenge.js" in url:
print(
"Challenge script:",
url,
)
if "captcha.js" in url:
print(
"Captcha script:",
url,
)
```
To inspect JSON response bodies, use Chrome DevTools Protocol with the corresponding request ID.
This is useful when `iv` or `context` is returned by an XHR request instead of embedded in the final HTML.
## Keep challenge parameters synchronized
Amazon WAF parameters may be connected to the current challenge state.
A result should be discarded if the automation:
- reloads the page;
- navigates away;
- restarts the browser;
- changes the proxy;
- changes the User-Agent;
- receives a replacement challenge;
- waits until the challenge expires;
- modifies the session cookies.
When a challenge changes, extract a new set of values and create a new SolveCaptcha task.
Do not combine:
```text
sitekey from challenge A
iv from challenge B
context from challenge C
```
All parameters must come from the same active challenge.
## CAPCHA_NOT_READY
This response means the task is still being processed:
```json
{
"status": 0,
"request": "CAPCHA_NOT_READY"
}
```
Correct behavior:
1. Keep the same task ID.
2. Wait five seconds.
3. Request the result again.
4. Stop after a defined timeout.
Do not create duplicate tasks while the original task remains active.
## ERROR_CAPTCHA_UNSOLVABLE
This error means the challenge could not be solved reliably.
Possible causes include:
- expired `iv`;
- expired `context`;
- mismatched parameters;
- incorrect page URL;
- incomplete script URLs;
- a changed challenge;
- blocked proxy;
- unsupported challenge state.
Recommended action:
1. Reload or recreate the challenge.
2. Extract all parameters again.
3. Create a new task.
4. Limit the total number of retries.
Do not repeatedly submit the same expired challenge data.
## ERROR_WRONG_USER_KEY
The SolveCaptcha API key is invalid.
Check:
```text
SOLVECAPTCHA_API_KEY
```
Stop submitting tasks until the key is corrected.
## ERROR_ZERO_BALANCE
The SolveCaptcha account does not have enough balance.
Stop creating tasks until the balance is replenished.
## ERROR_NO_SLOT_AVAILABLE
The task cannot currently be accepted.
Use a delayed retry or exponential backoff:
```python
delay = min(
60,
5 * (2 ** attempt),
)
```
Do not continuously resend task creation requests.
## Invalid JSON and temporary HTTP errors
Production integrations should handle:
- connection timeouts;
- HTTP 500 responses;
- HTTP 502 responses;
- invalid JSON;
- interrupted connections;
- temporary DNS errors.
Recommended request settings:
```python
requests.post(
url,
data=payload,
timeout=30,
)
```
Retry only temporary transport and server errors. Do not retry permanent API errors such as an invalid key without correcting the request.
## Common implementation mistakes
### Using method=userrecaptcha
Amazon WAF requires:
```text
method=amazon_waf
```
### Using the wrong key field
The Amazon WAF challenge `key` value must be sent as:
```text
sitekey
```
to SolveCaptcha.
### Omitting iv or context
Both values are required.
### Mixing parameters from different challenges
The site key, `iv`, and `context` must belong to the same page instance.
### Reloading while waiting
A page reload may generate new challenge parameters and invalidate the pending result.
### Polling immediately
Wait approximately 15–20 seconds before the first result request.
### Polling continuously
When the API returns `CAPCHA_NOT_READY`, wait five seconds before trying again.
### Expecting a single token
The response contains:
```text
captcha_voucher
existing_token
```
### Reusing an old result
Do not reuse a voucher or token for another challenge or browser session.
### Hardcoding script URLs
Extract `challenge.js` and `captcha.js` from the current page when they are available.
### Applying values through an invented field
Inspect the real website verification request. Amazon WAF integrations do not all use the same frontend field.
## Recommended project structure
Separate parameter extraction, API communication, and browser integration:
```text
amazon_waf_solver/
├── extractor.py
├── solvecaptcha.py
├── browser.py
├── verifier.py
├── settings.py
└── main.py
```
Responsibilities:
```text
extractor.py
Finds key, iv, context, and script URLs.
solvecaptcha.py
Creates tasks and polls results.
browser.py
Manages Selenium sessions, cookies, and proxies.
verifier.py
Applies the returned values through the
target website's verification flow.
settings.py
Loads API keys, proxy data, and timeouts.
main.py
Coordinates the complete workflow.
```
This makes it easier to update selectors or request logic without rewriting the API client.
## Frequently asked questions
### What SolveCaptcha method is used for Amazon WAF?
Use:
```text
method=amazon_waf
```
### Which parameters are required?
The required challenge values are:
```text
sitekey
iv
context
pageurl
```
You must also send your SolveCaptcha API key and the `amazon_waf` method.
### Are challenge_script and captcha_script required?
They are optional API parameters. Include them when the challenged page exposes the script URLs.
### Where can I find the site key?
Search the challenged page source or initialization response for the Amazon WAF `key` value. Send that value to SolveCaptcha as `sitekey`.
### How long should I wait before checking the result?
Wait approximately 15–20 seconds before the first result request. If the response is `CAPCHA_NOT_READY`, poll again after five seconds.
### What does the completed response contain?
The response object contains:
```text
captcha_voucher
existing_token
```
### Can I use the same solution more than once?
No. Treat the result as challenge-specific and session-specific.
### Is a proxy required?
No. The API lists it as optional. When the target workflow uses a proxy, keep it stable for the entire challenge.
### Can SolveCaptcha solve every Amazon captcha?
The `amazon_waf` method applies to AWS WAF captcha challenges that expose the required parameters. Other Amazon captcha types may require a different method.
### Why does a correct solution fail?
Common causes include:
- stale challenge parameters;
- page reload;
- changed cookies;
- changed proxy;
- incorrect page URL;
- values applied through the wrong request;
- expired challenge;
- mixing parameters from different sessions.
## Conclusion
Amazon WAF captcha solving requires both challenge extraction and session-aware automation.
A reliable workflow should:
1. identify the captcha as AWS WAF;
2. extract `key`, `iv`, and `context`;
3. collect the current `challenge.js` and `captcha.js` URLs;
4. preserve the complete challenged page URL;
5. submit the task with `method=amazon_waf`;
6. wait 15–20 seconds before the first result request;
7. poll every five seconds while the task is processing;
8. process `captcha_voucher` and `existing_token` separately;
9. apply the values through the website’s actual verification flow;
10. discard the solution when the challenge or browser session changes.
Use the [SolveCaptcha Amazon WAF API](/captcha-solver-api#amazon-waf) to integrate AWS WAF captcha processing into authorized Python scraping, QA, and browser automation projects.