One could write, “Experienced developers working on parsing and automation often face the need to bypass modern CAPTCHAs.” But that’s too boring… I’d rather start like this—continuing to explore the amusing world of CAPTCHAs, I finally stumbled upon the Chinese variant of protection: the GeeTest CAPTCHA. Let’s break down what this beast is, where it dwells, and why you should (or shouldn’t) fear it… You’ll understand as we go!
GeeTest is one of the advanced anti-bot systems combining user puzzles with behavioral analysis. I decided to take a close look at recognizing the GeeTest CAPTCHA under real-world conditions and figure out how to bypass GeeTest with various methods. But first—a classic introduction (which, by the way, may be more interesting than the practical part of the article, since bypassing the GeeTest CAPTCHA is already a non-trivial task for many readers).

What Is GeeTest and Why Is This CAPTCHA Difficult (You Need Know it For Successful Bypass Geetest)?
GeeTest (developer: Chinese company GeeTest) is a modern CAPTCHA system designed to protect websites from bots. Unlike classic “Enter the characters from the image,” GeeTest emphasizes interactive puzzles: for example, the user must slide a puzzle piece or solve a mini-game. Meanwhile, the system analyzes user behavior (mouse movements, solving speed, clicks) and collects extensive device information (so‑called device fingerprint
). All of this complicates automatic recognition.
The hallmark of GeeTest is adaptivity: when the system suspects a bot, the challenges become harder. For instance, a genuine user may only see a simple one-step slider, whereas suspicious traffic will get a series of complex tasks. Such multi-level protection greatly raises the bar for bots.
Key reasons why bypassing GeeTest can be fatal for some scripts:
Interactive challenges. You must emulate real interactions (dragging the slider, clicking objects, etc.), not just recognize text or move a slider from point A to B.
Behavioral analysis. GeeTest tracks cursor trajectory, pauses, movement sharpness, attempts, and more. Atypical “robotic” behavior leads to failure.
Device fingerprinting. The CAPTCHA gathers browser/system data: User-Agent, screen resolution, installed plugins, fonts, time zone, Canvas/WebGL fingerprint, and more. If these look suspicious (e.g., typical of an automated browser), the system may either escalate the challenge or block the attempt entirely.
Obfuscation and server‑side validation. GeeTest scripts are heavily obfuscated (especially in v4), and final answers are verified server‑side via tokens. You can’t simply guess the puzzle position—you must correctly form the response that the server will accept.
Thus, GeeTest poses a serious challenge for developers in parsing and automation. Yet, there are still ways to bypass this CAPTCHA—let’s explore them next.
GeeTest v3 vs. v4: CAPTCHA Evolution (Differents with Bypassing)
GeeTest has undergone several iterations, with versions v3 and v4 being the most widespread. Understanding their differences is crucial for choosing a bypass method.
GeeTest v3 (classic version) presents a visible CAPTCHA (most often a slider puzzle). Initialization uses two parameters in the page’s code:
gt
– the site ID in the GeeTest system (public key).challenge
– a unique challenge string for the current session.
Typically, the page loads
gt.js
from the GeeTest server, and solving it triggers requests like/get.php
and/validate.php
. Version 3 supports several challenge types: Slide CAPTCHA (slider puzzle), Icon CAPTCHA (select/drag icons), Space CAPTCHA, etc.GeeTest v4 (Adaptive CAPTCHA) is the newer, more flexible version with invisible modes. Key differences:
Instead of
gt + challenge
, it uses a singlecaptcha_id
(analogous togt
), and all other parameters are passed in aninitParameters
object during initialization. In practice, the frontend callsinitGeetest4
with an options object wherecaptcha_id
is primary.Scripts load from paths containing
/v4/
(e.g.,gcaptcha4.js
), which is evident in traffic analysis.Adaptivity: v4 dynamically adjusts difficulty. If a user seems “clean,” the CAPTCHA may run in silent mode (barely noticeable). v4 features a NoCaptcha mode with a single “Verify” button—background checks have already confirmed human traffic. For suspicious users, v4 will impose a series of tough trials.
The v4 protocol is more complex: user interaction data is packaged and encrypted before sending to the server. In v4, the parameter w is an encrypted “answer” containing all user actions, timestamps, etc., calculated in an obfuscated script, making it hard to forge without replicating the full logic.
To detect the version on a site, inspect the page code and network requests: if you see gt
and challenge
, it’s v3; if the CAPTCHA loads via gcaptcha4.geetest.com
with captcha_id
, it’s v4. For example, a typical v4 load URL:
https://gcaptcha4.geetest.com/load?captcha_id=<ID>&challenge=<UUID>
Here, captcha_id
is the key, and a dynamic challenge
is generated per case. In v3, you usually find challenge
directly in the HTML or initialization data.
Types of GeeTest Challenges: Slider, Icons, “Fifteen Puzzle,” and Mini‑Games - Smart Bypass GeeTest
Over the years, GeeTest has introduced a variety of challenge types. Here are the main ones a developer might encounter:
Slide CAPTCHA (slider puzzle). The classic GeeTest: an image with a missing fragment and a separate puzzle piece. The user must drag the slider so the piece fits perfectly into the gap. Although it looks simple, the system evaluates how smoothly and human‑like you moved the piece. Bot task: determine the offset of the cutout and simulate human cursor movement. Slide CAPTCHA appears in both v3 and v4 (it remains the most common challenge).

Click/Icon CAPTCHA. The user sees images or icons and must click all that meet the prompt (e.g., “Find all the cats among these pictures”) or drag icons to match their shadows. GeeTest records click coordinates and timing. In v3, Icon CAPTCHA was rarer; in v4 it’s been technically enhanced.

IconCrush CAPTCHA. A v4‑specific type: a grid of icons similar to a “match‑three” game, where the user must select three identical icons in a row. It’s a mini‑game requiring image‑analysis to identify identical elements—challenging for bots.

Gobang CAPTCHA. Named after the game “五子棋” (Gobang/five‑in‑a‑row). The user places stones on a board trying to get five in a row. This simple puzzle is used under high suspicion. For a bot, solving Gobang means either fully simulating gameplay (non‑trivial) or avoiding reaching this stage by passing earlier, easier challenges.

Space CAPTCHA. Mentioned in v3 docs, likely another click‑based task: place objects into correct “spaces” or slots. Details are scarce; I haven’t personally encountered a clear example, nor found precise illustrations. The goal is similar: verify dynamic user actions when positioning objects.
NoCAPTCHA (OneTap). Like reCAPTCHA v2 Checkbox: the user simply clicks “I’m not a robot.” Behind the scenes, GeeTest conducts extensive checks—behavioral analysis, fingerprints, hidden JavaScript tests, maybe even Proof‑of‑Work. If everything looks legitimate, one click suffices; otherwise, a full challenge (slider or other) may appear. NoCAPTCHA is common for real users; for us, it means v4 may show no visible puzzle if traffic seems human.

GeeTest continually experiments. Other types (e.g., Image CAPTCHA—reordering image fragments—or audio CAPTCHA for vision‑impaired users) may appear. The above are the most known and illustrative from a bypass perspective.
How GeeTest Identifies Bots: Behavior and Fingerprints - Making Bypass GeeTest Easier
Before exploring solutions, it’s vital to understand which signals GeeTest uses to distinguish bots from humans. This knowledge helps you emulate human behavior convincingly (or reveals the difficulty if you lack the skill).
Behavioral Analysis
Every interaction stage is tracked. For sliders, the system logs cursor trajectory (X/Y coordinates every millisecond), jerks, pauses. A movement that’s too straight, without micro‑oscillations, looks scripted. Teleporting the cursor or constant speed also flags a bot. Reaction time matters: humans won’t start dragging the slider in the exact millisecond the widget loads, but bots might. For click CAPTCHAs, the order and speed of clicks matter. Icon CAPTCHA checks how quickly and accurately you dragged icons—too fast or too precise will raise suspicion. All data is sent to the server (partially in clear in v3, fully encrypted inside w
in v4).
Device Fingerprinting
GeeTest collects browser info via JavaScript:
Screen parameters: resolution, color depth, viewport size.
Browser data: User-Agent, presence of
webdriver
(WebDriver flag), plugin and MIME‑type lists, platform, language, time zone.Canvas/WebGL fingerprint: draws hidden content on a
<canvas>
and reads pixel data (different systems yield slightly different patterns), checks the WebGL renderer.Audio fingerprinting: creates an
AudioContext
and records minute variations in generated sound.Fonts: enumerates installed fonts hiddenly.
Together, these form a unique “fingerprint.” If a bot repeatedly presents the same fingerprint, it can be detected. Or if the fingerprint is atypical (e.g., a headless browser), the system will escalate. For example, Headless Chrome sets navigator.webdriver=true
—GeeTest checks that and can instantly harden the challenge.
Network Information (IP, Proxy)
IP address, geolocation, and proxy usage factor in. Known VPN or datacenter IPs almost always get a tougher challenge. Multiple attempts from one IP within minutes look like a botnet/script. GeeTest may share data with other anti‑bot systems or use its own IP reputation databases.
General Heuristics
Like reCAPTCHA, GeeTest uses machine learning on huge datasets, analyzing hundreds of parameters server‑side (load times, JS call order, device performance, etc.). For instance, humans can’t click ten distinct targets in 0.1 seconds or exhibit perfectly random movements—you usually twitch before starting. Bots often act too linearly. Ultimately, GeeTest computes a trust score or directly decides pass/fail. Anomalous behavior either leads to harder tasks or outright failure, regardless of a correct puzzle answer. Therefore, bypassing requires not just solving the puzzle correctly, but doing so in a convincingly human manner.
Approaches to Solving and Bypassing the GeeTest CAPTCHA
Let’s move to the most interesting part: bypass methods. There’s no one‑size‑fits‑all solution—it depends on the version, challenge type, and the site’s anti‑bot strictness. Here are several approaches you can combine:
1. Using Third‑Party Services (RuCaptcha, 2Captcha, SolveCaptcha, etc.)
The simplest path is outsourcing CAPTCHA solving to a specialized service. Services like RuCaptcha/2Captcha or SolveCaptcha employ real humans or proprietary ML models. You send the CAPTCHA parameters via API and receive a ready‑to‑use solution (tokens) to inject back into the site.
Example with 2Captcha:
You extract necessary parameters from the target page (for v3: gt
, challenge
, page URL; for v4: captcha_id
and page URL—2Captcha fetches challenge
). Then:
import requests, time
API_KEY = "YOUR_2CAPTCHA_APIKEY"
website_url = "https://example-with-captcha.com/page"
gt = "81388ea1fc187e0c335c0a8907ff2625" # gt value (v3)
challenge = "2e2f0f65240058b683cb6ea21c303eea6n" # challenge value (v3)
# 1. Send CAPTCHA task to 2Captcha
payload = {
'key': API_KEY,
'method': 'geetest',
'gt': gt,
'challenge': challenge,
'pageurl': website_url
}
resp = requests.post("http://2captcha.com/in.php", data=payload)
if resp.text.startswith("OK|"):
captcha_id = resp.text.split('|')[1]
else:
raise Exception(f"2Captcha API error: {resp.text}")
# 2. Poll for the result
result = None
result_url = f"http://2captcha.com/res.php?key={API_KEY}&action=get&id={captcha_id}"
for i in range(20):
time.sleep(5) # wait 5 seconds between polls
res = requests.get(result_url)
if res.text == "CAPCHA_NOT_READY":
continue
if res.text.startswith("OK|"):
result = res.text.split('|', 1)[1]
break
if not result:
raise Exception("Failed to get CAPTCHA solution in time")
print("GeeTest solution:", result)
For v3, the service usually returns JSON with challenge
, validate
, and seccode
. For v4, it may return a different format (e.g., a single captcha_output
token)—check the service docs.
Injection: Inject the returned values back into the page’s hidden form or call the appropriate JS callback. For v3, set the hidden fields geetest_challenge
, geetest_validate
, geetest_seccode
and submit the form. For v4, call the CAPTCHA object’s submit function or set the token.
Pros: Minimal effort, solves most CAPTCHAs in 2–20 seconds, cost ≈$0.001–$0.002 per CAPTCHA.
Cons: External dependency, potential delays, cost. Complex challenges (Gobang, IconCrush) may fail or incur extra human intervention.
Tip: Use proxyless mode if you don’t need to relay your own IP, or proxy mode to solve from your address (helps if the site ties the CAPTCHA to your IP). RuCaptcha/2Captcha support both via their GeeTestTask/GeeTestTaskProxyless methods.
Other services (e.g., SolveCaptcha) use neural nets first and fall back to humans—also paid, sometimes more economical at scale. Conceptually identical: send images or parameters, receive the answer.
Conclusion: Third‑party services are ideal for quick prototypes or small/large‑scale scraping. For full autonomy or speed, consider harder approaches.
2. Solving with OpenCV and Computer Vision Algorithms
This approach teaches your code to solve the CAPTCHA itself, especially suitable for graphic challenges like slider puzzles. The idea is to download the images, analyze them (find the cut‑out), and compute the required movement in pixels.
Common slider‑CAPTCHA case: You have two images—background with a missing piece and the puzzle fragment. Using OpenCV:
import cv2
import numpy as np
# Load images (e.g., previously downloaded)
background = cv2.imread("captcha_bg.png", 0) # background (grayscale)
template = cv2.imread("captcha_piece.png", 0) # puzzle piece
# Enhance images: apply edge detection to highlight the cut shape
bg_edges = cv2.Canny(background, 50, 150)
tpl_edges = cv2.Canny(template, 50, 150)
# Perform template matching
result = cv2.matchTemplate(bg_edges, tpl_edges, cv2.TM_CCOEFF_NORMED)
_, max_val, _, max_loc = cv2.minMaxLoc(result)
match_x, match_y = max_loc
print(f"Found insertion position: X={match_x}px, Y={match_y}px (match {max_val:.2f})")
Here, match_x
is the horizontal offset where the piece should go (vertical Y
is usually fixed). Next, you must emulate human-like slider movement using a browser automation library (Selenium, Puppeteer, Playwright):
from selenium.webdriver import ActionChains
import time, random
slider = driver.find_element(By.CSS_SELECTOR, ".geetest_slider_button")
actions = ActionChains(driver)
actions.click_and_hold(slider).perform()
distance = match_x
moved = 0
while moved < distance:
step = random.randint(5, 8)
if moved + step > distance:
step = distance - moved
actions.move_by_offset(xoffset=step, yoffset=0).perform()
moved += step
time.sleep(random.uniform(0.01, 0.03))
# Micro‑adjustments to mimic human tremor
actions.move_by_offset(xoffset=-3, yoffset=0).perform()
time.sleep(0.1)
actions.move_by_offset(xoffset=3, yoffset=0).perform()
actions.release().perform()
This script drags the slider in small, irregular steps with pauses and micro‑adjustments, emulating human motion. If done correctly, GeeTest will render the movement, validate it server‑side, and return validate/seccode
tokens.
CV can apply to other challenges too—IconCrush or Gobang—but they require more advanced image recognition or game‑logic solving. Some have resorted to building a hash-based database of all slider backgrounds: precompute offsets by matching hashes, then look up instantly.
Pros: Independence from external services, millisecond‑level solves, full control.
Cons: Maintenance overhead—must update for new designs or logic. Hard challenges (Gobang) may be impractical without deep AI work.
A hybrid strategy is powerful: try OpenCV first; if it fails or times out, fall back to 2Captcha. This balances speed, cost, and reliability.
3. Browser Automation and User Emulation (Selenium, Puppeteer)
While we used the browser above to apply the solution, some developers attempt to bypass without explicit recognition—by brute‑forcing human‑like actions in a real browser.
Example: Without OpenCV or paid services, spin up Chrome/Firefox under script control, wait for the widget, and attempt slider movements of varying lengths until success. Or for Icon CAPTCHA, inspect the DOM for hints or alt‑tags. This “hit‑and‑try” method is generally unreliable—GeeTest limits attempts and escalates on failure. Yet, it exists.
More practical is a hybrid: use Puppeteer or Selenium to open the page (ensuring full JS execution), extract gt/challenge
or captcha_id
, send to 2Captcha, then inject the result back via the browser. This addresses frontend quirks—some sites expect the CAPTCHA to be solved in the live page context.
Puppeteer sketch:
// Extract parameters
const gt = await page.evaluate(() => window.gt);
const challenge = await page.evaluate(() => window.challenge);
// Solve via API
const solveResponse = await solveGeeTest(gt, challenge, page.url());
const { challenge: ch, validate, seccode } = solveResponse;
// Inject solution back
await page.evaluate((ch, validate, seccode) => {
document.getElementById('geetest_challenge').value = ch;
document.getElementById('geetest_validate').value = validate;
document.getElementById('geetest_seccode').value = seccode;
document.querySelector('form#geetest-demo-form').submit();
}, ch, validate, seccode);
Anti‑detection is critical: plain headless Selenium/Puppeteer flags itself (navigator.webdriver
, missing plugins, unusual headers). To avoid this:
Use stealth plugins (e.g.,
puppeteer-extra-plugin-stealth
) or undetected-chromedriver.Set real User-Agent, add fake plugins, align timezone/language with proxy region.
Emulate human input events (mousemove, mousedown, small delays).
Full browser automation simulates a real user at the browser level. It consumes more resources but may be the only way against combined defenses (e.g., Cloudflare + GeeTest).
4. Reverse‑Engineering and Protocol Emulation
The most arduous—yet “sporting”—method is fully reverse-engineering GeeTest’s protocol to forge valid responses without a browser. GeeTest’s JS is obfuscated; data is encrypted. Nonetheless, enthusiasts have:
v3: Analyzed
gt.js
to understand request parameters for /validate.php, including mouse-trail checks. Early versions had flaws allowing empty or fixed tracks—these are long closed. Some bots now algorithmically generate plausible tracks server‑side without real browsers.v4: Scrutinized
gcaptcha4.js
to decipher the encrypted w payload (which packs all user actions). By dissecting the obfuscated “lotParser” and AES/RSA routines, they replicated logic in Python to produce validvalidate
tokens, bypassing the browser altogether.
However, public successes prompt countermeasures: GeeTest frequently updates obfuscation, adds fields, tweaks algorithms. Reverse-engineering is a constant arms race. Yet understanding the protocol can reveal shortcuts—e.g., direct image URLs or alternative CAPTCHA modes—leveraging system “laziness.”
In my view, reverse-engineering is for enthusiasts needing ultimate speed or control. In production, teams typically combine the first three methods and reserve pure protocol emulation as a last resort.
Anti‑Detection: Masking the Bot as a Human
Regardless of your chosen approach, the following best practices help avoid bot detection by GeeTest:
Use relevant proxies. Ideally residential or mobile IPs matching the site’s audience. Avoid public datacenter proxies. If using a solving service, ensure it uses your proxy IP to submit solutions.
Mimic real browser requests. Some anti-bot layers require solving JS challenges before the CAPTCHA. Use a full browser or replicate all headers (
Sec-Fetch-Mode
,Accept-Language
,cookies
, etc.).Harden your browser environment. Stealth plugins, undetected drivers, or anti-detect browsers (Multilogin, Dolphin{anty}, Mimic) let you create profiles with realistic fingerprints.
Generate plausible input events. Avoid linear, constant-speed mouse tracks. Use Bézier curves, random deviations, varied delays, micro‑adjustments—humans rarely move perfectly.
Respect timing. Don’t start solving immediately; wait 1–2 seconds as a human would. Insert pauses between clicks—humans don’t click five targets in one second.
Update signatures. Monitor changes: follow forums (Habr, BlackHatWorld, Reddit /r/webscraping), analyze network logs, adapt to new parameters.
Limit attempts. After 2–3 failures, rotate IP/session. For mass scraping, distribute load—avoid sending 100 solves from one IP.
By combining these strategies—third‑party APIs, OpenCV, browser automation—you can achieve reliable performance. GeeTest, like other CAPTCHAs, is a cat‑and‑mouse game: defenders add complexity, bot authors adapt. For an experienced engineer, this challenge can be engaging: computer vision, reverse-engineering, and web automation all play a part. Apply hybrid methods (browser + API or OpenCV + input emulation) to maximize success. Stay ready for GeeTest v5—until then, happy parsing and may no CAPTCHA stand in your way!