AWS WAF CAPTCHA Solver API (2026 Guide)

Solve AWS WAF CAPTCHA automatically with an API. Python and Node.js examples for bypassing AWS WAF bot protection in automation workflows.

March 17, 2026 · 5 min read

AWS WAF CAPTCHA is Amazon's bot protection layer, deployed in front of APIs, web apps, and ALBs running on AWS infrastructure. It uses an audio/visual CAPTCHA challenge with token-based verification. If you're building automation against AWS-hosted services, this guide shows you how to handle it.

How AWS WAF CAPTCHA works

AWS WAF CAPTCHA operates differently from reCAPTCHA or hCaptcha:

The challenge itself is a puzzle or image CAPTCHA served by captcha.amazonaws.com.

Solving AWS WAF CAPTCHA with Ocilar

cURL

curl -X POST https://api.ocilar.com/api/v1/solve/aws-waf \
  -H "X-API-Key: sk-your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "page_url": "https://target-site.com/protected-page",
    "context": "aws-waf-captcha"
  }'

# Response
{
  "token": "KQoAns...base64...",
  "cookie": "aws-waf-token=KQoAns...",
  "latency_ms": 4200,
  "credits_used": 1
}

Python — automated request flow

import requests
from ocilar import OcilarClient

client = OcilarClient(api_key="sk-your_key")

def fetch_with_waf_bypass(url: str) -> requests.Response:
    """
    Fetch a URL protected by AWS WAF CAPTCHA.
    Automatically solves the CAPTCHA and retries with the token.
    """
    session = requests.Session()

    # First attempt — may be blocked by WAF
    resp = session.get(url)

    # Check if WAF redirected us to a CAPTCHA challenge
    if "captcha.amazonaws.com" in resp.url or resp.status_code == 405:
        print("AWS WAF CAPTCHA detected, solving...")

        result = client.solve_aws_waf(page_url=url)

        # Set the WAF token cookie
        session.cookies.set(
            "aws-waf-token",
            result.token,
            domain=url.split("/")[2]
        )

        # Retry the original request
        resp = session.get(url)
        print(f"Status after solve: {resp.status_code}")

    return resp

response = fetch_with_waf_bypass("https://target-site.com/api/data")
print(response.json())

Python — Playwright with AWS WAF

import asyncio
from playwright.async_api import async_playwright
from ocilar import OcilarClient

client = OcilarClient(api_key="sk-your_key")

async def browse_waf_protected():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        context = await browser.new_context()
        page = await context.new_page()

        # Attempt to navigate
        response = await page.goto("https://target-site.com/protected")

        # Detect WAF challenge
        current_url = page.url
        if "captcha.amazonaws.com" in current_url or "waf-challenge" in current_url:
            print("WAF challenge detected, solving...")

            result = client.solve_aws_waf(page_url="https://target-site.com/protected")

            # Inject the token as a cookie
            await context.add_cookies([{
                "name": "aws-waf-token",
                "value": result.token,
                "domain": "target-site.com",
                "path": "/"
            }])

            # Reload the original page
            await page.goto("https://target-site.com/protected")

        content = await page.content()
        print("Page loaded, length:", len(content))

        await browser.close()

asyncio.run(browse_waf_protected())

Node.js

import { OcilarClient } from '@ocilar/sdk'
import axios from 'axios'

const client = new OcilarClient({ apiKey: 'sk-your_key' })

async function fetchWithWafBypass(url) {
  const instance = axios.create()

  try {
    return await instance.get(url)
  } catch (err) {
    if (err.response?.status === 405 || err.message.includes('captcha')) {
      console.log('WAF detected, solving...')

      const { token } = await client.solveAwsWaf({ pageUrl: url })

      // Retry with token header
      return instance.get(url, {
        headers: { 'x-aws-waf-token': token },
        withCredentials: true
      })
    }
    throw err
  }
}

const response = await fetchWithWafBypass('https://target-site.com/api/data')
console.log(response.data)

Token caching — avoid solving on every request

AWS WAF tokens are valid for the configured TTL (often 5–60 minutes). Cache and reuse them:

import time
from ocilar import OcilarClient

client = OcilarClient(api_key="sk-your_key")

_token_cache = {}  # domain -> (token, expires_at)

def get_waf_token(page_url: str, ttl_seconds: int = 300) -> str:
    domain = page_url.split("/")[2]
    now = time.time()

    if domain in _token_cache:
        token, expires_at = _token_cache[domain]
        if now < expires_at - 30:  # 30s buffer
            return token

    result = client.solve_aws_waf(page_url=page_url)
    _token_cache[domain] = (result.token, now + ttl_seconds)
    return result.token

Common use cases

Price monitoring & e-commerce data

Many retail and marketplace sites use AWS WAF to block scrapers. Token caching means you solve once and make hundreds of requests before needing to solve again.

API testing against WAF-protected staging environments

Internal tools and CI pipelines testing against AWS-hosted staging environments can hit WAF challenges. Automate the solve step so tests don't block on manual CAPTCHA.

Compliance and audit crawlers

Security scanners and compliance tools (accessibility audits, broken link checkers) that crawl AWS-hosted sites need to handle WAF challenges transparently.

Pricing

AWS WAF CAPTCHA solving costs $2.00 per 1,000 solves. Volume discounts available.

ServiceAWS WAF supportPrice / 1K
2CaptchaLimited$2.99
CapSolverYes$2.80
Anti-CaptchaNo
OcilarYes$2.00

FAQ

How is AWS WAF different from Cloudflare Turnstile?

Both protect web apps but work differently at the infrastructure level. AWS WAF is deployed on AWS ALB/CloudFront; Cloudflare Turnstile runs on Cloudflare's network. Each requires a different solver. Ocilar supports both — see the Turnstile guide.

What if the WAF uses a JS challenge instead of a visual CAPTCHA?

AWS WAF also issues silent JS challenges (no visual CAPTCHA). These are handled differently — the browser must execute challenge JS and return a token. Use the Playwright approach above which runs real browser JS.

Can I solve AWS WAF in headless mode?

Yes. The Ocilar solver handles the challenge server-side — your automation code just injects the resulting token. No headful browser required for the solve step itself.

What's the token TTL?

Token TTL is set by the site's WAF configuration. Common values: 300s (5 min), 900s (15 min), 3600s (1 hour). Check response headers for x-amzn-waf-action to detect WAF behavior.

Try Ocilar free

1,000 free solves. No credit card required.

Get API Key