CAPSOLVER
Blog
How to Solve GeeTest V4 in n8n with CapSolver: Complete Integration Guide

How to Solve GeeTest V4 in n8n with CapSolver: Complete Integration Guide

Logo of CapSolver

Ethan Collins

Pattern Recognition Specialist

18-Mar-2026

GeeTest V4 is the latest generation of GeeTest's behavioral CAPTCHA system, used by a growing number of websites to protect login forms, registration pages, and data endpoints. Unlike older CAPTCHA systems that rely on image puzzles, GeeTest V4 uses adaptive challenges and behavioral analysis — making it one of the more sophisticated protections you'll encounter in automation workflows.

What if you could solve GeeTest V4 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 GeeTest V4 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 GeeTest V4 solver API

Direct-use workflows — CapSolver embedded as a step inside larger automations:

  • A price & product scraper that solves GeeTest V4, fetches protected pages, and alerts on price changes
  • An account login automation that solves GeeTest V4 before submitting credentials

What is GeeTest V4?

GeeTest V4 is the newest version of GeeTest's CAPTCHA platform. It replaces the older V3 system with a simplified integration model and enhanced behavioral detection. From a solving perspective, V4 is structurally simpler than V3 — it only requires one static parameter (captchaId) instead of the dynamic challenge flow that V3 needs.

Key differences from GeeTest V3:

Feature GeeTest V3 GeeTest V4
Main parameter gt + dynamic challenge captchaId (static)
Challenge fetch Required — must call GeeTest API first Not needed — captchaId is static
Solution fields 3 (challenge, validate, seccode) 5 (captcha_id, lot_number, pass_token, gen_time, captcha_output)
Widget script gt.js gcaptcha4.js
Task type GeeTestTask / GeeTestTaskProxyLess GeeTestTaskProxyLess only

Why V4 is simpler to automate: The captchaId is embedded in the page source and never changes — find it once, use it forever. No dynamic challenge fetching means fewer nodes in your workflow.


Prerequisites

Before getting started, make sure you have the following:

  1. An n8n instance — Either self-hosted or n8n Cloud
  2. A CapSolver accountSign up here and get your API key
  3. 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. GeeTest V4 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.

n8n credentials page showing CapSolver account

Step 2: Create the CapSolver Credential

  1. Click Create credential (top right)
  2. Search for "CapSolver" and select CapSolver API
  3. Enter your API Key — copy it directly from the CapSolver Dashboard
  4. Leave Allowed HTTP Request Domains set to All (default)
  5. Click Save

n8n will automatically test the connection. You should see a green "Connection tested successfully" banner confirming your API key is valid.

CapSolver credential configuration with successful connection test

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 GeeTest V4 solver workflow!


How to Identify GeeTest V4 Parameters

Before you can solve a GeeTest V4 CAPTCHA, you need to find its captchaId — the only required parameter. Unlike GeeTest V3 (which requires fetching a dynamic challenge), V4's captchaId is static and embedded directly in the page source.

Method 1: Inspect Page Source

  1. Open View Source (Ctrl+U) or use DevTools Elements tab
  2. Search for captcha_id or captchaId in the page source
  3. Look for references to gcaptcha4.js — the GeeTest V4 widget script
  4. The captchaId is typically passed as a configuration parameter when initializing the widget
html Copy
<!-- Example: GeeTest V4 initialization in page source -->
<script>
  initGeetest4({
    captchaId: 'e392e1d7fd421dc63325744d5a2b9c73',
    product: 'bind'
  });
</script>

Method 2: DevTools Network Tab

  1. Open DevTools (F12) > Network tab
  2. Filter requests by gcaptcha4 or geetest
  3. Look for requests to gcaptcha4.geetest.com — the captcha_id parameter will be in the query string

Key advantage of V4: The captchaId is static — once you find it, you can use it indefinitely without needing to fetch a new challenge each time. This makes V4 workflows structurally identical to Turnstile workflows.


Workflow: GeeTest V4 Solver API

This workflow creates a POST API endpoint that accepts GeeTest V4 parameters and returns a solved token set.

How It Works

The workflow consists of four nodes:

  1. Webhook — Receives incoming POST requests with GeeTest V4 parameters
  2. GeeTest V4 — Sends the challenge to CapSolver and waits for a solution
  3. CapSolver Error? — IF node that branches on whether solving failed ($json.error is not empty)
  4. Respond to Webhook — Returns the solution on success, or {"error": "..."} on failure

Node Configuration

1. Webhook Node

Setting Value
HTTP Method POST
Path solver-geetest-v4
Respond Response Node

This creates an endpoint at: https://your-n8n-instance.com/webhook/solver-geetest-v4

2. CapSolver GeeTest V4 Node

Parameter Value Description
Operation GeeTest V4 Must be set to GeeTest V4
Type GeeTestTaskProxyLess This is the only available task type (no proxy variant)
Website URL {{ $json.body.websiteURL }} The URL of the page with the GeeTest V4 widget
Captcha ID {{ $json.body.captchaId }} The static GeeTest V4 captcha ID
GeeTest API Server Subdomain (Optional) Custom GeeTest API server if the site uses one

Select your CapSolver credentials in this node. The optional geetestApiServerSubdomain parameter is rarely needed — only add it if the default GeeTest server doesn't work for your target site.

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

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 Copy
curl -X POST https://your-n8n-instance.com/webhook/solver-geetest-v4 \
  -H "Content-Type: application/json" \
  -d '{
    "websiteURL": "https://example.com/login",
    "captchaId": "e392e1d7fd421dc63325744d5a2b9c73"
  }'

Expected Response:

json Copy
{
  "taskId": "abc123...",
  "solution": {
    "captcha_id": "e392e1d7fd421dc63325744d5a2b9c73",
    "lot_number": "7c18c041a6ed4e...",
    "pass_token": "d88ce40c0a5c5a18...",
    "gen_time": "1709123456",
    "captcha_output": "dGVzdF9jYXB0Y2hh..."
  },
  "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 Copy
{
  "name": "GeeTest V4 — Solver API",
  "nodes": [
    {
      "parameters": {
        "content": "## GeeTest V4 — Solver API\n\n**Who it's for:** Developers who need to solve GeeTest V4 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 GeeTest V4 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-1773678228112-1",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "solver-geetest-v4",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -192,
        0
      ],
      "id": "a1b2c3d4-0001-0001-0001-a1b2c3d40001",
      "name": "Receive Solver Request",
      "webhookId": "a1b2c3d4-0001-0001-0001-a1b2c3d40002"
    },
    {
      "parameters": {
        "operation": "GeeTest V4",
        "websiteURL": "={{ $json.body.websiteURL }}",
        "captchaId": "={{ $json.body.captchaId }}",
        "optional": {}
      },
      "type": "n8n-nodes-capsolver.capSolver",
      "typeVersion": 1,
      "position": [
        112,
        0
      ],
      "id": "a1b2c3d4-0001-0001-0001-a1b2c3d40003",
      "name": "GeeTest V4",
      "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-0001-0001-0001-a1b2c3d40004",
      "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": "a1b2c3d4-0001-0001-0001-a1b2c3d40005",
      "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": "a1b2c3d4-0001-0001-0001-a1b2c3d40006",
      "name": "Respond to Webhook"
    }
  ],
  "connections": {
    "Receive Solver Request": {
      "main": [
        [
          {
            "node": "GeeTest V4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GeeTest V4": {
      "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 GeeTest V4 solver API endpoint accepts the following parameters:

Parameter Required Description
websiteURL Yes The URL of the page hosting the GeeTest V4 widget
captchaId Yes The static GeeTest V4 captcha ID (found in page source)
geetestApiServerSubdomain No Custom GeeTest API server subdomain (rarely needed)

Tip: You can identify the websiteURL and captchaId by inspecting the page source or using DevTools to search for captcha_id in network requests.

Compared to GeeTest V3, V4 is simpler — you only need two required parameters and the captchaId is static. No dynamic challenge fetching is needed.


Workflow: Submitting GeeTest V4 Tokens to a Website

The API workflow above shows how to get a solved GeeTest V4 token set. 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 5 solution fields to the target website — exactly as a browser would — to unlock the data or action behind the GeeTest V4 protection.

Here's the general pattern:

  1. Solve the challenge > Get the 5 solution fields from CapSolver
  2. Submit the fields > Send them to the target website via an HTTP Request (as form fields or JSON body)
  3. Verify the response > Check if the website accepted the solution
  4. Process the result > Extract the data you need

The 5 Solution Fields

Unlike Turnstile (single token) or reCAPTCHA (single gRecaptchaResponse), GeeTest V4 returns 5 solution fields that must all be submitted together:

Field Description
captcha_id The captcha identifier (same as input captchaId)
lot_number Unique lot number for this solve
pass_token Authentication token proving the solve
gen_time Timestamp when the solution was generated
captcha_output The actual captcha output/answer

Example: Solving & Submitting GeeTest V4

Example: https://example.com/ — A GeeTest V4-protected website

Workflow Flow

Copy
Manual Trigger > CapSolver GeeTest V4 > HTTP POST Request (5 fields) > IF (check success) > Edit Fields (extract data)

How It Works

  1. Manual Trigger — Starts the workflow manually (click "Execute workflow"). You can replace this with any trigger — Webhook, Schedule, App Event, etc.
  2. CapSolver GeeTest V4 — Solves the GeeTest V4 challenge:
    • Operation: GeeTest V4
    • Website URL: https://example.com/login
    • Captcha ID: e392e1d7fd421dc... (find it by inspecting the page source)
  3. HTTP POST Request — Submits the 5 solved fields to the target website:
    • captcha_id = {{ $json.data.solution.captcha_id }}
    • lot_number = {{ $json.data.solution.lot_number }}
    • pass_token = {{ $json.data.solution.pass_token }}
    • gen_time = {{ $json.data.solution.gen_time }}
    • captcha_output = {{ $json.data.solution.captcha_output }}
    • Include any other form fields the site expects (e.g., username, password)
  4. IF Node — Checks if the response indicates success (e.g., a redirect, a success message, or specific JSON fields)
  5. Edit Fields — Extracts the data you need from the response

Key concept: Every website handles token submission differently. In this example, the 5 fields are sent as form-urlencoded POST data — but other sites may expect them as JSON body fields, query parameters, or through a completely different endpoint. Always inspect the site's actual form submission (using DevTools Network tab) to see exactly how the fields need to be sent.


Workflow: Use-Case Examples

The solver API and scraping example above show the core pattern: solve the GeeTest V4, submit the 5 fields, 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
GeeTest V4 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
GeeTest V4 Account Login — CapSolver + Schedule + Webhook Logs into your own account on a captcha-protected site by solving first, then POSTing credentials with the 5 solution fields

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:

Copy
Every 6 Hours > Solve GeeTest V4 > Fetch Product Page > Extract Data
  > Compare Data > Data Changed? > Build Alert / No Change

Key behaviors:

  • The 5 solution fields are sent as form-urlencoded POST body parameters (adapt to your site's expected format)
  • The HTML node extracts price and product name via CSS selectors (.product-price, h1)
  • $workflow.staticData.lastPrice persists 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 Copy
{
  "name": "GeeTest V4 Scraping — Price & Product Details — CapSolver + Schedule + Webhook",
  "nodes": [
    {
      "parameters": {
        "content": "## GeeTest V4 Scraping — Price & Product Monitor\n\n**Who it's for:** Teams monitoring prices or product data on GeeTest V4-protected sites.\n\n**What it does:** Solves GeeTest V4, 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 GeeTest V4 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-1773678228112-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-1773678228112-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-1773678228112-3",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 6
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        -400,
        0
      ],
      "id": "99999999-9999-9999-9999-999999999901",
      "name": "Every 6 Hours"
    },
    {
      "parameters": {
        "operation": "GeeTest V4",
        "websiteURL": "https://YOUR-TARGET-SITE.com/product-page",
        "captchaId": "YOUR_CAPTCHA_ID_HERE",
        "optional": {}
      },
      "type": "n8n-nodes-capsolver.capSolver",
      "typeVersion": 1,
      "position": [
        -96,
        0
      ],
      "id": "99999999-9999-9999-9999-999999999902",
      "name": "Solve GeeTest V4",
      "credentials": {
        "capSolverApi": {
          "id": "YOUR_CREDENTIAL_ID",
          "name": "CapSolver account"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "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"
            }
          ]
        },
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "captcha_id",
              "value": "={{ $json.data.solution.captcha_id }}"
            },
            {
              "name": "lot_number",
              "value": "={{ $json.data.solution.lot_number }}"
            },
            {
              "name": "pass_token",
              "value": "={{ $json.data.solution.pass_token }}"
            },
            {
              "name": "gen_time",
              "value": "={{ $json.data.solution.gen_time }}"
            },
            {
              "name": "captcha_output",
              "value": "={{ $json.data.solution.captcha_output }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "fullResponse": false
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        208,
        0
      ],
      "id": "99999999-9999-9999-9999-999999999903",
      "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": "99999999-9999-9999-9999-999999999904",
      "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": "99999999-9999-9999-9999-999999999905",
      "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": "99999999-9999-9999-9999-999999999906",
      "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": "99999999-9999-9999-9999-999999999907",
      "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": "99999999-9999-9999-9999-999999999908",
      "name": "No Change"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "price-monitor-geetest-v4",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -400,
        420
      ],
      "id": "99999999-9999-9999-9999-999999999909",
      "name": "Webhook Trigger",
      "webhookId": "99999999-aaaa-bbbb-cccc-999999999909",
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "operation": "GeeTest V4",
        "websiteURL": "https://YOUR-TARGET-SITE.com/product-page",
        "captchaId": "YOUR_CAPTCHA_ID_HERE",
        "optional": {}
      },
      "type": "n8n-nodes-capsolver.capSolver",
      "typeVersion": 1,
      "position": [
        -96,
        420
      ],
      "id": "99999999-9999-9999-9999-999999999910",
      "name": "Solve GeeTest V4 [Webhook]",
      "credentials": {
        "capSolverApi": {
          "id": "YOUR_CREDENTIAL_ID",
          "name": "CapSolver account"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "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"
            }
          ]
        },
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "captcha_id",
              "value": "={{ $json.data.solution.captcha_id }}"
            },
            {
              "name": "lot_number",
              "value": "={{ $json.data.solution.lot_number }}"
            },
            {
              "name": "pass_token",
              "value": "={{ $json.data.solution.pass_token }}"
            },
            {
              "name": "gen_time",
              "value": "={{ $json.data.solution.gen_time }}"
            },
            {
              "name": "captcha_output",
              "value": "={{ $json.data.solution.captcha_output }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "fullResponse": false
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        208,
        420
      ],
      "id": "99999999-9999-9999-9999-999999999911",
      "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": "99999999-9999-9999-9999-999999999912",
      "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": "99999999-9999-9999-9999-999999999913",
      "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": "99999999-9999-9999-9999-999999999914",
      "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": "99999999-9999-9999-9999-999999999915",
      "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": "99999999-9999-9999-9999-999999999916",
      "name": "No Change [Webhook]"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify($json) }}",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        1712,
        420
      ],
      "id": "99999999-9999-9999-9999-999999999917",
      "name": "Respond to Webhook"
    }
  ],
  "connections": {
    "Every 6 Hours": {
      "main": [
        [
          {
            "node": "Solve GeeTest V4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Solve GeeTest V4": {
      "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 GeeTest V4 [Webhook]",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Solve GeeTest V4 [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:

Copy
Every 24 Hours > Set Login Config > Solve GeeTest V4 > Submit Login
  > Login Successful? > Mark Login Success / Mark Login Failed

Key behaviors:

  • Uses GeeTest V4 — the CapSolver node operation is set to GeeTest V4
  • Body parameters include the 7 form fields: username, password, plus the 5 GeeTest V4 solution fields (captcha_id, lot_number, pass_token, gen_time, captcha_output)
  • The Login Successful? check evaluates both statusCode < 400 and the presence of a configurable successMarker in the response body
  • Webhook path accepts all parameters via the POST body — edit the webhook request to configure on-demand login
  • Webhook path returns the result as JSON via Respond to Webhook
Click to expand full workflow JSON (15 nodes)
json Copy
{
  "name": "GeeTest V4 Account Login — CapSolver + Schedule + Webhook",
  "nodes": [
    {
      "parameters": {
        "content": "## GeeTest V4 Account Login\n\n**Who it's for:** Anyone automating login to a GeeTest V4-protected website.\n\n**What it does:** Solves GeeTest V4 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 GeeTest V4 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-1773678228112-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-1773678228112-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-1773678228112-3",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 24
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        -640,
        0
      ],
      "id": "99999999-9999-9999-9999-999999999921",
      "name": "Every 24 Hours"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "login-001",
              "name": "websiteURL",
              "value": "https://YOUR-LOGIN-PAGE.com",
              "type": "string"
            },
            {
              "id": "login-002",
              "name": "captchaId",
              "value": "YOUR_CAPTCHA_ID_HERE",
              "type": "string"
            },
            {
              "id": "login-003",
              "name": "usernameField",
              "value": "email",
              "type": "string"
            },
            {
              "id": "login-004",
              "name": "passwordField",
              "value": "password",
              "type": "string"
            },
            {
              "id": "login-005",
              "name": "usernameValue",
              "value": "[email protected]",
              "type": "string"
            },
            {
              "id": "login-006",
              "name": "passwordValue",
              "value": "YOUR_ACCOUNT_PASSWORD",
              "type": "string"
            },
            {
              "id": "login-007",
              "name": "successMarker",
              "value": "account-dashboard",
              "type": "string"
            },
            {
              "id": "login-008",
              "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": "99999999-9999-9999-9999-999999999922",
      "name": "Set Login Config [Schedule]"
    },
    {
      "parameters": {
        "operation": "GeeTest V4",
        "websiteURL": "={{ $json.websiteURL }}",
        "captchaId": "={{ $json.captchaId }}"
      },
      "type": "n8n-nodes-capsolver.capSolver",
      "typeVersion": 1,
      "position": [
        -32,
        0
      ],
      "id": "99999999-9999-9999-9999-999999999923",
      "name": "Solve GeeTest V4 [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": "={{ $('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 }}"
            },
            {
              "name": "captcha_id",
              "value": "={{ $('Solve GeeTest V4 [Schedule]').item.json.data.solution.captcha_id }}"
            },
            {
              "name": "lot_number",
              "value": "={{ $('Solve GeeTest V4 [Schedule]').item.json.data.solution.lot_number }}"
            },
            {
              "name": "pass_token",
              "value": "={{ $('Solve GeeTest V4 [Schedule]').item.json.data.solution.pass_token }}"
            },
            {
              "name": "gen_time",
              "value": "={{ $('Solve GeeTest V4 [Schedule]').item.json.data.solution.gen_time }}"
            },
            {
              "name": "captcha_output",
              "value": "={{ $('Solve GeeTest V4 [Schedule]').item.json.data.solution.captcha_output }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": true
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        272,
        0
      ],
      "id": "99999999-9999-9999-9999-999999999924",
      "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": "99999999-9999-9999-9999-999999999925",
      "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": "99999999-9999-9999-9999-999999999926",
      "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": "99999999-9999-9999-9999-999999999927",
      "name": "Mark Login Failed [Schedule]"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "account-login-geetest-v4",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -640,
        420
      ],
      "id": "99999999-9999-9999-9999-999999999928",
      "name": "Webhook Trigger",
      "webhookId": "99999999-aaaa-bbbb-cccc-999999999928",
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "operation": "GeeTest V4",
        "websiteURL": "={{ $json.body.websiteURL }}",
        "captchaId": "={{ $json.body.captchaId }}"
      },
      "type": "n8n-nodes-capsolver.capSolver",
      "typeVersion": 1,
      "position": [
        -32,
        420
      ],
      "id": "99999999-9999-9999-9999-999999999929",
      "name": "Solve GeeTest V4 [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' }}"
            }
          ]
        },
        "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 }}"
            },
            {
              "name": "captcha_id",
              "value": "={{ $json.data.solution.captcha_id }}"
            },
            {
              "name": "lot_number",
              "value": "={{ $json.data.solution.lot_number }}"
            },
            {
              "name": "pass_token",
              "value": "={{ $json.data.solution.pass_token }}"
            },
            {
              "name": "gen_time",
              "value": "={{ $json.data.solution.gen_time }}"
            },
            {
              "name": "captcha_output",
              "value": "={{ $json.data.solution.captcha_output }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": true
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        272,
        420
      ],
      "id": "99999999-9999-9999-9999-999999999930",
      "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": "99999999-9999-9999-9999-999999999931",
      "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": "99999999-9999-9999-9999-999999999932",
      "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": "99999999-9999-9999-9999-999999999933",
      "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": "99999999-9999-9999-9999-999999999934",
      "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 GeeTest V4 [Schedule]",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Solve GeeTest V4 [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 GeeTest V4 [Webhook]",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Solve GeeTest V4 [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 GeeTest V4-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 GeeTest V4 using a webhook-based workflow
  • Use-case examples — scraping and account login — showing how to submit the 5 solved fields and process protected data
  • How to identify GeeTest V4 parameters — the static captchaId found in page source
  • Key differences from V3 — no dynamic challenge fetch needed, making V4 structurally simpler to automate

The key takeaway: solving the GeeTest V4 challenge is only half the job — you also need to submit all 5 solution fields (captcha_id, lot_number, pass_token, gen_time, captcha_output) 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!

CapSolver bonus code banner

Frequently Asked Questions

What is GeeTest V4?

GeeTest V4 is the latest generation of GeeTest's behavioral CAPTCHA system. It verifies visitors using adaptive challenges and behavioral analysis, replacing the older V3 system with a simplified integration model. From a solving perspective, V4 requires only a static captchaId parameter — no dynamic challenge fetching needed.

How much does it cost to solve a GeeTest V4 challenge?

Pricing varies based on usage. Check the CapSolver pricing page for current GeeTest V4 rates.

How long does it take to solve a GeeTest V4 challenge?

GeeTest V4 challenges are typically solved in a few seconds. The exact time depends on server load and challenge complexity.

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 captchaId for a website?

Search the page source for captcha_id or captchaId, or look for references to gcaptcha4.js (the GeeTest V4 widget script). The captchaId is static — find it once, use it forever.

What is the difference between GeeTest V3 and V4?

GeeTest V3 requires fetching a dynamic challenge parameter before each solve (via the gt and challenge fields), and returns 3 solution fields. GeeTest V4 uses a static captchaId that never changes, requires no dynamic challenge fetch, and returns 5 solution fields (captcha_id, lot_number, pass_token, gen_time, captcha_output). V4 is structurally simpler to automate.

CapSolver returned a solution but the website still rejected it — why?

Several things can cause this. First, solutions expire quickly — make sure you're submitting the 5 fields immediately after solving. Second, verify you're sending all 5 fields: captcha_id, lot_number, pass_token, gen_time, and captcha_output — missing any one of them will cause rejection. Third, check the field names and submission format: inspect the actual network request the browser makes (DevTools > Network tab) to confirm the exact field names, request method, and endpoint. Some sites expect the fields in a JSON body rather than form-urlencoded. If the solution 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