AWS WAF CAPTCHA
Choose a token flow or an image classification task. Choose an end-to-end WAF solve for a token and cookie session, or classification when you already drive the image-grid challenge yourself.
{
"clientKey": "capzy_YOUR_API_KEY",
"task": {
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "https://example.com/protected-page"
}
}Illustrative values. Replace the inputs with values from your current integration.
Choose the AWS task you actually need.
Choose an end-to-end WAF solve for a token and cookie session, or classification when you already drive the image-grid challenge yourself.
Your API key authenticates Capzy.
Provider keys, challenge IDs, images, and session values belong inside task.
Start with the protected URL and current WAF scripts.
- Copy the protected page's full URL into websiteURL. In Network, locate challenge.js, captcha.js, or jsapi.js if you are supplying explicit script URLs.
- When forwarding window.gokuProps, capture key, iv, and context from the same page load into awsKey, awsIv, and awsContext.
- Preserve awsWafCookieDomainList and an existing token only when continuing that current WAF session. Otherwise let the end-to-end task inspect the page.
{
"websiteURL": "https://example.com/protected",
"awsKey": "CURRENT_GOKU_KEY",
"awsIv": "CURRENT_GOKU_IV",
"awsContext": "CURRENT_GOKU_CONTEXT"
}The three gokuProps values are optional captured context. Never combine key, iv, or context from separate challenges.
Provider integration documentationHow AWS WAF CAPTCHA works
AWS WAF is Amazon's Web Application Firewall bot protection. It applies one of two actions (via the x-amzn-waf-action header): • Challenge — a silent proof-of-work the browser runs invisibly. No visible puzzle; the page just needs a valid aws-waf-token. • CAPTCHA — a visible image grid AWS escalates to for higher-risk sessions ("choose all the chairs"). A Challenge token does NOT clear a CAPTCHA gate — the site just re-serves the puzzle. AntiAwsWafTask covers BOTH end-to-end: we read the enforced action and route to the right solver automatically, so you don't have to know which one a page is on.
AntiAwsWafTask / …ProxyLess: we pre-flight the target to read the enforced action. • Challenge — we run the site's real challenge.js and hand back the exact aws-waf-token AWS issues, correct by construction as AWS rotates the script. • CAPTCHA (image grid) — we host the widget on a coherent page, solve the tiles with our vision model, let AWS's own captcha.js mint the token, and return it. Chained rounds are handled for you. Typical solve ~3-11s. Either way you get a ready-to-replay aws-waf-token plus the coherent userAgent. AwsWafClassification remains available if you drive your own browser and only want tile indices.
- One task type solves BOTH the silent Challenge and the image-grid CAPTCHA (auto-detected)
- Silent Challenge from just a website URL — runs the site's real challenge.js
- Image-grid CAPTCHA solved end-to-end: we host the widget, classify, and mint the token
- Returns a ready aws-waf-token + userAgent + cookie array to replay
- Drop-in for CapSolver params + accepts CapMonster (AmazonTask) field names
Know what goes in.
Choose a field to see its purpose, where to get it, and its place in the request. Optional values omitted from the example can be added when your flow uses them.
The common case: a silent proof-of-work, no visible puzzle. Send just the websiteURL — we run the site's real challenge.js and return the aws-waf-token.
Request authentication
Required task inputs
Optional context
websiteURL
stringRequiredThe URL of the page protected by AWS WAF. For most sites this is ALL you need — we fetch it, read the enforced action, and solve Challenge or CAPTCHA accordingly. The fields below are only for SPA / session-bound pages where the challenge isn't in the server-side response.
Copy the full page URL from the address bar or the document request in Network, including the path where this flow runs.
Open the input guidehttps://example.com/protected-page{
"clientKey": "capzy_YOUR_API_KEY",
"task": {
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "https://example.com/protected-page"
}
}The selected field is highlighted when present. Preserve the declared value type and current challenge context.
Make your first request.
Create the task, keep its taskId, and poll until status is ready. Then read the selected variant's solution.
- Create the task
Send
clientKeyand the selectedtaskto/createTaskfrom your server. Keep the returnedtaskId. - Wait for the solution
Send that same key and ID to
/getTaskResult. While processing, wait two seconds before checking again. Stop on Ready or an error. - Apply the result
For end-to-end solving, preserve the scoped solution.cookies and solution.userAgent and use solution.token as aws-waf-token in that session. For classification, use objects in your own verification flow; do not treat indices as a token.
import json, os, time
import requests
API = "https://api.capzy.ai"
KEY = os.environ["CAPZY_API_KEY"]
task = json.loads("{\"type\":\"AntiAwsWafTaskProxyLess\",\"websiteURL\":\"https://example.com/protected-page\"}")
def call(path, payload):
response = requests.post(f"{API}/{path}", json={"clientKey": KEY, **payload}, timeout=30)
response.raise_for_status()
data = response.json()
if data.get("errorId", 0) or data.get("status") == "failed":
raise RuntimeError(data.get("errorDescription") or data.get("errorCode") or "Task failed")
return data
created = call("createTask", {"task": task})
for attempt in range(60):
result = call("getTaskResult", {"taskId": created["taskId"]})
if result.get("status") == "ready":
solution = result["solution"]
print(solution)
break
time.sleep(2)
else:
raise TimeoutError("Task is still processing; keep the taskId to check it later.")
Before runningReplace all illustrative inputs with your captured values. Set CAPZY_API_KEY in your environment. Install requests with pip install requests.
Polling and failuresThe example checks HTTP/API failures, uses 30-second request timeouts, and stops after 60 result checks. Retain taskId if your task is still processing.
Understand what comes back.
Follow this task from creation to completion. Response fields and usage follow your selected request variant.
WAF token or classified objects
For end-to-end solving, preserve the scoped solution.cookies and solution.userAgent and use solution.token as aws-waf-token in that session. For classification, use objects in your own verification flow; do not treat indices as a token.
- string
- The aws-waf-token value (both Challenge and CAPTCHA). Replay it as the aws-waf-token cookie on requests to the protected site.
- object[]
- Ready-to-use cookie array: [{name:"aws-waf-token", value, domain, path}] scoped to the target — drop straight into a cookie jar.
- string
- The exact user-agent we solved with. Replay the token with THIS UA — the token is bound to the browser fingerprint, so a mismatch is rejected.
{
"errorId": 0,
"status": "ready",
"solution": {
"token": "d6975ede-…:EQoA…:<signed aws-waf-token>",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) … Chrome/152.0.0.0 Safari/537.36",
"cookies": [
{
"name": "aws-waf-token",
"value": "d6975ede-…",
"domain": "example.com",
"path": "/"
}
]
}
}Illustrative values. Additional metadata may be returned; only Ready contains a completed solution.
Install the scoped AWS WAF token
Install every returned scoped cookie, including aws-waf-token, and use the matching userAgent. Keep the original session and solve proxy when one was supplied. Retain Set-Cookie updates from subsequent responses.
Execution context result is the parsed Ready response from the polling example. session, when referenced, is your existing requests.Session (or browser-compatible session) with the original cookie jar, headers, and solving proxy configured in session.proxies for both http and https. Keep this client for the complete flow. task is the task object you submitted. For Shape, action_body is the original protected request body as bytes or a string, with its original Content-Type in session.headers. Install curl_cffi when the fragment imports it; match the target's required browser/TLS identity.
sol = result["solution"]
for cookie in sol["cookies"]:
session.cookies.set(cookie["name"], cookie["value"],
domain=cookie["domain"], path=cookie.get("path", "/"))
session.headers["User-Agent"] = sol["userAgent"]
# Keep the original proxy and cookie jar; responses can refresh the token.
response = session.get("https://target.example.com/", timeout=30)
print(response.status_code)When something doesn't work.
Check your captured values, the selected variant, and the response before starting another task.
Which task type should I use?
AntiAwsWafTask for almost everything — it auto-detects whether the site enforces the silent Challenge or the visible image-grid CAPTCHA and solves either, returning a ready aws-waf-token. Use AntiAwsWafTaskProxyLess to have us route the proxy, or AntiAwsWafTask with your own proxy (recommended — a consistent, trusted IP means fewer CAPTCHA rounds). Reach for AwsWafClassification only if you already drive the widget in your own browser and just want tile indices.
I use CapSolver / CapMonster — do I need to change my params?
No. AntiAwsWafTask accepts the same optional fields as CapSolver (awsKey/awsIv/awsContext/awsChallengeJS/awsApiJs), and CapMonster's AmazonTask field names are accepted as aliases: websiteKey→awsKey, context→awsContext, iv→awsIv, challengeScript→awsChallengeJS, captchaScript→awsCaptchaJS. Point your existing payload at us and it works.
The site shows a "choose all the …" image grid — can you solve it?
Yes, end-to-end. Send AntiAwsWafTask with the websiteURL (+ a proxy) and we host the widget, classify the tiles with our vision model, let AWS's own captcha.js mint the token, handle any chained rounds, and return the aws-waf-token + the userAgent to replay with. No need to send tiles yourself.
What do I send for the Challenge (token) flow?
Just websiteURL for most sites — we fetch it, discover the challenge.js, and mint the token. You only need the extra fields when the challenge isn't in that server-side response: SPA / hash-routed / async / session-bound pages (like Amazon's account-verification flow). For those, capture the challenge in your own session and pass awsChallengeJS (the challenge.js script URL) — or awsApiJs (the jsapi.js SDK URL) if the site uses the AWS WAF JavaScript API. For best fidelity on hardened sites, also pass all three of awsKey / awsIv / awsContext from window.gokuProps, from the same page load (iv/context expire in ~30s).
The token flow returns "AWS WAF challenge not detected" — what now?
That page renders the challenge in the browser, so we can't see it from a server-side fetch. Open the WAF page in your own browser/scraper, read window.gokuProps and the challenge.js (or jsapi.js) <script src>, and pass them as awsChallengeJS / awsApiJs plus awsKey / awsIv / awsContext. Note session-bound flows (e.g. Amazon CVF) require values from your live session — a cold fetch on our side can't reproduce them.
How do I use the returned token?
Set it as the aws-waf-token cookie (or header) on your HTTP client before requesting the protected page.
What images do I send to AwsWafClassification?
The ~9 grid tiles as base64-encoded PNG/JPEG strings, ordered top-left to bottom-right. We return the 0-based indices (objects) of the tiles that matched your target label. Critical: send the tiles as the browser RENDERS them (screenshot the visible grid / read the decoded canvas), NOT the raw <img> or blob bytes. AWS ships each tile obfuscated and reassembles it in-browser, so the raw bytes are unrecognizable noise — we detect that and reject it with ERROR_INVALID_TASK_DATA rather than guessing.
Does AwsWafClassification support the toy-car or rotate puzzles?
No. Only the image-grid puzzles (aws:grid:* labels) are supported. The toy-car-path and rotate CAPTCHA variants are not currently solved.
Connect AWS WAF CAPTCHA to your workflow.
Get your Capzy API key and use this guide's integration.
AntiAwsWafTaskProxyLess · Live configuration