AWS WAF Captcha
Solve AWS WAF challenges automatically with our API
Overview
AWS WAF (Web Application Firewall) uses JavaScript challenges to protect websites. Our API solves these challenges and returns the required cookie token.
Supported Task Types
| Task Type | Proxy Required | Description |
|---|---|---|
AntiAwsWafTaskProxyLess | No | Web challenge — uses our built-in proxy infrastructure |
AntiAwsWafTask | Yes | Web challenge — requires your own proxy |
AntiAwsWafMobileTask | No | Mobile app token — minted by the genuine AWS WAF mobile SDK on real devices. No URL, parameters, or proxy. See Mobile App Token. |
Create Task
Endpoint: POST /createTask
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
clientKey | String | Yes | Your API key |
task.type | String | Yes | AntiAwsWafTaskProxyLess or AntiAwsWafTask |
task.websiteURL | String | Yes | Target page URL with WAF protection |
task.awsChallengeJS | String | No | URL of the challenge.js script |
task.awsApiJs | String | No | URL of the jsapi.js script (CAPTCHA flow) |
task.awsKey | String | No | The key value from captcha page |
task.awsIv | String | No | The iv value from captcha page |
task.awsContext | String | No | The context value from captcha page |
task.awsProblemUrl | String | No | The problem endpoint URL |
task.awsApiKey | String | No | The api_key value |
task.awsExistingToken | String | No | Previous aws-waf-token for refresh |
task.proxy | String | No | Proxy (required for AntiAwsWafTask). See Proxy Format |
Response
{
"errorId": 0,
"taskId": "61138bb6-19fb-11ec-a9c8-0242ac110006"
}Get Task Result
Endpoint: POST /getTaskResult
Request
{
"clientKey": "YOUR_API_KEY",
"taskId": "61138bb6-19fb-11ec-a9c8-0242ac110006"
}Response (Ready)
{
"errorId": 0,
"status": "ready",
"solution": {
"cookie": "aws-waf-token=xxxxxxxx...",
"token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:...",
"captchaVoucher": "eyJ...",
"userAgent": "Mozilla/5.0 ..."
}
}captchaVoucher is returned only for the visual-CAPTCHA flow (Situation 4) — submit it to the Amazon CVF endpoint /aaut/verify/cvf/{jwt}. The PoW flow (challenge.js) returns just cookie + token.
Mobile App Token (AntiAwsWafMobileTask)
Some native mobile apps protect their API with the AWS WAF mobile SDK instead of the web JavaScript challenge. For these, the aws-waf-token is minted on-device by the app's genuine SDK (a PBKDF2 proof-of-work over device signals) — there is no challenge.js, no page parameters, and no proxy.
AntiAwsWafMobileTask returns a genuine, freshly-minted mobile aws-waf-token. Present it to the target API exactly as the app does — as a Cookie: aws-waf-token=<token> header.
No parameters needed
Unlike the web task types, the mobile task takes only task.type — no websiteURL, no awsChallengeJS/awsApiJs, no proxy. The token is device/PoW-based and works from your own IP.
Request
{
"clientKey": "YOUR_API_KEY",
"task": { "type": "AntiAwsWafMobileTask" }
}Response (Ready)
{
"errorId": 0,
"status": "ready",
"solution": {
"token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:DAoA...:...",
"cookie": "aws-waf-token=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:DAoA...:...",
"userAgent": "gyg_app/... CFNetwork/... Darwin/...",
"captchaMethod": "mobile_sdk_pow"
}
}Send the returned cookie (or build the header yourself as aws-waf-token=<token>) with your request to the protected mobile API endpoint.
Fast & fresh
Mobile tokens are served from a continuously-refreshed warm pool — solves typically return in 1-3 seconds. Tokens are single-use and short-lived; request one per protected call and present it promptly.
Per-app coverage
Mobile tokens are minted per target app. Contact us to confirm or add coverage for the app you're targeting.
Parameter Situations (web challenges)
AWS WAF can be configured in different ways. Choose the situation that matches your target website.
Situation 1: Automatic Detection
When to use: You only have the website URL and want us to handle everything automatically.
Recommended approach
Auto-detection is the simplest method. Start here and only use manual parameters if auto-detection fails or you need more control.
Simply provide the websiteURL. Our system will visit the page, look for window.gokuProps (containing key, iv, context) and detect any challenge.js or jsapi.js scripts automatically.
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "https://example.com/protected-page"
}
}Situation 2: Manual Parameters
When to use: You have extracted key, iv, context, and challenge.js URL manually.
Required parameters: awsKey, awsIv, awsContext, awsChallengeJS
How to find them:
- Open DevTools (F12) → Network tab
- Look for requests to
*.token.awswaf.com - Find
window.gokuPropsin the HTML containingkey,iv,context
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "https://example.com/protected-page",
"awsKey": "AQIDAHjA1234567890abcdefghijklmnop...",
"awsIv": "a1b2c3d4e5f6g7h8",
"awsContext": "eyJ0eXBlIjoiQ0FQVENIQSIsImNhcHRjaGFTY3JpcH...",
"awsChallengeJS": "https://b516434d791a.aa24f28d.eu-west-1.token.awswaf.com/b516434d791a/challenge.js"
}
}Situation 3-1: Challenge.js Only
When to use: You can find challenge.js on the page but not the manual parameters (key, iv, context).
This is the most common scenario. The challenge.js script handles the WAF challenge (PoW token generation) automatically.
How to find it:
- Open DevTools → Network tab
- Filter by
challenge.js - Copy the full URL (format:
https://{apiKey}.{accountId}.{region}.token.awswaf.com/{apiKey}/challenge.js)
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "https://example.com/protected-page",
"awsChallengeJS": "https://b516434d791a.aa24f28d.eu-west-1.token.awswaf.com/b516434d791a/challenge.js"
}
}Situation 3-2: jsapi.js Only
When to use: You cannot find challenge.js on the page, but you can find jsapi.js. The challenge.js script is assembled from the code inside jsapi.js, so either URL works.
challenge.js vs jsapi.js
Both URLs point to the same WAF system. If you can only find jsapi.js in the network requests, use this situation. Our system will handle the rest.
How to find it:
- Open DevTools → Network tab
- Filter by
jsapi.js - Copy the full URL (format:
https://{apiKey}.{accountId}.{region}.captcha.awswaf.com/{apiKey}/jsapi.js)
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "https://example.com/protected-page",
"awsApiJs": "https://b516434d791a.aa24f28d.eu-west-1.captcha.awswaf.com/b516434d791a/jsapi.js"
}
}Situation 4: Problem URL (Visual CAPTCHA)
When to use: You have the problem endpoint URL containing CAPTCHA configuration. This is used for visual CAPTCHA challenges (e.g., grid image selection).
The problem URL contains information about the visual CAPTCHA type and required solutions.
How to find it:
- Open DevTools → Network tab
- Filter by
problem - Look for URLs like:
https://xxx.captcha.awswaf.com/xxx/problem?kind=visual&...
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "https://example.com/protected-page",
"awsProblemUrl": "https://xxx.us-east-1.captcha.awswaf.com/xxx/problem?kind=visual&domain=example.com&problem=gridcaptcha-5-0.15-0&num_solutions_required=2"
}
}Optional: awsApiJs
You can optionally include awsApiJs alongside awsProblemUrl for faster solving, but it is not required.
Situation 5: Token Refresh (Secondary Verification)
When to use: You need to upgrade an existing token for higher security operations (SignUp, checkout, etc.). The problem endpoint typically contains an api_key value that is constant per website.
Some protected actions require a "fresh" token even if you already have a valid one.
Required parameters: awsExistingToken + awsApiJs or awsChallengeJS (whichever is available on the page)
Optional: awsApiKey - the api_key value found in the problem endpoint URL
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "https://example.com/signup",
"awsApiJs": "https://xxx.captcha.awswaf.com/xxx/jsapi.js",
"awsApiKey": "your_api_key_value",
"awsExistingToken": "aws-waf-token=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:..."
}
}Or with challenge.js:
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "https://example.com/signup",
"awsChallengeJS": "https://xxx.token.awswaf.com/xxx/challenge.js",
"awsExistingToken": "aws-waf-token=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:..."
}
}How to Find the Right Parameters
challenge.js vs jsapi.js - which one do I need?
Use awsChallengeJS (challenge.js) for basic page access. Use awsApiJs (jsapi.js) for protected actions like sign up, checkout, or form submissions that require CAPTCHA-level validation.
Step-by-step Guide
- Open the target page in Chrome with DevTools (F12) → Network tab
- Filter by
awswafto find requests to*.awswaf.comdomains - Identify the script URLs:
| What you see | Domain pattern | Parameter to use |
|---|---|---|
challenge.js | *.token.awswaf.com or *.sdk.awswaf.com | awsChallengeJS |
jsapi.js | *.captcha.awswaf.com or *.captcha-sdk.awswaf.com | awsApiJs |
- Copy the full URL and use it in your task payload along with
websiteURL
Which parameter should I use?
| Your goal | Parameter | Why |
|---|---|---|
| Access a protected page | awsChallengeJS | Page loads only need a PoW (Proof of Work) token |
| Sign up / Create account | awsApiJs | Sign up endpoints typically require a CAPTCHA-validated token |
| Checkout / Purchase | awsApiJs | Payment flows usually require CAPTCHA-level validation |
| Login | Either works | Try awsChallengeJS first - use awsApiJs if you get a 405 response |
| Not sure | awsApiJs | CAPTCHA tokens work everywhere, PoW tokens may be rejected on protected actions |
Tip
If both URLs are available on the page, you can provide both awsChallengeJS and awsApiJs in the same request. Our system will use the optimal combination.
How to Identify AWS WAF
Signs that a website uses AWS WAF:
| Indicator | Where to Look |
|---|---|
| Cookie name | aws-waf-token in browser cookies |
| Network requests | Requests to *.token.awswaf.com, *.captcha.awswaf.com, *.sdk.awswaf.com, or *.captcha-sdk.awswaf.com |
| Scripts | challenge.js or jsapi.js from awswaf.com |
| Challenge page | Page asking to verify with AWS branding |
DevTools Quick Check:
Network tab → Filter: "awswaf" → Look for challenge.js or jsapi.jsCode Examples
import requests
import time
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.capbypass.pro"
def solve_aws_waf(website_url, challenge_js=None, api_js=None):
# Build task
task = {
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": website_url
}
if challenge_js:
task["awsChallengeJS"] = challenge_js
if api_js:
task["awsApiJs"] = api_js
# Create task
response = requests.post(f"{BASE_URL}/createTask", json={
"clientKey": API_KEY,
"task": task
})
task_id = response.json()["taskId"]
# Poll for result
while True:
result = requests.post(f"{BASE_URL}/getTaskResult", json={
"clientKey": API_KEY,
"taskId": task_id
}).json()
if result["status"] == "ready":
return result["solution"]["cookie"]
if result.get("errorId"):
raise Exception(result.get("errorDescription"))
time.sleep(2)
# Usage - Situation 1 (auto-detect)
cookie = solve_aws_waf("https://example.com")
# Usage - Situation 3-1 (challenge.js)
cookie = solve_aws_waf(
"https://example.com",
challenge_js="https://xxx.token.awswaf.com/xxx/challenge.js"
)
# Usage - Situation 3-2 (jsapi.js)
cookie = solve_aws_waf(
"https://example.com",
api_js="https://xxx.captcha.awswaf.com/xxx/jsapi.js"
)const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.capbypass.pro';
async function solveAwsWaf({ websiteURL, awsChallengeJS, awsApiJs }) {
// Build task
const task = {
type: 'AntiAwsWafTaskProxyLess',
websiteURL
};
if (awsChallengeJS) task.awsChallengeJS = awsChallengeJS;
if (awsApiJs) task.awsApiJs = awsApiJs;
// Create task
const createRes = await fetch(`${BASE_URL}/createTask`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ clientKey: API_KEY, task })
});
const { taskId } = await createRes.json();
// Poll for result
while (true) {
const resultRes = await fetch(`${BASE_URL}/getTaskResult`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ clientKey: API_KEY, taskId })
});
const result = await resultRes.json();
if (result.status === 'ready') {
return result.solution.cookie;
}
if (result.errorId) {
throw new Error(result.errorDescription);
}
await new Promise(r => setTimeout(r, 2000));
}
}Typical Solve Time
| Flow Type | Average | Maximum |
|---|---|---|
| PoW (challenge.js) | 5-15 seconds | 60 seconds |
| CAPTCHA (jsapi.js) | 10-30 seconds | 120 seconds |
Error Codes
| Error Code | Description |
|---|---|
ERROR_KEY_DOES_NOT_EXIST | Invalid API key |
ERROR_ZERO_BALANCE | Insufficient balance |
ERROR_CAPTCHA_UNSOLVABLE | Challenge could not be solved |
ERROR_TASK_NOT_FOUND | Task ID not found |
ERROR_INVALID_TASK_DATA | Missing or invalid parameters |
ERROR_PROXY_NOT_DEFINED | Proxy required for a non-ProxyLess task type — use the ProxyLess variant or supply task.proxy |
ERROR_PROXY_CONNECTION_FAILED | Could not connect through your proxy (refused, unreachable, or bad credentials) - check the proxy is alive and reachable |
ERROR_PROXY_BANNED | The target blocked your proxy IP (datacenter or flagged) - use a residential or mobile proxy |
ERROR_INVALID_DEVELOPER_KEY | The provided developerKey is invalid or disabled |
ERROR_WRONG_TASK_TYPE | Wrong task type for this site (e.g., standard vs enterprise) |
ERROR_TIMEOUT | Task exceeded timeout |
ERROR_TASK_QUEUE_FULL | Server is at capacity — retry in a few seconds |
ERROR_TASK_TYPE_COMING_SOON | Task type is not yet available |
ERROR_TASK_TYPE_INACTIVE | Task type is currently disabled |
ERROR_WORKER_CRASHED | Solver process exited mid-solve — balance refunded, safe to retry |
ERROR_INTERNAL | Internal server error |