SurSolver

AWS WAF CAPTCHA solver API

Solve the AWS WAF image-grid CAPTCHA and get the aws-waf-token cookie value for the protected site.

Updated

$0.50 / 1K tasksCharged when a task is accepted

On this page

AWS WAF CAPTCHA task at a glance

AwsCaptchaCookie solves the "select all the …" image grid that AWS WAF shows when a web ACL rule uses the CAPTCHA action. It returns the aws-waf-token cookie value that proves the grid was completed.

Field Required Notes
type yes AwsCaptchaCookie
websiteURL yes The protected URL that answers with the CAPTCHA page
userAgent yes Your browser's User-Agent; use it again when you replay the cookie
proxy yes Your sticky proxy, as a proxy string or split proxy fields
cookies no Existing session cookies as a Cookie header value or NDJSON (one JSON object per line)

There is no site key, IV, context or script URL to collect. The solver loads the protected URL through your proxy and reads the CAPTCHA configuration from the page itself. The AWS CAPTCHA API reference has the complete request and result examples.

Image grids it answers

The puzzle is a 3×3 grid of nine pictures with one target category, for example "select all the clocks". The solver picks the tiles that show the target and confirms the selection, then repeats for a replacement grid if AWS issues one.

A 3 by 3 AWS WAF CAPTCHA grid asking for clocks; tile numbers 0 to 8 are overlaid

Other layouts and multi-target puzzles are outside the current integration. Those tasks fail instead of returning a guessed answer, and a failed task returns its original charge once.

Use the aws-waf-token result

When ready, set solution["aws-waf-token"] as the aws-waf-token cookie on the protected site. Merge the name-to-value entries in solution.cookies when present, then repeat the request through the same proxy with the same userAgent. No token alias or new user agent is returned.

A valid WAF cookie does not bypass a login or any other application rule. Keep the application's own session cookies when your flow needs them.

Pick the right AWS task

The protected URL answers with Use
A visual CAPTCHA page AwsCaptchaCookie (this page)
The silent JavaScript challenge AwsChallengeCookie

If the URL serves only the silent challenge, AwsCaptchaCookie fails instead of reporting a solved CAPTCHA. Execution can take up to the 120-second CAPTCHA budget, so keep polling getTaskResult rather than submitting the same task again.

For the response headers that tell the two actions apart, how token lifetime works, and a failure checklist, read the AWS WAF CAPTCHA guide.

Request and ready result

Send the actual CAPTCHA-protected URL to POST /createTask. The values below are placeholders; cookies is optional and carries the existing blocked session:

snippet.json
{
  "clientKey": "sur_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "task": {
    "type": "AwsCaptchaCookie",
    "websiteURL": "https://example.com/protected",
    "userAgent": "YOUR_SUPPORTED_USER_AGENT",
    "proxy": "http://user:password@proxy.example.com:8080",
    "cookies": "session=YOUR_SESSION"
  }
}

Poll POST /getTaskResult with clientKey and the returned taskId until it is ready or fails:

snippet.json
{
  "errorId": 0,
  "status": "ready",
  "solution": {
    "aws-waf-token": "<aws-waf-token-value>"
  }
}

Keep the value unchanged and use it under the cookie name aws-waf-token. Do not send it as an image answer, copy another task's cookie, or substitute the silent Challenge task for the visual CAPTCHA.

Complete solve and replay example

The script sends the current session to the solve, polls the result, replaces aws-waf-token while preserving the other cookies, and retries the page through the same proxy and User-Agent. Set SUCCESS_TEXT to text that appears only in an accepted application response.

aws-captcha-python.py
# aws-captcha-python.py - solve AWS WAF CAPTCHA and request the protected page with the
# aws-waf-token cookie.
# Install: pip install requests
# Run: python aws-captcha-python.py

import time

import requests


# Your SurSolver API key.
CLIENT_KEY = "sur_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# The protected page that answers with the challenge.
TARGET_URL = "https://example.com/page"
# The proxy for the solve and the replay: http://user:pass@host:port or socks5://host:port.
PROXY_URL = "http://username:password@proxy.example.com:8080"
# Existing session cookies as a Cookie header value (name=value; name2=value2).
SESSION_COOKIES = None
# The User-Agent the solve runs with; send the result with this same user agent.
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36"
# Text that appears only in a response the site accepted.
SUCCESS_TEXT = "PASTE_ACCEPTED_MARKER"


API = "https://api.sursolver.com"
POLL_ATTEMPTS = 60


def call(path, body):
    # API errors are HTTP 200 with errorId 1; anything else is a transport failure.
    response = requests.post(f"{API}{path}", json=body, timeout=30)
    response.raise_for_status()
    data = response.json()
    if data["errorId"] != 0:
        raise RuntimeError(f'{data["errorCode"]}: {data["errorDescription"]}')
    return data


def solve(task):
    created = call("/createTask", {"clientKey": CLIENT_KEY, "task": task})
    for _ in range(POLL_ATTEMPTS):
        result = call("/getTaskResult", {"clientKey": CLIENT_KEY, "taskId": created["taskId"]})
        if result["status"] == "ready":
            return result["solution"]
        time.sleep(3)
    raise TimeoutError(f'task {created["taskId"]} was not ready in {POLL_ATTEMPTS} polls')


def without_empty(fields):
    # Optional task fields are sent only when they have a value.
    return {name: value for name, value in fields.items() if value not in (None, "")}


PROXIES = {"http": PROXY_URL, "https": PROXY_URL}


def main():
    solution = solve({
        "type": "AwsCaptchaCookie",
        "websiteURL": TARGET_URL,
        "userAgent": USER_AGENT,
        **without_empty({
            "cookies": SESSION_COOKIES,
        }),
        "proxy": PROXY_URL,
    })

    # Replay with the user agent the solve ran with, through the same proxy.
    headers = {"User-Agent": USER_AGENT}
    cookies = dict(part.strip().split("=", 1) for part in (SESSION_COOKIES or "").split(";")
                   if "=" in part)
    cookies["aws-waf-token"] = solution["aws-waf-token"]
    cookies = {
        **cookies,
        **solution.get("cookies", {}),
        "aws-waf-token": solution["aws-waf-token"],
    }
    response = requests.get(
        TARGET_URL,
        headers=headers,
        cookies=cookies,
        proxies=PROXIES,
        timeout=30,
    )
    if not response.ok or SUCCESS_TEXT not in response.text:
        raise SystemExit(f"The site did not accept the result (HTTP {response.status_code}).")
    print("The site accepted the result.")


if __name__ == "__main__":
    main()

SESSION_COOKIES in this script is a Cookie header string. For browser automation, install the solved cookie on the protected origin in the same context, then repeat the protected action.

Troubleshooting

Symptom Check Correction
No image puzzle is reached The response is the silent challenge or an ordinary page Choose the task matching the current WAF action
Unsupported puzzle failure Layout is not a supported single-target 3×3 grid Do not treat it as a solved CAPTCHA
Cookie is generated but the page still blocks Exit IP, User-Agent or cookie domain changed Keep the original proxy session and replay identity
HTTP 200 still contains a challenge Status alone was treated as acceptance Check an application-specific response marker
A task is still processing The visual solve has not reached its terminal state Keep polling the same task within its budget; do not create duplicates

FAQ

Is AWS CAPTCHA different from AWS WAF Challenge?

Yes. AwsCaptchaCookie solves the visual CAPTCHA page. AwsChallengeCookie handles the separate silent JavaScript challenge. A silent challenge token does not prove that a CAPTCHA was completed.

Which inputs does AWS CAPTCHA require?

Send websiteURL, your browser userAgent and your proxy. The solver discovers the CAPTCHA page scripts and configuration itself. No site key, IV or context field is required.

What is returned?

solution["aws-waf-token"] contains the cookie value. solution.cookies contains additional returned cookies as a name-to-value object when available. Replay through the same proxy and userAgent.

Which visual CAPTCHA puzzles are supported?

The current integration handles supported single-target 3 by 3 image-selection grids. Other grid layouts or multi-target puzzles fail rather than returning a guessed solution.

Why can the task fail before showing an image puzzle?

The URL may serve a silent challenge, a normal page or a different block instead of the CAPTCHA page. Check the current response and choose the task matching the action it actually serves.