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.

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
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
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
Troubleshooting Common GeeTest v3 Errors and Fixes
Diagnose the most common Gee Test v 3 errors — stale challenge, bad parameters, validation failures — and fix them with practical troubleshooting steps.

Diagnose the most common Gee Test v 3 errors — stale challenge, bad parameters, validation failures — and fix...

Automation Testing GeeTest v3
Jan 24, 2026
Tutorials Build an Automated Testing Pipeline with CaptchaAI
Build a CI/CD testing pipeline that uses Captcha AI to handle CAPTCHAs in end-to-end tests.

Build a CI/CD testing pipeline that uses Captcha AI to handle CAPTCHAs in end-to-end tests. Covers pytest inte...

Automation Python reCAPTCHA v2
Jan 16, 2026
Tutorials CAPTCHA Handling in Mobile Apps with Appium
Handle CAPTCHAs in mobile app automation using Appium and Captcha AI — extract Web sitekeys, solve, and inject tokens on Android and i OS.

Handle CAPTCHAs in mobile app automation using Appium and Captcha AI — extract Web View sitekeys, solve, and i...

Automation Python All CAPTCHA Types
Feb 13, 2026
Tutorials Testing CaptchaAI Before Full Migration: Parallel Run Guide
Run your existing CAPTCHA provider alongside Captcha AI in parallel — compare solve rates, speed, and cost before committing to a full migration.

Run your existing CAPTCHA provider alongside Captcha AI in parallel — compare solve rates, speed, and cost bef...

Automation Python All CAPTCHA Types
Feb 02, 2026
Tutorials Solving GeeTest v3 with Python and CaptchaAI API
Complete guide to solving Gee Test v 3 CAPTCHA challenges using Python and Captcha AI API.

Complete guide to solving Gee Test v 3 CAPTCHA challenges using Python and Captcha AI API. Includes parameter...

Automation Python reCAPTCHA v3
Jan 30, 2026
Tutorials CAPTCHA Handling in Flask Applications with CaptchaAI
Integrate Captcha AI into Flask applications for automated CAPTCHA solving.

Integrate Captcha AI into Flask applications for automated CAPTCHA solving. Includes service class, API endpoi...

Automation Cloudflare Turnstile
Mar 17, 2026
Tutorials Streaming Batch Results: Processing CAPTCHA Solutions as They Arrive
Process CAPTCHA solutions the moment they arrive instead of waiting for tasks to complete — use async generators, event emitters, and callback patterns for stre...

Process CAPTCHA solutions the moment they arrive instead of waiting for all tasks to complete — use async gene...

Automation Python All CAPTCHA Types
Apr 07, 2026