captchaforge
Automatic CAPTCHA detection and multi-strategy solving for
chromiumoxide-driven headless
browsers — Cloudflare Turnstile, reCAPTCHA v2/v3, hCaptcha, image
grids, audio challenges, sliders.
Part of the Santh security research ecosystem. Beta — used in production by wafrift and golemn-browser but the public API may shift before 1.0. Pin the version in
Cargo.toml.
Quick start
Add to Cargo.toml:
[]
= { = "https://github.com/santhsecurity/captchaforge", = "main" }
= "0.9"
= { = "1", = ["full"] }
Detect + solve on the page your headless browser is on:
use ;
async
Strategies
The default chain tries strategies in order; the first one that succeeds wins. Each result is recorded in a per-domain pattern store so repeat visits prefer the strategy that worked last time.
- Behavioural — realistic mouse movement + timing for Turnstile
and reCAPTCHA v3. Solvers verify the response token is actually
present before reporting
success. - Vision-LLM — screenshot the challenge, hand it to a multimodal
model (Ollama
qwen3-vl:30bout of the box, configurable), parse the model's grid / click answer, simulate the mouse. - Audio bypass — click the accessibility audio challenge, run STT, type the transcribed answer, then verify the reCAPTCHA token was accepted.
- Crowd-sourced pattern memory — track which strategy succeeded per-domain and re-prioritise the solver order on next visit.
- Human fallback — return unsolved with a base64 JPEG screenshot
in
CaptchaSolveResult::screenshotso a downstream human-in-the-loop can finish.
You can plug in your own solver by implementing the
CaptchaSolver trait and adding it to the chain via
chain.add_solver(...) before default_chain() strategies.
Detection coverage
Out of the box detect::detect recognises:
- Cloudflare Turnstile (
.cf-turnstile,[data-turnstile-sitekey],script[src*="challenges.cloudflare.com"]) - Cloudflare bot interstitial ("Just a moment",
#challenge-form) - reCAPTCHA v2 + v3 (
.g-recaptcha,[data-sitekey],script[src*="google.com/recaptcha"]) - hCaptcha (
.h-captcha,[data-hcaptcha-sitekey],script[src*="hcaptcha.com"]) - Image grids, audio challenges, sliders (when the surrounding code
classifies them via
DetectedCaptcha::*)
Adding a new family is one match arm in detect.rs plus a JavaScript
selector. PRs welcome.
Configuration
VLM endpoint and model are runtime-overridable on VlmCaptchaSolver:
use ;
let mut chain = empty;
chain.add_solver;
Audio STT endpoint is similarly configurable on AudioCaptchaSolver.
Origin and licensing
Extracted from golemn-browser (originally GPL-3.0). The original author (Santh Project) re-licensed the extracted slice as MIT OR Apache-2.0 so it can be embedded in MIT/Apache-licensed downstream tools (notably wafrift for managed-WAF challenge handling and any future Santh tool that needs a captcha layer).
Testing
The test suite does not require a real chromium binary or a real
Ollama server — all chromium-bound paths are pure Rust unit tests
against the JavaScript / Rust glue layer. Tests that exercise the
real headless browser live in
wafrift-captchaforge-bridge
where the chromium runtime is available.
License
MIT OR Apache-2.0 at your option. Copyright 2026 CORUM COLLECTIVE LLC.