How to Solve AWS WAF in n8n with CapSolver

Lucas Mitchell
Automation Engineer
13-Mar-2026

AWS WAF (Web Application Firewall) is Amazon's enterprise-grade bot protection system used by some of the largest websites on the internet. Unlike traditional CAPTCHAs that show image puzzles or checkboxes, AWS WAF uses invisible challenges and token-based verification — making it particularly challenging for automation tools to handle.
What if you could solve AWS WAF challenges automatically inside your n8n workflows — whether you're building a reusable solver API, scraping a captcha-protected site, or automating a login form — all without writing a single line of traditional code?
In this guide, you'll learn how to combine n8n (a visual workflow automation tool) with CapSolver (an AI-powered captcha solving service) to solve AWS WAF challenges on demand — either as a standalone API endpoint or as a step inside any automation workflow.
What you'll build:
Solver API — a reusable endpoint your other tools can call:
- An AWS WAF solver API
Direct-use workflows — CapSolver embedded as a step inside larger automations:
- A price & product scraper that solves AWS WAF, fetches protected pages, and alerts on price changes
- An account login automation that solves AWS WAF before submitting credentials
What is AWS WAF?
AWS WAF (Web Application Firewall) is Amazon Web Services' bot mitigation and web security service. It protects websites from common web exploits, bot traffic, and automated abuse. Many high-traffic sites — especially e-commerce platforms, financial services, and enterprise applications — use AWS WAF to gate access behind invisible CAPTCHA challenges.
How AWS WAF differs from reCAPTCHA and Turnstile:
- No site key required — Unlike reCAPTCHA or Turnstile, AWS WAF does not expose a public site key. You only need the
websiteURLto start solving. - Cookie-based authentication — Instead of returning a token you submit in a form field, AWS WAF returns an
aws-waf-tokencookie that must be sent with subsequent requests via theCookieHTTP header. - Multiple optional parameters — AWS WAF may expose
awsKey,awsIv,awsContext,awsChallengeJS, and other parameters depending on the site's configuration. These are optional and only needed for specific implementations. - Invisible challenge — AWS WAF challenges typically run entirely in the background using JavaScript, with no visible widget for the user to interact with.

Not the same as CloudFront. AWS WAF is the firewall layer that sits in front of web applications. CloudFront is Amazon's CDN. A site can use CloudFront without AWS WAF, or AWS WAF without CloudFront — they are separate services, though commonly used together.
Prerequisites
Before getting started, make sure you have the following:
- An n8n instance — Either self-hosted or n8n Cloud
- A CapSolver account — Sign up here and get your API key
- The CapSolver n8n node — Already available as an official node in n8n (no installation needed)
Important: Make sure you have sufficient balance in your CapSolver account. AWS WAF solving tasks consume credits based on usage.
Setting Up CapSolver in n8n
CapSolver is available as an official integration in n8n — no community node installation required. You can find it directly in the node panel when building your workflows.
Since it's an official integration, you need to create a credential in n8n so that the CapSolver node can authenticate with your account.
Step 1: Open the Credentials Page
Go to your n8n instance and navigate to Settings -> Credentials. You'll see all your configured credentials here.

Step 2: Create the CapSolver Credential
- Click Create credential (top right)
- Search for "CapSolver" and select CapSolver API
- Enter your API Key — copy it directly from the CapSolver Dashboard
- Leave Allowed HTTP Request Domains set to
All(default) - Click Save
n8n will automatically test the connection. You should see a green "Connection tested successfully" banner confirming your API key is valid.

Important: Every CapSolver node in your workflows will reference this credential. You only need to create it once — all your solver workflows will share the same credential.
Now you're ready to build your AWS WAF solver workflow!
How to Identify AWS WAF Parameters
Before you can solve an AWS WAF challenge, you need to confirm the target site is using AWS WAF and gather any optional parameters. The easiest way is using the CapSolver Browser Extension combined with manual inspection.
Step 1: Look for AWS WAF Indicators
Navigate to your target website and open DevTools (F12). Look for these telltale signs:
- Cookies — Check for an
aws-waf-tokencookie in the Application tab - Network requests — Look for requests to
captcha.awswaf.comor URLs containingchallenge.js - Response headers — AWS WAF often returns
x-amzn-waf-*headers
Step 2: Gather Optional Parameters (If Needed)
Most AWS WAF solves only require the websiteURL. However, some sites expose additional parameters that can improve solve accuracy:
| Parameter | Where to Find | Description |
|---|---|---|
awsKey |
Page source / JS variables | The key value returned by the captcha page |
awsIv |
Page source / JS variables | The iv value returned by the captcha page |
awsContext |
Page source / JS variables | The context value returned by the captcha page |
awsChallengeJS |
Network tab | The challenge.js URL (e.g., https://captcha.awswaf.com/.../challenge.js) |
awsApiJs |
Network tab | The jsapi.js URL |
awsProblemUrl |
Network tab | The problem endpoint URL |
awsApiKey |
Network tab | The api_key value from the problem endpoint |
awsExistingToken |
Cookies | A previous aws-waf-token if refreshing |
Tip: For most sites, you only need
websiteURL. Start with just that parameter and add optional ones only if the token isn't being accepted.
For a detailed guide on identifying captcha parameters, check out the official CapSolver documentation.
Workflow: AWS WAF Solver API
This workflow creates a POST API endpoint that accepts AWS WAF parameters and returns a solved cookie token.

How It Works
The workflow consists of four nodes:
- Webhook — Receives incoming POST requests with AWS WAF parameters
- AWS WAF — Sends the challenge to CapSolver and waits for a solution
- CapSolver Error? — IF node that branches on whether solving failed (
$json.erroris not empty) - Respond to Webhook — Returns the solution on success, or
{"error": "..."}on failure
Node Configuration
1. Webhook Node
| Setting | Value |
|---|---|
| HTTP Method | POST |
| Path | solver-aws-waf |
| Respond | Response Node |
This creates an endpoint at: https://your-n8n-instance.com/webhook/solver-aws-waf
2. CapSolver AWS WAF Node
| Parameter | Value | Description |
|---|---|---|
| Operation | AWS WAF |
Must be set to AWS WAF |
| Type | AntiAwsWafTaskProxyLess |
No proxy needed (default). Use AntiAwsWafTask with a proxy for stricter sites |
| Website URL | {{ $json.body.websiteURL }} |
The URL of the page with the AWS WAF challenge |
| awsKey | (Optional) | The key value returned by the captcha page |
| awsIv | (Optional) | The iv value returned by the captcha page |
| awsContext | (Optional) | The context value returned by the captcha page |
| awsChallengeJS | (Optional) | The challenge.js link |
| awsApiJs | (Optional) | The jsapi.js link |
Key difference from Turnstile/reCAPTCHA: AWS WAF does not require a
websiteKey. OnlywebsiteURLis mandatory. Also select your CapSolver credentials in this node.
3. CapSolver Error? Node (IF)
| Setting | Value |
|---|---|
| Condition | ={{ $json.error }} is not empty |
| True branch | Routes to the Error Respond to Webhook node |
| False branch | Routes to the Success Respond to Webhook node |
This makes the error path explicit on the canvas. The CapSolver node continues on error (onError: continueRegularOutput), so failures arrive here as { "error": "..." } rather than crashing the workflow.
4. Respond to Webhook Nodes
Success branch (false output of CapSolver Error?):
| Setting | Value |
|---|---|
| Respond With | JSON |
| Response Body | ={{ JSON.stringify($json.data) }} |
Error branch (true output of CapSolver Error?):
| Setting | Value |
|---|---|
| Respond With | JSON |
| Response Body | ={{ JSON.stringify({ error: $json.error }) }} |
Error messages follow one of two formats depending on where the failure occurred:
| Failure point | Format |
|---|---|
| Task creation rejected (wrong key, no balance, invalid data, etc.) | {"error": "Failed to create task: Request failed with status code 400"} |
| Task created but captcha could not be solved | {"error": "Solve failed: <reason>"} |
| Solve timed out after 120 s | {"error": "Get task result timeout: unable to solve within 120000 seconds"} |
Note: Task creation failures (wrong API key, zero balance, invalid task data) all surface as the same HTTP 400 message — the n8n node catches the HTTP exception before reading CapSolver's error body.
Common error examples:
json
{"error": "Failed to create task: Request failed with status code 400"}
{"error": "Solve failed: Invalid parameters"}
{"error": "Get task result timeout: unable to solve within 120000 seconds"}
Test It
Send a POST request to your webhook endpoint:
bash
curl -X POST https://your-n8n-instance.com/webhook/solver-aws-waf \
-H "Content-Type: application/json" \
-d '{
"websiteURL": "https://example.com/protected-page"
}'
You can also include optional parameters:
bash
curl -X POST https://your-n8n-instance.com/webhook/solver-aws-waf \
-H "Content-Type: application/json" \
-d '{
"websiteURL": "https://example.com/protected-page",
"awsKey": "AQIDAHjc...",
"awsIv": "CgAHAQABAA...",
"awsContext": "gxPZ0w9O..."
}'
Expected Response:
json
{
"taskId": "abc123...",
"solution": {
"cookie": "aws-waf-token=76b8ee9e-fa6a-4c36-b8e9-0c1d97EXAMPLE..."
},
"status": "ready"
}
Important: The solution returns a
cookiefield (nottokenorgRecaptchaResponselike other captcha types). The value is a full cookie string likeaws-waf-token=LONG_VALUEthat you send via theCookieHTTP header.
Import This Workflow
Copy the JSON below and import it into n8n via Menu -> Import from JSON:
Click to expand workflow JSON
json
{
"name": "AWS WAF — Solver API",
"nodes": [
{
"parameters": {
"content": "## AWS WAF — Solver API\n\n**Who it's for:** Developers who need to solve AWS WAF challenges via a simple POST endpoint.\n\n**What it does:** Exposes a webhook that accepts captcha parameters, solves the challenge with CapSolver, and returns the token or error as JSON.\n\n**How it works:**\n1. Webhook receives POST with target URL, site key, and optional params\n2. CapSolver node solves the AWS WAF challenge\n3. IF node checks for errors → returns success token or error JSON\n\n**Setup:**\n1. Add your CapSolver API key under **Settings → Credentials → CapSolver API**\n2. Activate the workflow\n3. POST to the webhook URL with your captcha parameters",
"height": 494,
"width": 460,
"color": 1
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-712,
-400
],
"id": "sticky-blog-main-1773678228095-1",
"name": "Sticky Note"
},
{
"parameters": {
"httpMethod": "POST",
"path": "solver-aws-waf",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-192,
0
],
"id": "aw111111-1111-1111-1111-aw1111111101",
"name": "Receive Solver Request",
"webhookId": "aw111111-aaaa-bbbb-cccc-aw1111111101"
},
{
"parameters": {
"operation": "AWS WAF",
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "={{ $json.body.websiteURL }}",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
112,
0
],
"id": "aw111111-1111-1111-1111-aw1111111102",
"name": "AWS WAF",
"onError": "continueRegularOutput",
"credentials": {
"capSolverApi": {
"id": "YOUR_CREDENTIAL_ID",
"name": "CapSolver account"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose",
"version": 2
},
"conditions": [
{
"id": "capsolver-err-001",
"leftValue": "={{ $json.error }}",
"operator": {
"type": "string",
"operation": "isNotEmpty",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
400,
0
],
"id": "aw111111-1111-1111-1111-aw1111111103",
"name": "CapSolver Error?"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ error: $json.error }) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
700,
-100
],
"id": "aw111111-1111-1111-1111-aw1111111104",
"name": "Respond to Webhook (Error)"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json.data) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
700,
100
],
"id": "aw111111-1111-1111-1111-aw1111111105",
"name": "Respond to Webhook"
}
],
"connections": {
"Receive Solver Request": {
"main": [
[
{
"node": "AWS WAF",
"type": "main",
"index": 0
}
]
]
},
"AWS WAF": {
"main": [
[
{
"node": "CapSolver Error?",
"type": "main",
"index": 0
}
]
]
},
"CapSolver Error?": {
"main": [
[
{
"node": "Respond to Webhook (Error)",
"type": "main",
"index": 0
}
],
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
}
}
API Parameter Reference
The AWS WAF solver API endpoint accepts the following parameters:
| Parameter | Required | Description |
|---|---|---|
websiteURL |
Yes | The URL of the page with the AWS WAF challenge |
awsKey |
No | The key value returned by the captcha page |
awsIv |
No | The iv value returned by the captcha page |
awsContext |
No | The context value returned by the captcha page |
awsChallengeJS |
No | The challenge.js link from the captcha page |
awsApiJs |
No | The jsapi.js link from the captcha page |
awsProblemUrl |
No | The problem endpoint URL |
awsApiKey |
No | The api_key value of the problem endpoint |
awsExistingToken |
No | A previous aws-waf-token used for last verification |
Tip: You can identify the
websiteURLby inspecting the page URL. Use DevTools to check foraws-waf-tokencookies and network requests tocaptcha.awswaf.com.
Compared to reCAPTCHA and Turnstile, AWS WAF is simpler in one way — you only need one required parameter (websiteURL), with no site key needed. However, it has more optional parameters for fine-tuning.
Workflow: Submitting an AWS WAF Token to a Website
The API workflow above shows how to get a solved AWS WAF cookie. But what do you actually do with it?
In real-world automation, solving the challenge is only half the job. You need to submit the cookie to the target website — exactly as a browser would — to unlock the data or action behind the AWS WAF protection.
Here's the general pattern:
- Solve the challenge -> Get the cookie from CapSolver (
solution.cookie) - Submit the cookie -> Send it to the target website via the
CookieHTTP header - Verify the response -> Check if the website accepted the cookie
- Process the result -> Extract the data you need
Example: Solving & Submitting AWS WAF
Example: https://example.com/ — An AWS WAF-protected website
Workflow Flow
Manual Trigger -> CapSolver AWS WAF -> HTTP GET Request (with Cookie header) -> IF (check success) -> Valid / Invalid
How It Works
- Manual Trigger — Starts the workflow manually (click "Execute workflow"). You can replace this with any trigger — Webhook, Schedule, App Event, etc.
- CapSolver AWS WAF — Solves the AWS WAF challenge:
- Operation:
AWS WAF - Website URL:
https://example.com/protected-page - Type:
AntiAwsWafTaskProxyLess
- Operation:
- HTTP Request — Sends a request to the protected page with the solved cookie:
- The cookie is sent in the
Cookieheader:={{ $json.data.solution.cookie }} - This is what a browser does — it stores the
aws-waf-tokencookie and sends it with every subsequent request
- The cookie is sent in the
- IF Node — Checks if the response indicates success (e.g., status code < 400, expected content present)
- Valid / Invalid — Routes to appropriate handling. On the Valid branch, use the HTML node to extract specific elements (e.g., product data, account info)
Key difference from Turnstile/reCAPTCHA: AWS WAF tokens are submitted as cookies, not form fields. The solved value goes in the
CookieHTTP header, not in ag-recaptcha-responseorcf-turnstile-responsefield. This means you can use GET requests (not just POST) to access protected pages.
Click to expand workflow JSON
json
{
"name": "AWS WAF Submit Token Example",
"nodes": [
{
"parameters": {
"content": "## AWS WAF — Solve & Submit Token\n\n**Who it's for:** Anyone automating form submissions on AWS WAF-protected pages.\n\n**What it does:** Solves the AWS WAF challenge, submits the token to the target site, and checks whether it was accepted.\n\n**How it works:**\n1. Solve AWS WAF via CapSolver\n2. POST the solved token to the target site\n3. Check response for success marker → route to Valid or Invalid\n\n**Setup:**\n1. Add your CapSolver API key under **Settings → Credentials**\n2. Replace target URL, site key, and form fields\n3. Inspect your target site's form (DevTools → Network) to match the submission format",
"height": 494,
"width": 460,
"color": 1
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-728,
-400
],
"id": "sticky-blog-main-1773678228095-1",
"name": "Sticky Note"
},
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-208,
0
],
"id": "aw222222-2222-2222-2222-aw2222222201",
"name": "When clicking 'Execute workflow'"
},
{
"parameters": {
"operation": "AWS WAF",
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "https://YOUR-TARGET-SITE.com",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
96,
0
],
"id": "aw222222-2222-2222-2222-aw2222222202",
"name": "AWS WAF",
"credentials": {
"capSolverApi": {
"id": "YOUR_CREDENTIAL_ID",
"name": "CapSolver account"
}
}
},
{
"parameters": {
"url": "https://YOUR-TARGET-SITE.com",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "user-agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
},
{
"name": "Cookie",
"value": "={{ $json.data.solution.cookie }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": true,
"neverError": true
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
400,
0
],
"id": "aw222222-2222-2222-2222-aw2222222203",
"name": "Submit Token to Target Site"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "aws-if-001",
"leftValue": "={{ $json.statusCode }}",
"rightValue": 400,
"operator": {
"type": "number",
"operation": "lt"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
700,
0
],
"id": "aw222222-2222-2222-2222-aw2222222204",
"name": "Request Successful?"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "valid-001",
"name": "status",
"value": "valid",
"type": "string"
},
{
"id": "valid-002",
"name": "statusCode",
"value": "={{ $json.statusCode }}",
"type": "number"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1000,
-100
],
"id": "aw222222-2222-2222-2222-aw2222222205",
"name": "Valid"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "invalid-001",
"name": "status",
"value": "invalid",
"type": "string"
},
{
"id": "invalid-002",
"name": "statusCode",
"value": "={{ $json.statusCode }}",
"type": "number"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1000,
100
],
"id": "aw222222-2222-2222-2222-aw2222222206",
"name": "Invalid"
}
],
"connections": {
"When clicking 'Execute workflow'": {
"main": [
[
{
"node": "AWS WAF",
"type": "main",
"index": 0
}
]
]
},
"AWS WAF": {
"main": [
[
{
"node": "Submit Token to Target Site",
"type": "main",
"index": 0
}
]
]
},
"Submit Token to Target Site": {
"main": [
[
{
"node": "Request Successful?",
"type": "main",
"index": 0
}
]
]
},
"Request Successful?": {
"main": [
[
{
"node": "Valid",
"type": "main",
"index": 0
}
],
[
{
"node": "Invalid",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
}
}
Workflow: Use-Case Examples
The solver API and submission example above show the core pattern: solve the AWS WAF challenge, submit the cookie, process the result. The following workflows extend this pattern to production-ready use cases — each with dual triggers (schedule + webhook), persistent state tracking, and structured output.
| Workflow | Purpose |
|---|---|
AWS WAF Scraping — Price & Product Details — CapSolver + Schedule + Webhook |
Scrapes price and product name every 6 hours, compares against previous values stored in staticData, alerts on changes |
AWS WAF Account Login — CapSolver + Schedule + Webhook |
Logs into your own account on an AWS WAF-protected site by solving first, then POSTing credentials with the cookie |
Example 1: Scraping
This workflow scrapes a product page every 6 hours (schedule) or on demand (webhook), extracts the price using the HTML node, and compares it against the previously stored value.
Schedule path:
Every 6 Hours -> Solve AWS WAF -> Fetch Product Page -> Extract Data
-> Compare Data -> Data Changed? -> Build Alert / No Change
Key behaviors:
- The cookie is sent as a
Cookieheader (this is the correct way to submit AWS WAF tokens — not as a form field) - The HTML node extracts price and product name via CSS selectors (
.product-price,h1) $workflow.staticData.lastPricepersists the previous price across executions- Price comparison detects both drops (severity:
deal) and increases (severity:info)
Click to expand full workflow JSON (17 nodes)
json
{
"name": "AWS WAF Scraping — Price & Product Details — CapSolver + Schedule + Webhook",
"nodes": [
{
"parameters": {
"content": "## AWS WAF Scraping — Price & Product Monitor\n\n**Who it's for:** Teams monitoring prices or product data on AWS WAF-protected sites.\n\n**What it does:** Solves AWS WAF, fetches a product page, extracts price & name via CSS selectors, compares against stored values, and alerts on changes.\n\n**How it works:**\n1. Schedule (every 6h) or Webhook triggers the flow\n2. CapSolver solves the AWS WAF challenge\n3. HTTP Request fetches the product page with the solved token\n4. HTML node extracts price and product name\n5. Code node compares current vs. stored price → alerts on change\n\n**Setup:**\n1. Add your CapSolver API key under **Settings → Credentials**\n2. Replace placeholder URLs and site keys\n3. Update CSS selectors in Extract Data to match your target page\n4. Connect the Build Alert output to your notification channel",
"height": 560,
"width": 460,
"color": 1
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-920,
-380
],
"id": "sticky-blog-main-1773678228094-1",
"name": "Sticky Note"
},
{
"parameters": {
"content": "### Schedule Path\nRuns automatically every 6 hours.\nResults stored in workflow static data for cross-execution comparison.",
"height": 480,
"width": 1900,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-440,
-280
],
"id": "sticky-blog-section-1773678228094-2",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "### Webhook Path\nOn-demand trigger — same logic, returns result as JSON response.",
"height": 480,
"width": 1900,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-440,
140
],
"id": "sticky-blog-section-1773678228094-3",
"name": "Sticky Note2"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-400,
0
],
"id": "aw333333-3333-3333-3333-aw3333333301",
"name": "Every 6 Hours"
},
{
"parameters": {
"operation": "AWS WAF",
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "https://YOUR-TARGET-SITE.com/product-page",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-96,
0
],
"id": "aw333333-3333-3333-3333-aw3333333302",
"name": "Solve AWS WAF",
"credentials": {
"capSolverApi": {
"id": "YOUR_CREDENTIAL_ID",
"name": "CapSolver account"
}
}
},
{
"parameters": {
"url": "https://YOUR-TARGET-SITE.com/product-page",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "user-agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
},
{
"name": "Cookie",
"value": "={{ $json.data.solution.cookie }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": false
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
208,
0
],
"id": "aw333333-3333-3333-3333-aw3333333303",
"name": "Fetch Product Page"
},
{
"parameters": {
"operation": "extractHtmlContent",
"sourceData": "json",
"dataPropertyName": "data",
"extractionValues": {
"values": [
{
"key": "price",
"cssSelector": ".product-price, [data-price], .price",
"returnValue": "text",
"returnArray": false
},
{
"key": "productName",
"cssSelector": "h1, .product-title",
"returnValue": "text",
"returnArray": false
}
]
},
"options": {}
},
"type": "n8n-nodes-base.html",
"typeVersion": 1.2,
"position": [
512,
0
],
"id": "aw333333-3333-3333-3333-aw3333333304",
"name": "Extract Data"
},
{
"parameters": {
"jsCode": "// Get current and previous price from workflow static data\nconst staticData = $workflow.staticData;\nconst currentPrice = $input.first().json.price;\nconst previousPrice = staticData.lastPrice;\nconst productName = $input.first().json.productName || 'Product';\n\n// Parse numeric values for comparison\nconst parsePrice = (str) => {\n if (!str) return null;\n const match = str.match(/[\\d,]+\\.?\\d*/);\n return match ? parseFloat(match[0].replace(',', '')) : null;\n};\n\nconst currentNum = parsePrice(currentPrice);\nconst previousNum = parsePrice(previousPrice);\n\n// Update stored price\nstaticData.lastPrice = currentPrice;\nstaticData.lastChecked = new Date().toISOString();\n\nconst changed = previousNum !== null && currentNum !== null && currentNum !== previousNum;\nconst direction = changed ? (currentNum < previousNum ? 'dropped' : 'increased') : 'unchanged';\nconst diff = changed ? Math.abs(currentNum - previousNum).toFixed(2) : '0';\n\nreturn [{\n json: {\n productName,\n currentPrice,\n previousPrice: previousPrice || 'first check',\n changed,\n direction,\n diff: changed ? `$${diff}` : null,\n checkedAt: new Date().toISOString()\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
800,
0
],
"id": "aw333333-3333-3333-3333-aw3333333305",
"name": "Compare Data"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "price-if-001",
"leftValue": "={{ $json.changed }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1104,
0
],
"id": "aw333333-3333-3333-3333-aw3333333306",
"name": "Data Changed?"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "alert-001",
"name": "alert",
"value": "=Price {{ $json.direction }} for {{ $json.productName }}: {{ $json.previousPrice }} → {{ $json.currentPrice }} ({{ $json.direction === 'dropped' ? '-' : '+' }}{{ $json.diff }})",
"type": "string"
},
{
"id": "alert-002",
"name": "severity",
"value": "={{ $json.direction === 'dropped' ? 'deal' : 'info' }}",
"type": "string"
},
{
"id": "alert-003",
"name": "checkedAt",
"value": "={{ $json.checkedAt }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1408,
-80
],
"id": "aw333333-3333-3333-3333-aw3333333307",
"name": "Build Alert"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "nc-001",
"name": "status",
"value": "no_change",
"type": "string"
},
{
"id": "nc-002",
"name": "currentPrice",
"value": "={{ $json.currentPrice }}",
"type": "string"
},
{
"id": "nc-003",
"name": "checkedAt",
"value": "={{ $json.checkedAt }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1408,
128
],
"id": "aw333333-3333-3333-3333-aw3333333308",
"name": "No Change"
},
{
"parameters": {
"httpMethod": "POST",
"path": "price-monitor-aws-waf",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-400,
420
],
"id": "aw333333-3333-3333-3333-aw3333333309",
"name": "Webhook Trigger",
"webhookId": "aw333333-aaaa-bbbb-cccc-aw3333333309",
"onError": "continueRegularOutput"
},
{
"parameters": {
"operation": "AWS WAF",
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "https://YOUR-TARGET-SITE.com/product-page",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-96,
420
],
"id": "aw333333-3333-3333-3333-aw3333333310",
"name": "Solve AWS WAF [Webhook]",
"credentials": {
"capSolverApi": {
"id": "YOUR_CREDENTIAL_ID",
"name": "CapSolver account"
}
}
},
{
"parameters": {
"url": "https://YOUR-TARGET-SITE.com/product-page",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "user-agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
},
{
"name": "Cookie",
"value": "={{ $json.data.solution.cookie }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": false
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
208,
420
],
"id": "aw333333-3333-3333-3333-aw3333333311",
"name": "Fetch Product Page [Webhook]"
},
{
"parameters": {
"operation": "extractHtmlContent",
"sourceData": "json",
"dataPropertyName": "data",
"extractionValues": {
"values": [
{
"key": "price",
"cssSelector": ".product-price, [data-price], .price",
"returnValue": "text",
"returnArray": false
},
{
"key": "productName",
"cssSelector": "h1, .product-title",
"returnValue": "text",
"returnArray": false
}
]
},
"options": {}
},
"type": "n8n-nodes-base.html",
"typeVersion": 1.2,
"position": [
512,
420
],
"id": "aw333333-3333-3333-3333-aw3333333312",
"name": "Extract Data [Webhook]"
},
{
"parameters": {
"jsCode": "// Get current and previous price from workflow static data\nconst staticData = $workflow.staticData;\nconst currentPrice = $input.first().json.price;\nconst previousPrice = staticData.lastPrice;\nconst productName = $input.first().json.productName || 'Product';\n\n// Parse numeric values for comparison\nconst parsePrice = (str) => {\n if (!str) return null;\n const match = str.match(/[\\d,]+\\.?\\d*/);\n return match ? parseFloat(match[0].replace(',', '')) : null;\n};\n\nconst currentNum = parsePrice(currentPrice);\nconst previousNum = parsePrice(previousPrice);\n\n// Update stored price\nstaticData.lastPrice = currentPrice;\nstaticData.lastChecked = new Date().toISOString();\n\nconst changed = previousNum !== null && currentNum !== null && currentNum !== previousNum;\nconst direction = changed ? (currentNum < previousNum ? 'dropped' : 'increased') : 'unchanged';\nconst diff = changed ? Math.abs(currentNum - previousNum).toFixed(2) : '0';\n\nreturn [{\n json: {\n productName,\n currentPrice,\n previousPrice: previousPrice || 'first check',\n changed,\n direction,\n diff: changed ? `$${diff}` : null,\n checkedAt: new Date().toISOString()\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
800,
420
],
"id": "aw333333-3333-3333-3333-aw3333333313",
"name": "Compare Data [Webhook]"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "price-if-002",
"leftValue": "={{ $json.changed }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1104,
420
],
"id": "aw333333-3333-3333-3333-aw3333333314",
"name": "Data Changed? [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "alert-004",
"name": "alert",
"value": "=Price {{ $json.direction }} for {{ $json.productName }}: {{ $json.previousPrice }} → {{ $json.currentPrice }} ({{ $json.direction === 'dropped' ? '-' : '+' }}{{ $json.diff }})",
"type": "string"
},
{
"id": "alert-005",
"name": "severity",
"value": "={{ $json.direction === 'dropped' ? 'deal' : 'info' }}",
"type": "string"
},
{
"id": "alert-006",
"name": "checkedAt",
"value": "={{ $json.checkedAt }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1408,
340
],
"id": "aw333333-3333-3333-3333-aw3333333315",
"name": "Build Alert [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "nc-004",
"name": "status",
"value": "no_change",
"type": "string"
},
{
"id": "nc-005",
"name": "currentPrice",
"value": "={{ $json.currentPrice }}",
"type": "string"
},
{
"id": "nc-006",
"name": "checkedAt",
"value": "={{ $json.checkedAt }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1408,
548
],
"id": "aw333333-3333-3333-3333-aw3333333316",
"name": "No Change [Webhook]"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
1712,
420
],
"id": "aw333333-3333-3333-3333-aw3333333317",
"name": "Respond to Webhook"
}
],
"connections": {
"Every 6 Hours": {
"main": [
[
{
"node": "Solve AWS WAF",
"type": "main",
"index": 0
}
]
]
},
"Solve AWS WAF": {
"main": [
[
{
"node": "Fetch Product Page",
"type": "main",
"index": 0
}
]
]
},
"Fetch Product Page": {
"main": [
[
{
"node": "Extract Data",
"type": "main",
"index": 0
}
]
]
},
"Extract Data": {
"main": [
[
{
"node": "Compare Data",
"type": "main",
"index": 0
}
]
]
},
"Compare Data": {
"main": [
[
{
"node": "Data Changed?",
"type": "main",
"index": 0
}
]
]
},
"Data Changed?": {
"main": [
[
{
"node": "Build Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "No Change",
"type": "main",
"index": 0
}
]
]
},
"Webhook Trigger": {
"main": [
[
{
"node": "Solve AWS WAF [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Solve AWS WAF [Webhook]": {
"main": [
[
{
"node": "Fetch Product Page [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Fetch Product Page [Webhook]": {
"main": [
[
{
"node": "Extract Data [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Extract Data [Webhook]": {
"main": [
[
{
"node": "Compare Data [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Compare Data [Webhook]": {
"main": [
[
{
"node": "Data Changed? [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Data Changed? [Webhook]": {
"main": [
[
{
"node": "Build Alert [Webhook]",
"type": "main",
"index": 0
}
],
[
{
"node": "No Change [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Build Alert [Webhook]": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"No Change [Webhook]": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
}
}
Example 2: Account Login
This workflow automates login to an AWS WAF-protected site. A Set Login Config node centralizes all parameters — [Schedule] for the schedule path. Edit the config node to configure your target site.
Schedule path:
Every 24 Hours -> Set Login Config -> Solve Captcha -> Submit Login
-> Login Successful? -> Mark Login Success / Mark Login Failed
Error handling: If CapSolver fails, the execution stops and is marked as failed in n8n. Check Executions to see the error, or configure n8n's Error Workflow to get notified automatically.
Key behaviors:
- Uses
AntiAwsWafTaskProxyLess— no proxy needed for most sites - No
websiteKeyortokenFieldName— AWS WAF only needswebsiteURL, and the token is submitted as aCookieheader (not a form field) - Form fields for username/password are submitted normally via form-urlencoded POST — only the AWS WAF cookie is added as a header
- The Login Successful? check evaluates both
statusCode < 400and the presence of a configurablesuccessMarkerin the response body - Webhook path reads parameters from the request body for on-demand execution
- Webhook path returns the result as JSON via Respond to Webhook
Click to expand full workflow JSON (15 nodes)
json
{
"name": "AWS WAF Account Login — CapSolver + Schedule + Webhook",
"nodes": [
{
"parameters": {
"content": "## AWS WAF Account Login\n\n**Who it's for:** Anyone automating login to a AWS WAF-protected website.\n\n**What it does:** Solves AWS WAF before submitting login credentials, then checks whether login succeeded.\n\n**How it works:**\n1. Schedule (every 24h) or Webhook triggers the flow\n2. Set Login Config centralizes all parameters (URL, keys, credentials, task type)\n3. CapSolver solves the AWS WAF challenge\n4. Submit Login POSTs credentials with the solved token\n5. Login Successful? checks status code and response body\n\n**Setup:**\n1. Add your CapSolver API key under **Settings → Credentials**\n2. Edit **Set Login Config** — replace URL, site key, email, password, and success marker\n3. Edit **Submit Login** to match your target site's form field names\n4. Change task type if needed",
"height": 560,
"width": 460,
"color": 1
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1160,
-380
],
"id": "sticky-blog-main-1773678228094-1",
"name": "Sticky Note"
},
{
"parameters": {
"content": "### Schedule Path\nRuns every 24 hours to keep the session alive or verify access.",
"height": 480,
"width": 2200,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-680,
-280
],
"id": "sticky-blog-section-1773678228094-2",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "### Webhook Path\nOn-demand login trigger — returns result as JSON response.",
"height": 480,
"width": 2200,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-680,
140
],
"id": "sticky-blog-section-1773678228094-3",
"name": "Sticky Note2"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 24
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-640,
0
],
"id": "aw666666-6666-6666-6666-aw6666666601",
"name": "Every 24 Hours"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "login-001",
"name": "websiteURL",
"value": "https://YOUR-LOGIN-PAGE.com",
"type": "string"
},
{
"id": "login-008",
"name": "usernameField",
"value": "email",
"type": "string"
},
{
"id": "login-009",
"name": "passwordField",
"value": "password",
"type": "string"
},
{
"id": "login-010",
"name": "usernameValue",
"value": "[email protected]",
"type": "string"
},
{
"id": "login-011",
"name": "passwordValue",
"value": "YOUR_ACCOUNT_PASSWORD",
"type": "string"
},
{
"id": "login-013",
"name": "successMarker",
"value": "account-dashboard",
"type": "string"
},
{
"id": "login-014",
"name": "userAgent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-336,
0
],
"id": "aw666666-6666-6666-6666-aw6666666602",
"name": "Set Login Config [Schedule]"
},
{
"parameters": {
"operation": "AWS WAF",
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "={{ $json.websiteURL }}"
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-32,
0
],
"id": "aw666666-6666-6666-6666-aw6666666603",
"name": "Solve Captcha [Schedule]",
"credentials": {
"capSolverApi": {
"id": "YOUR_CREDENTIAL_ID",
"name": "CapSolver account"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://YOUR-LOGIN-PAGE.com/login",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "content-type",
"value": "application/x-www-form-urlencoded"
},
{
"name": "user-agent",
"value": "={{ $('Set Login Config [Schedule]').item.json.userAgent }}"
},
{
"name": "Cookie",
"value": "={{ $json.data.solution.cookie }}"
}
]
},
"sendBody": true,
"contentType": "form-urlencoded",
"bodyParameters": {
"parameters": [
{
"name": "={{ $('Set Login Config [Schedule]').item.json.usernameField }}",
"value": "={{ $('Set Login Config [Schedule]').item.json.usernameValue }}"
},
{
"name": "={{ $('Set Login Config [Schedule]').item.json.passwordField }}",
"value": "={{ $('Set Login Config [Schedule]').item.json.passwordValue }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": true,
"neverError": true
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
272,
0
],
"id": "aw666666-6666-6666-6666-aw6666666604",
"name": "Submit Login [Schedule]"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "login-if-001",
"leftValue": "={{ $json.statusCode < 400 && String($json.body || $json.data || '').includes($('Set Login Config [Schedule]').item.json.successMarker) }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
576,
0
],
"id": "aw666666-6666-6666-6666-aw6666666605",
"name": "Login Successful? [Schedule]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "login-015",
"name": "action",
"value": "account_login",
"type": "string"
},
{
"id": "login-016",
"name": "status",
"value": "success",
"type": "string"
},
{
"id": "login-017",
"name": "message",
"value": "Configured account login flow succeeded",
"type": "string"
},
{
"id": "login-018",
"name": "checkedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
880,
-80
],
"id": "aw666666-6666-6666-6666-aw6666666606",
"name": "Mark Login Success [Schedule]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "login-019",
"name": "action",
"value": "account_login",
"type": "string"
},
{
"id": "login-020",
"name": "status",
"value": "failed",
"type": "string"
},
{
"id": "login-021",
"name": "statusCode",
"value": "={{ $json.statusCode }}",
"type": "number"
},
{
"id": "login-022",
"name": "message",
"value": "Login response did not match the configured success marker",
"type": "string"
},
{
"id": "login-023",
"name": "checkedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
880,
120
],
"id": "aw666666-6666-6666-6666-aw6666666607",
"name": "Mark Login Failed [Schedule]"
},
{
"parameters": {
"httpMethod": "POST",
"path": "account-login-aws-waf",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-640,
420
],
"id": "aw666666-6666-6666-6666-aw6666666608",
"name": "Webhook Trigger",
"webhookId": "aw666666-aaaa-bbbb-cccc-aw6666666608",
"onError": "continueRegularOutput"
},
{
"parameters": {
"operation": "AWS WAF",
"type": "AntiAwsWafTaskProxyLess",
"websiteURL": "={{ $json.body.websiteURL }}"
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-32,
420
],
"id": "aw666666-6666-6666-6666-aw6666666610",
"name": "Solve Captcha [Webhook]",
"credentials": {
"capSolverApi": {
"id": "YOUR_CREDENTIAL_ID",
"name": "CapSolver account"
}
}
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Webhook Trigger').item.json.body.loginActionURL }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "content-type",
"value": "application/x-www-form-urlencoded"
},
{
"name": "user-agent",
"value": "={{ $('Webhook Trigger').item.json.body.userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36' }}"
},
{
"name": "Cookie",
"value": "={{ $json.data.solution.cookie }}"
}
]
},
"sendBody": true,
"contentType": "form-urlencoded",
"bodyParameters": {
"parameters": [
{
"name": "={{ $('Webhook Trigger').item.json.body.usernameField || 'email' }}",
"value": "={{ $('Webhook Trigger').item.json.body.usernameValue }}"
},
{
"name": "={{ $('Webhook Trigger').item.json.body.passwordField || 'password' }}",
"value": "={{ $('Webhook Trigger').item.json.body.passwordValue }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": true,
"neverError": true
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
272,
420
],
"id": "aw666666-6666-6666-6666-aw6666666611",
"name": "Submit Login [Webhook]"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "login-if-002",
"leftValue": "={{ $json.statusCode < 400 && String($json.body || $json.data || '').includes($('Webhook Trigger').item.json.body.successMarker) }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
576,
420
],
"id": "aw666666-6666-6666-6666-aw6666666612",
"name": "Login Successful? [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "login-038",
"name": "action",
"value": "account_login",
"type": "string"
},
{
"id": "login-039",
"name": "status",
"value": "success",
"type": "string"
},
{
"id": "login-040",
"name": "message",
"value": "Configured account login flow succeeded",
"type": "string"
},
{
"id": "login-041",
"name": "checkedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
880,
340
],
"id": "aw666666-6666-6666-6666-aw6666666613",
"name": "Mark Login Success [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "login-042",
"name": "action",
"value": "account_login",
"type": "string"
},
{
"id": "login-043",
"name": "status",
"value": "failed",
"type": "string"
},
{
"id": "login-044",
"name": "statusCode",
"value": "={{ $json.statusCode }}",
"type": "number"
},
{
"id": "login-045",
"name": "message",
"value": "Login response did not match the configured success marker",
"type": "string"
},
{
"id": "login-046",
"name": "checkedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
880,
540
],
"id": "aw666666-6666-6666-6666-aw6666666614",
"name": "Mark Login Failed [Webhook]"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
1184,
420
],
"id": "aw666666-6666-6666-6666-aw6666666615",
"name": "Respond to Webhook"
}
],
"connections": {
"Every 24 Hours": {
"main": [
[
{
"node": "Set Login Config [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Set Login Config [Schedule]": {
"main": [
[
{
"node": "Solve Captcha [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Solve Captcha [Schedule]": {
"main": [
[
{
"node": "Submit Login [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Submit Login [Schedule]": {
"main": [
[
{
"node": "Login Successful? [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Login Successful? [Schedule]": {
"main": [
[
{
"node": "Mark Login Success [Schedule]",
"type": "main",
"index": 0
}
],
[
{
"node": "Mark Login Failed [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Webhook Trigger": {
"main": [
[
{
"node": "Solve Captcha [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Solve Captcha [Webhook]": {
"main": [
[
{
"node": "Submit Login [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Submit Login [Webhook]": {
"main": [
[
{
"node": "Login Successful? [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Login Successful? [Webhook]": {
"main": [
[
{
"node": "Mark Login Success [Webhook]",
"type": "main",
"index": 0
}
],
[
{
"node": "Mark Login Failed [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Mark Login Success [Webhook]": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Mark Login Failed [Webhook]": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
}
}
Conclusion
You've learned how to build AWS WAF-solving APIs and production-ready scraping workflows using n8n and CapSolver — no traditional coding required.
In this guide, we covered:
- API solver endpoints for AWS WAF using webhook-based workflows
- Use-case examples — scraping and account login — showing how to submit solved cookies and process protected data
- How to identify AWS WAF parameters using DevTools
- Best practices for cookie-based token handling, error management, and production use
The key takeaway: AWS WAF tokens work differently from reCAPTCHA and Turnstile — they are submitted as cookies via the Cookie HTTP header, not as form fields. Only websiteURL is required (no site key needed), and the solution returns solution.cookie instead of solution.token.
Tip: These workflows use Schedule + Webhook triggers, but you can swap the trigger node to any n8n trigger — manual, app event, form submission, etc. After fetching data, use n8n's built-in nodes to save results to Google Sheets, databases, cloud storage, or send alerts via Telegram/Slack/Email.
Ready to get started? Sign up for CapSolver and use bonus code n8n for an extra 8% bonus on your first recharge!

Frequently Asked Questions
What is AWS WAF?
AWS WAF (Web Application Firewall) is Amazon's web security service that protects websites from bots, scrapers, and other automated threats. It can present invisible CAPTCHA challenges that require an aws-waf-token cookie to bypass. Many enterprise and e-commerce sites use it.
How much does it cost to solve an AWS WAF challenge?
Pricing varies by task complexity. Check the CapSolver pricing page for current AWS WAF rates.
How long does it take to solve an AWS WAF challenge?
Most AWS WAF challenges are solved in 5-30 seconds depending on the site's configuration and the parameters provided. Providing optional parameters like awsKey, awsIv, and awsContext can improve solve speed and reliability.
Can I use these workflows with n8n Cloud?
Yes! These workflows work with both self-hosted n8n and n8n Cloud. The CapSolver node is already available as an official integration — just add your API credentials.
How do I find AWS WAF parameters for a website?
The simplest approach: open the target site, check for aws-waf-token in cookies (Application tab in DevTools), and look for network requests to captcha.awswaf.com. For most sites, you only need the websiteURL.
CapSolver returned a cookie but the website still rejected it — why?
Several things can cause this. First, cookies expire quickly — make sure you're using the cookie immediately after solving. Second, verify you're sending the cookie correctly: it must go in the Cookie HTTP header (not a form field or custom header). Third, some sites may require additional parameters like awsContext or awsChallengeJS — use the CapSolver extension to check. Fourth, some stricter sites may require the AntiAwsWafTask type (with proxy) instead of AntiAwsWafTaskProxyLess. If the cookie is still rejected, contact CapSolver support for site-specific help.
Compliance Disclaimer: The information provided on this blog is for informational purposes only. CapSolver is committed to compliance with all applicable laws and regulations. The use of the CapSolver network for illegal, fraudulent, or abusive activities is strictly prohibited and will be investigated. Our captcha-solving solutions enhance user experience while ensuring 100% compliance in helping solve captcha difficulties during public data crawling. We encourage responsible use of our services. For more information, please visit our Terms of Service and Privacy Policy.
More

How to Use CapSolver in n8n: The Complete Guide to Solving CAPTCHA in Your Workflows
Learn how to integrate CapSolver with n8n to solve CAPTCHAs and build reliable automation workflows with ease.

Lucas Mitchell
18-Mar-2026

How to Solve Cloudflare Turnstile Using CapSolver and n8n
Build a Cloudflare Turnstile solver API using CapSolver and n8n. Learn how to automate token solving, submit it to websites, and extract protected data with no coding.

Ethan Collins
18-Mar-2026

How to Solve reCAPTCHA v2/v3 Using CapSolver and n8n
Build a eCAPTCHA v2/v3 solver API using CapSolver and n8n. Learn how to automate token solving, submit it to websites, and extract protected data with no coding.

Lucas Mitchell
18-Mar-2026

How to Solve TLS Fingerprinting in n8n with CapSolver
Solve TLS fingerprinting in n8n with CapSolver. Make requests appear as real browsers and avoid bot detection blocks.

Ethan Collins
18-Mar-2026

How to Solve Visual Puzzles in n8n with CapSolver
Solve visual CAPTCHAs with CapSolver Vision Engine in n8n. Handle sliders, rotation, object selection, and GIF OCR instantly.

Ethan Collins
18-Mar-2026

How to Solve GeeTest V3 in n8n with CapSolver: Complete Integration Guide
Learn how to integrate CapSolver with n8n to solve GeeTest V3 and build reliable automation workflows.

Ethan Collins
18-Mar-2026

