How to Solve Cloudflare Turnstile Using CapSolver and n8n

Ethan Collins
Pattern Recognition Specialist
18-Mar-2026

Cloudflare Turnstile is quickly becoming the go-to CAPTCHA alternative for modern websites. Unlike traditional CAPTCHAs that force users to solve image puzzles, Turnstile runs silently in the background โ making it harder to detect and bypass with standard automation tools.
What if you could solve Turnstile 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 Cloudflare Turnstile challenges on demand โ either as a standalone API endpoint or as a step inside any automation workflow.
What you'll build:
Solver APIs โ reusable endpoints your other tools can call:
- A Cloudflare Turnstile solver API
Direct-use workflows โ CapSolver embedded as a step inside larger automations:
- A price & product scraper that solves Turnstile, fetches protected pages, and alerts on price changes
- An account login automation that solves Turnstile before submitting credentials
What is Cloudflare Turnstile?
Cloudflare Turnstile is a CAPTCHA alternative that verifies visitors automatically using browser signals โ no puzzles, no checkboxes. It appears as a small widget embedded in forms (login, signup, checkout) and comes in three modes: Managed, Non-Interactive, and Invisible. From a solving perspective, the mode doesn't matter โ you always need the same two parameters: websiteURL and websiteKey.

Not the same as Cloudflare Challenge. If you see a full-page "Performing security verification..." screen, that's a Cloudflare Challenge, not Turnstile โ it requires a different solver.
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)
- CapSolver browser extension (optional but recommended) โ For identifying captcha parameters on target websites
Important: Make sure you have sufficient balance in your CapSolver account. Turnstile 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 Turnstile solver workflow!
Workflow: Cloudflare Turnstile Solver API
This workflow creates a POST API endpoint that accepts Turnstile parameters and returns a solved token.

How It Works
The workflow consists of four nodes:
- Webhook โ Receives incoming POST requests with Turnstile parameters
- Cloudflare Turnstile โ 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-turnstile |
| Respond | Response Node |
This creates an endpoint at: https://your-n8n-instance.com/webhook/solver-turnstile
2. CapSolver Cloudflare Turnstile Node
| Parameter | Value | Description |
|---|---|---|
| Operation | Cloudflare Turnstile |
Must be set to Cloudflare Turnstile |
| Type | AntiTurnstileTaskProxyLess |
This task type does not require a proxy |
| Website URL | {{ $json.body.websiteURL }} |
The URL of the page with the Turnstile widget |
| Website Key | {{ $json.body.websiteKey }} |
The Turnstile site key |
| metadata.action | (Optional) | Some sites require a specific action string for the Turnstile challenge |
| metadata.cdata | (Optional) | Custom data that some sites pass to the Turnstile widget for verification |
Some sites also require metadata.action and/or metadata.cdata โ you can add these under the Optional section in the node. 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) }} |
Test It
Send a POST request to your webhook endpoint:
bash
curl -X POST https://your-n8n-instance.com/webhook/solver-turnstile \
-H "Content-Type: application/json" \
-d '{
"websiteURL": "https://example.com/login",
"websiteKey": "0x4AAAAAAADV8V8V8V8V8V8V"
}'
Expected Response:
json
{
"taskId": "abc123...",
"solution": {
"token": "0.XXXXXXXXXXXXXXXX..."
},
"status": "ready"
}
Import This Workflow
Copy the JSON below and import it into n8n via Menu โ Import from JSON:
Click to expand workflow JSON
json
{
"name": "Turnstile โ Solver API",
"nodes": [
{
"parameters": {
"content": "## Turnstile โ Solver API\n\n**Who it's for:** Developers who need to solve Turnstile 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 Turnstile 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-1773678228117-1",
"name": "Sticky Note"
},
{
"parameters": {
"httpMethod": "POST",
"path": "solver-turnstile",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-192,
0
],
"id": "137be4f0-1762-4f0c-b993-c512d27e35de",
"name": "Receive Solver Request",
"webhookId": "3d32ad61-d925-4a09-8fe5-7226e6664a98"
},
{
"parameters": {
"operation": "Cloudflare Turnstile",
"websiteURL": "={{ $json.body.websiteURL }}",
"websiteKey": "={{ $json.body.websiteKey }}",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
112,
0
],
"id": "954ff1f0-d5de-4468-b0d1-fbce03676676",
"name": "Cloudflare Turnstile",
"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": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"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": "e1f2a3b4-c5d6-7890-abcd-123456789012",
"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": "db264e2b-48ce-4887-9b2b-2b8077993c30",
"name": "Respond to Webhook"
}
],
"connections": {
"Receive Solver Request": {
"main": [
[
{
"node": "Cloudflare Turnstile",
"type": "main",
"index": 0
}
]
]
},
"Cloudflare Turnstile": {
"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 Turnstile solver API endpoint accepts the following parameters:
| Parameter | Required | Description |
|---|---|---|
websiteURL |
Yes | The URL of the page hosting the Turnstile widget |
websiteKey |
Yes | The Turnstile site key |
metadata.action |
No | Action string required by some sites for the Turnstile challenge |
metadata.cdata |
No | Custom data passed to the Turnstile widget by some sites |
Tip: You can identify the
websiteURLandwebsiteKeyby inspecting the page source or using the CapSolver browser extension.
Compared to reCAPTCHA, Turnstile is simpler โ you only need two required parameters. Some sites may also require the optional metadata.action or metadata.cdata fields โ add these in the node's Optional section if the token isn't being accepted.
Workflow: Submitting a Turnstile Token to a Website
The API workflow above shows how to get a solved Turnstile token. 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 token to the target website โ exactly as a browser would โ to unlock the data or action behind the Turnstile protection.
Here's the general pattern:
- Solve the challenge โ Get the token from CapSolver
- Submit the token โ Send it to the target website via an HTTP Request (usually as a
cf-turnstile-responseform field) - Verify the response โ Check if the website accepted the token
- Process the result โ Extract the data you need
Example: Solving & Submitting Turnstile
Example: https://example.com/ โ A Turnstile-protected website
Workflow Flow
Manual Trigger โ CapSolver Turnstile โ HTTP POST Request โ IF (check success) โ Edit Fields (extract data)
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 Cloudflare Turnstile โ Solves the Turnstile challenge:
- Operation:
Cloudflare Turnstile - Website URL:
https://example.com/login - Website Key:
0x4AAAAAAA...(find it by inspecting the page source โ see How to Identify Turnstile Parameters
- Operation:
- HTTP POST Request โ Submits the solved token to the target website:
- The token is sent in the
cf-turnstile-responseform field - Include any other form fields the site expects (e.g.,
username,password) - This is what a browser does when you submit the form after Turnstile validates you
- The token is sent in the
- IF Node โ Checks if the response indicates success (e.g., a redirect, a success message, or specific JSON fields)
- Edit Fields โ Extracts the data you need from the response. In a real scenario, this is where you'd parse the HTML using the HTML node to pull out specific elements (e.g., user data, product listings, dashboard content) and map them to your output fields
Key concept: Every website handles token submission differently. In this example, the token goes in a
cf-turnstile-responseform field via POST โ but other sites may expect it in a different field name, as a JSON body, as a header, or through a completely different endpoint. Always inspect the site's actual form submission (using DevTools Network tab) to see exactly how the token needs to be sent.
Workflow: Use-Case Examples
The solver API and scraping example above show the core pattern: solve the Turnstile, submit the token, 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 |
|---|---|
Turnstile 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 |
Turnstile Account Login โ CapSolver + Schedule + Webhook |
Logs into your own account on a captcha-protected site by solving first, then POSTing credentials with the token |
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 Captcha โ Fetch Product Page โ Extract Data
โ Compare Data โ Data Changed? โ Build Alert / No Change
Key behaviors:
- The token is sent as a
cf-turnstile-responseheader (adapt to your site's expected format โ some sites may use a different field name) - 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": "Turnstile Scraping โ Price & Product Details โ CapSolver + Schedule + Webhook",
"nodes": [
{
"parameters": {
"content": "## Turnstile Scraping โ Price & Product Monitor\n\n**Who it's for:** Teams monitoring prices or product data on Turnstile-protected sites.\n\n**What it does:** Solves Turnstile, 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 Turnstile 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-1773678228117-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-1773678228117-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-1773678228117-3",
"name": "Sticky Note2"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-400,
0
],
"id": "33333333-3333-3333-3333-333333333301",
"name": "Every 6 Hours"
},
{
"parameters": {
"operation": "Cloudflare Turnstile",
"websiteURL": "https://YOUR-TARGET-SITE.com/product-page",
"websiteKey": "YOUR_SITE_KEY_HERE",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-96,
0
],
"id": "33333333-3333-3333-3333-333333333302",
"name": "Solve Turnstile",
"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": "cf-turnstile-response",
"value": "={{ $json.data.solution.token }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": false
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
208,
0
],
"id": "33333333-3333-3333-3333-333333333303",
"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": "33333333-3333-3333-3333-333333333304",
"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": "33333333-3333-3333-3333-333333333305",
"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": "33333333-3333-3333-3333-333333333306",
"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": "33333333-3333-3333-3333-333333333307",
"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": "33333333-3333-3333-3333-333333333308",
"name": "No Change"
},
{
"parameters": {
"httpMethod": "POST",
"path": "price-monitor",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-400,
420
],
"id": "33333333-3333-3333-3333-333333333309",
"name": "Webhook Trigger",
"webhookId": "33333333-aaaa-bbbb-cccc-333333333309",
"onError": "continueRegularOutput"
},
{
"parameters": {
"operation": "Cloudflare Turnstile",
"websiteURL": "https://YOUR-TARGET-SITE.com/product-page",
"websiteKey": "YOUR_SITE_KEY_HERE",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-96,
420
],
"id": "33333333-3333-3333-3333-333333333310",
"name": "Solve Turnstile [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": "cf-turnstile-response",
"value": "={{ $json.data.solution.token }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": false
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
208,
420
],
"id": "33333333-3333-3333-3333-333333333311",
"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": "33333333-3333-3333-3333-333333333312",
"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": "33333333-3333-3333-3333-333333333313",
"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": "33333333-3333-3333-3333-333333333314",
"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": "33333333-3333-3333-3333-333333333315",
"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": "33333333-3333-3333-3333-333333333316",
"name": "No Change [Webhook]"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
1712,
420
],
"id": "33333333-3333-3333-3333-333333333317",
"name": "Respond to Webhook"
}
],
"connections": {
"Every 6 Hours": {
"main": [
[
{
"node": "Solve Turnstile",
"type": "main",
"index": 0
}
]
]
},
"Solve Turnstile": {
"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 Turnstile [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Solve Turnstile [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 a captcha-protected site. A Set Login Config node centralizes all parameters โ [Schedule] for the schedule path and [Webhook] for the on-demand webhook path. Edit the appropriate config node to configure each path.
Schedule path:
Every 24 Hours โ Set Login Config โ Solve Captcha โ Submit Login
โ Login Successful? โ Mark Login Success / Mark Login Failed
Key behaviors:
- Defaults to Cloudflare Turnstile โ change the
Operationin the Solve Captcha node for other captcha types - Body parameters are hardcoded:
email,password, andcf-turnstile-response(edit the Submit Login node directly to match your site's field names) - The Login Successful? check evaluates both
statusCode < 400and the presence of a configurablesuccessMarkerin the response body - Webhook path uses Set Login Config [Webhook] with the same hardcoded placeholder values โ edit that node to configure the webhook on-demand path
- Webhook path returns the result as JSON via Respond to Webhook
Click to expand full workflow JSON (15 nodes)
json
{
"name": "Turnstile Account Login โ CapSolver + Schedule + Webhook",
"nodes": [
{
"parameters": {
"content": "## Turnstile Account Login\n\n**Who it's for:** Anyone automating login to a Turnstile-protected website.\n\n**What it does:** Solves Turnstile 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 Turnstile 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-1773678228116-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-1773678228116-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-1773678228116-3",
"name": "Sticky Note2"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 24
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-640,
0
],
"id": "tt666666-6666-6666-6666-tt6666666601",
"name": "Every 24 Hours"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "login-001",
"name": "websiteURL",
"value": "https://YOUR-LOGIN-PAGE.com",
"type": "string"
},
{
"id": "login-004",
"name": "websiteKey",
"value": "YOUR_SITE_KEY_HERE",
"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": "tt666666-6666-6666-6666-tt6666666602",
"name": "Set Login Config [Schedule]"
},
{
"parameters": {
"operation": "Cloudflare Turnstile",
"websiteURL": "={{ $json.websiteURL }}",
"websiteKey": "={{ $json.websiteKey }}"
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-32,
0
],
"id": "tt666666-6666-6666-6666-tt6666666603",
"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 }}"
}
]
},
"sendBody": true,
"contentType": "form-urlencoded",
"bodyParameters": {
"parameters": [
{
"name": "email",
"value": "[email protected]"
},
{
"name": "password",
"value": "YOUR_ACCOUNT_PASSWORD"
},
{
"name": "cf-turnstile-response",
"value": "={{ $json.data.solution.token }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": true,
"neverError": true
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
272,
0
],
"id": "tt666666-6666-6666-6666-tt6666666604",
"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": "tt666666-6666-6666-6666-tt6666666605",
"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": "tt666666-6666-6666-6666-tt6666666606",
"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": "tt666666-6666-6666-6666-tt6666666607",
"name": "Mark Login Failed [Schedule]"
},
{
"parameters": {
"httpMethod": "POST",
"path": "account-login",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-640,
420
],
"id": "tt666666-6666-6666-6666-tt6666666608",
"name": "Webhook Trigger",
"webhookId": "66666666-aaaa-bbbb-cccc-666666666608",
"onError": "continueRegularOutput"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "login-001",
"name": "websiteURL",
"value": "https://YOUR-LOGIN-PAGE.com",
"type": "string"
},
{
"id": "login-004",
"name": "websiteKey",
"value": "YOUR_SITE_KEY_HERE",
"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,
420
],
"id": "tt666666-6666-6666-6666-tt6666666609",
"name": "Set Login Config [Webhook]"
},
{
"parameters": {
"operation": "Cloudflare Turnstile",
"websiteURL": "={{ $json.websiteURL }}",
"websiteKey": "={{ $json.websiteKey }}"
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-32,
420
],
"id": "tt666666-6666-6666-6666-tt6666666610",
"name": "Solve Captcha [Webhook]",
"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 [Webhook]').item.json.userAgent }}"
}
]
},
"sendBody": true,
"contentType": "form-urlencoded",
"bodyParameters": {
"parameters": [
{
"name": "email",
"value": "[email protected]"
},
{
"name": "password",
"value": "YOUR_ACCOUNT_PASSWORD"
},
{
"name": "cf-turnstile-response",
"value": "={{ $json.data.solution.token }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": true,
"neverError": true
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
272,
420
],
"id": "tt666666-6666-6666-6666-tt6666666611",
"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($('Set Login Config [Webhook]').item.json.successMarker) }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
576,
420
],
"id": "tt666666-6666-6666-6666-tt6666666612",
"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": "tt666666-6666-6666-6666-tt6666666613",
"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": "tt666666-6666-6666-6666-tt6666666614",
"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": "tt666666-6666-6666-6666-tt6666666615",
"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": "Set Login Config [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Set Login Config [Webhook]": {
"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 a Cloudflare Turnstile-solving API and production-ready scraping workflows using n8n and CapSolver โ no traditional coding required.
In this guide, we covered:
- An API solver endpoint for Cloudflare Turnstile using a webhook-based workflow
- Use-case examples โ scraping and account login โ showing how to submit solved tokens and process protected data
- How to identify Turnstile parameters by inspecting the page source
- Best practices for token handling, error management, and production use
The key takeaway: solving the Turnstile challenge is only half the job โ you also need to submit the token to the target website to unlock the protected data.
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 Cloudflare Turnstile?
Cloudflare Turnstile is a CAPTCHA alternative that verifies visitors without requiring them to solve puzzles. It runs in the background using browser signals and behavioral analysis to determine if a visitor is human.
How much does it cost to solve a Turnstile challenge?
Pricing varies based on usage. Check the CapSolver pricing page for current Turnstile rates.
How long does it take to solve a Turnstile challenge?
Turnstile challenges are typically solved in a few seconds since there are no image challenges involved.
Can I use this workflow with n8n Cloud?
Yes! This workflow works 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 the Turnstile site key for a website?
Search the page source for data-sitekey in the HTML or look for turnstile.render() in the JavaScript. You can also open DevTools (F12) โ Network tab and filter by turnstile to find the site key in requests. For a detailed guide, see the CapSolver documentation.
CapSolver returned a token but the website still rejected it โ why?
Several things can cause this. First, tokens expire quickly โ make sure you're submitting the token immediately. Second, verify you're sending the token to the right place: inspect the actual network request the browser makes when you submit the form (DevTools โ Network tab) and confirm the field name (cf-turnstile-response is typical but not universal), request method, and endpoint all match what you've configured in n8n. Third, some sites require metadata.action or metadata.cdata parameters โ use the CapSolver extension to check if any of these apply. If the token 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 ImageToText Using CapSolver and n8n
Automate captcha solving with n8n using CapSolver Image to Text. Instantly convert images to text and streamline workflows.

Ethan Collins
18-Mar-2026

