Tutorials

GeeTest Token Injection in Browser Automation Frameworks

GeeTest v3 returns three values after solving: geetest_challenge, geetest_validate, and geetest_seccode. Injecting these correctly into a browser automation session requires understanding where the site expects them — hidden form fields, JavaScript callbacks, or XHR payloads. Here's how to do it in each major framework.

What You're Injecting

CaptchaAI returns a three-part result:

{
  "geetest_challenge": "a1b2c3d4e5...modified_challenge",
  "geetest_validate": "abc123def456_validate",
  "geetest_seccode": "abc123def456_validate|jordan"
}

All three values must be injected. Missing any one causes verification failure.

Step 1: Extract Parameters and Solve

Common to all frameworks — extract gt and challenge, then solve with CaptchaAI:

import requests
import time

def solve_geetest(gt, challenge, page_url):
    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": "YOUR_API_KEY",
        "method": "geetest",
        "gt": gt,
        "challenge": challenge,
        "pageurl": page_url,
        "json": 1
    })
    task_id = resp.json()["request"]

    for _ in range(60):
        time.sleep(3)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": "YOUR_API_KEY",
            "action": "get",
            "id": task_id,
            "json": 1
        })
        data = result.json()
        if data["status"] == 1:
            return data["request"]  # Returns dict with three values
    raise TimeoutError("GeeTest solve timed out")

Step 2: Inject in Playwright (Python)

Extract Parameters

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()

    # Capture GeeTest registration response
    geetest_data = {}
    def capture_geetest(response):
        if "register" in response.url and response.status == 200:
            try:
                data = response.json()
                if "gt" in data and "challenge" in data:
                    geetest_data.update(data)
            except Exception:
                pass

    page.on("response", capture_geetest)
    page.goto("https://example.com/login")
    page.wait_for_selector(".geetest_holder")

    gt = geetest_data["gt"]
    challenge = geetest_data["challenge"]

Inject Solution

    # Solve with CaptchaAI
    solution = solve_geetest(gt, challenge, page.url)

    # Method 1: Set hidden form fields
    page.evaluate(f"""
        const fields = {{
            'geetest_challenge': '{solution["geetest_challenge"]}',
            'geetest_validate': '{solution["geetest_validate"]}',
            'geetest_seccode': '{solution["geetest_seccode"]}'
        }};
        for (const [name, value] of Object.entries(fields)) {{
            let input = document.querySelector(`input[name="${{name}}"]`);
            if (!input) {{
                input = document.createElement('input');
                input.type = 'hidden';
                input.name = name;
                document.querySelector('form').appendChild(input);
            }}
            input.value = value;
        }}
    """)

    # Submit the form
    page.click("#submit-button")

Method 2: Trigger the GeeTest Callback

Some sites use GeeTest's JavaScript callback instead of form fields:

    page.evaluate(f"""
        // Find the GeeTest captcha object
        if (window.captchaObj) {{
            // Simulate a successful solve
            const result = {{
                geetest_challenge: '{solution["geetest_challenge"]}',
                geetest_validate: '{solution["geetest_validate"]}',
                geetest_seccode: '{solution["geetest_seccode"]}'
            }};

            // Override getValidate to return our solution
            window.captchaObj.getValidate = function() {{ return result; }};

            // Trigger the success callback
            const successEvent = new Event('geetest_success');
            document.dispatchEvent(successEvent);
        }}
    """)

Step 3: Inject in Puppeteer (JavaScript)

const puppeteer = require('puppeteer');

async function solveAndInject() {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();

  // Capture GeeTest params
  let gt, challenge;
  page.on('response', async (response) => {
    if (response.url().includes('register') && response.status() === 200) {
      try {
        const data = await response.json();
        if (data.gt && data.challenge) {
          gt = data.gt;
          challenge = data.challenge;
        }
      } catch (e) {}
    }
  });

  await page.goto('https://example.com/login');
  await page.waitForSelector('.geetest_holder');

  // Solve with CaptchaAI (implementation from earlier)
  const solution = await solveCaptcha(gt, challenge, page.url());

  // Inject the three values
  await page.evaluate((sol) => {
    // Set hidden inputs
    const form = document.querySelector('form');
    ['geetest_challenge', 'geetest_validate', 'geetest_seccode'].forEach(name => {
      let input = document.querySelector(`input[name="${name}"]`);
      if (!input) {
        input = document.createElement('input');
        input.type = 'hidden';
        input.name = name;
        form.appendChild(input);
      }
      input.value = sol[name];
    });
  }, solution);

  await page.click('#submit-button');
}

Step 4: Inject in Selenium (Python)

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("https://example.com/login")

# Wait for GeeTest widget
WebDriverWait(driver, 15).until(
    EC.presence_of_element_located((By.CLASS_NAME, "geetest_holder"))
)

# Extract gt and challenge from the page
gt = driver.execute_script(
    "return document.querySelector('[data-gt]')?.dataset.gt"
)
challenge = driver.execute_script(
    "return document.querySelector('[data-challenge]')?.dataset.challenge"
)

# Solve with CaptchaAI
solution = solve_geetest(gt, challenge, driver.current_url)

# Inject via JavaScript
driver.execute_script(f"""
    var fields = {{
        'geetest_challenge': '{solution["geetest_challenge"]}',
        'geetest_validate': '{solution["geetest_validate"]}',
        'geetest_seccode': '{solution["geetest_seccode"]}'
    }};
    var form = document.querySelector('form');
    for (var name in fields) {{
        var input = document.querySelector('input[name="' + name + '"]');
        if (!input) {{
            input = document.createElement('input');
            input.type = 'hidden';
            input.name = name;
            form.appendChild(input);
        }}
        input.value = fields[name];
    }}
""")

driver.find_element(By.ID, "submit-button").click()

Handling XHR-Based Submissions

Some sites submit GeeTest results via XHR instead of form POST. Intercept and modify the request:

# Playwright: Intercept the XHR and inject values
def handle_route(route):
    if "login" in route.request.url and route.request.method == "POST":
        # Modify the POST data to include our solution
        post_data = route.request.post_data
        # Add GeeTest values to the request
        route.continue_(post_data=modified_data)
    else:
        route.continue_()

page.route("**/api/login**", handle_route)

Troubleshooting

Issue Cause Fix
"GeeTest validation failed" Missing one of the three values Verify all three values are injected
Challenge expired before injection Too long between extraction and solve Extract and solve in quick succession
Form submits but values not included Wrong field names or form selector Inspect the actual form to find correct names
Callback not triggered Site uses a custom callback name Find the callback in the initGeetest options
Values injected but widget still shows Widget state not updated Trigger the success callback programmatically

FAQ

Do I need to visually hide the GeeTest widget after injection?

No. The widget's visual state doesn't affect the form submission. As long as the three values are in the form data, the server validates them regardless of the widget's appearance.

Can I inject GeeTest values without a browser?

Yes, if the site accepts a direct HTTP POST with the three values. Intercept the form submission endpoint and send the values via requests or any HTTP client.

Why does GeeTest use three separate values instead of one token?

The three values serve different purposes: geetest_challenge tracks the session, geetest_validate proves the challenge was solved, and geetest_seccode provides a hash for tamper detection.

Next Steps

Inject GeeTest solutions in any framework — get your CaptchaAI API key and start solving.

Full Working Code

Complete runnable examples for this article in Python, Node.js, PHP, Go, Java, C#, Ruby, Rust, Kotlin & Bash.

View on GitHub →

Discussions (0)

No comments yet.

Related Posts

API Tutorials Solve GeeTest v3 CAPTCHA with Python and CaptchaAI
Step-by-step Python tutorial for solving Gee Test v 3 slide puzzle CAPTCHAs using the Captcha AI API.

Step-by-step Python tutorial for solving Gee Test v 3 slide puzzle CAPTCHAs using the Captcha AI API. Includes...

Automation Python Testing
Mar 23, 2026
Troubleshooting CaptchaAI Wrong CAPTCHA Type Error: How to Fix
Fix wrong CAPTCHA type errors when using Captcha AI.

Fix wrong CAPTCHA type errors when using Captcha AI. Learn how to identify the correct CAPTCHA type on a page...

Automation Python reCAPTCHA v2
Feb 28, 2026
Troubleshooting GeeTest v3 Error Codes: Complete Troubleshooting Reference
Complete reference for Gee Test v 3 error codes — from registration failures to validation errors — with causes, fixes, and Captcha AI-specific troubleshooting.

Complete reference for Gee Test v 3 error codes — from registration failures to validation errors — with cause...

Automation Testing GeeTest v3
Apr 08, 2026
Tutorials Pytest Fixtures for CaptchaAI API Testing
Build reusable pytest fixtures to test CAPTCHA-solving workflows with Captcha AI.

Build reusable pytest fixtures to test CAPTCHA-solving workflows with Captcha AI. Covers mocking, live integra...

Automation Python reCAPTCHA v2
Apr 08, 2026
Use Cases Government Portal Automation with CAPTCHA Solving
Automate government portal interactions (visa applications, permit filings, records requests) with Captcha AI handling CAPTCHA challenges.

Automate government portal interactions (visa applications, permit filings, records requests) with Captcha AI...

Automation Python reCAPTCHA v2
Jan 30, 2026
Tutorials Browser Console CAPTCHA Detection: Finding Sitekeys and Parameters
Use browser Dev Tools to detect CAPTCHA types, extract sitekeys, and find parameters needed for Captcha AI API requests.

Use browser Dev Tools to detect CAPTCHA types, extract sitekeys, and find all parameters needed for Captcha AI...

Automation reCAPTCHA v2 Cloudflare Turnstile
Mar 25, 2026
Use Cases Multi-Step Checkout Automation with CAPTCHA Solving
Automate multi-step e-commerce checkout flows that include CAPTCHA challenges at cart, payment, or confirmation stages using Captcha AI.

Automate multi-step e-commerce checkout flows that include CAPTCHA challenges at cart, payment, or confirmatio...

Automation Python reCAPTCHA v2
Mar 21, 2026
Integrations Selenium Wire + CaptchaAI: Request Interception for CAPTCHA Solving
Complete guide to using Selenium Wire for request interception, proxy routing, and automated CAPTCHA solving with Captcha AI in Python.

Complete guide to using Selenium Wire for request interception, proxy routing, and automated CAPTCHA solving w...

Python reCAPTCHA v2 Cloudflare Turnstile
Mar 13, 2026
Explainers How GeeTest v3 CAPTCHA Works
how Gee Test v 3 CAPTCHA works.

Learn how Gee Test v 3 CAPTCHA works. Understand slide puzzles, icon challenges, the verification flow, and ho...

Automation Testing GeeTest v3
Feb 13, 2026
Tutorials Handling Multiple CAPTCHAs on a Single Page
how to detect and solve multiple CAPTCHAs on a single web page using Captcha AI.

Learn how to detect and solve multiple CAPTCHAs on a single web page using Captcha AI. Covers multi-iframe ext...

Python reCAPTCHA v2 Cloudflare Turnstile
Apr 09, 2026
Tutorials Discord Webhook Alerts for CAPTCHA Pipeline Status
Send CAPTCHA pipeline alerts to Discord — webhook integration for balance warnings, error spikes, queue status, and daily summary reports with Captcha AI.

Send CAPTCHA pipeline alerts to Discord — webhook integration for balance warnings, error spikes, queue status...

Automation Python All CAPTCHA Types
Apr 09, 2026
Tutorials Backpressure Handling in CAPTCHA Solving Queues
Prevent CAPTCHA queue overflows with backpressure — bounded queues, load shedding, and adaptive concurrency for Captcha AI pipelines.

Prevent CAPTCHA queue overflows with backpressure — bounded queues, load shedding, and adaptive concurrency fo...

Automation Python All CAPTCHA Types
Jan 19, 2026