A standalone captcha-solving model: the
CaptchaKraken-Lora-v1.2
adapter merged into Qwen/Qwen3.5-9B and quantized to FP8-dynamic. One
download, no adapter to wire up.
These are the weights our hosted API answers with.
Twilight is the stronger of two hardware tiers.
Sunlight v1.2
is the same merge at AWQ 4-bit, ~5 GB smaller and lighter on VRAM.
Weights: 13 GB (measured) · Min VRAM: ~22 GB
Quantized: language-model linears at FP8 (channel-wise weights, per-token
dynamic activations). The vision tower, the linear-attention projections and
the multi-token-prediction head stay bf16 — the task is reading a small
picture accurately, and quantizing the half that does the reading costs more
than it saves. FP8-dynamic needs no calibration data.
What changed since v1.1
v1.1 solved reCAPTCHA and hCaptcha. v1.2 solves everything the generators
cover — 44 puzzle types across 10 vendors, and it is the first generation to
handle animated challenges and typed text captchas at all.
This model answers generation-2 prompts. Every v1.1 model is generation 1,
and sending this one a generation-1 prompt does not error — it silently
degrades on every puzzle. Clients before 2.5.0 hardcode generation-1 text and
have no way to know otherwise.
1vllm serve CaptchaKraken/Twilight-v1.2-FP8 \2 --max-model-len 8192 --gpu-memory-utilization 0.85 --trust-remote-code --port 800034exportVLLM_BASE_URL=http://localhost:8000/v1
5exportCAPTCHA_KRAKEN_API_KEY=EMPTY
6exportCAPTCHA_LORA_NAME=CaptchaKraken/Twilight-v1.2-FP8 # must match the served name
No --enable-lora and no adapter flags — the adapter is already merged in.
Three things to get right, or it scores far below what it can
Send the prompts it was trained on.prompts.json in this repo carries
them plus the puzzle-type → template mapping. A mismatched prompt does not
error, it collapses accuracy.
Disable thinking — chat_template_kwargs: {"enable_thinking": false}.
With thinking on and a qwen3 reasoning parser, the answer goes to
reasoning and content comes back empty.
Serve it at a flat 720² pixel budget — MIN_PIXELS=518400,
MAX_PIXELS=518400. Qwen clamps each image's AREA into that band, and the
band decides how many visual tokens the model reads a puzzle from. This one
was measured, not guessed: see below.
Coordinates come back normalized 0–1000, top-left (0,0), bottom-right
(1000,1000) — not pixels. Grid screenshots must be sent with cell numbers
drawn on them; the model reads those labels and was never trained to invent a
numbering. The shipped client does all of this for you.
Evaluation
Scored with the project's soft-tolerance grader on the full 1458-sample
held-out real eval — every hand-labelled real capture we hold, none of it
trained on. Grid puzzles are exact tile-set match with per-error decay;
click/drag receive partial credit by normalized distance, so these are graded
scores, not "percent solved".
Vendor
Puzzle types
Held-out samples
Score
reCAPTCHA
2
629
0.600
hCaptcha
26
539
0.543
GeeTest
7
172
0.780
NetEase Yidun
3
37
0.775
BotDetect
1
28
0.929
Tencent
1
11
0.829
Prosopo
1
11
0.727
Yandex
1
11
0.364
Lemin
1
10
0.874
MTCaptcha
1
10
0.900
Overall
44
1458
0.6155
Training run 20260812-005302, verdict ready-to-deploy — passed all three
gates uncapped.
These figures are the unquantized adapter's. FP8 tracked the served
base+adapter setup within noise at v1.1 (66.87% vs 66.30% on the eval current
then), so the merge is not expected to cost anything here either — but the v1.2
quantization delta has not been measured on its own yet, and this note stays
until it has.
v1.1's numbers are not comparable to these. They were taken on a
156-sample eval that predates the 2026-08-05 split fix, when part of the real
capture set was still in training.
Why 720², and why not the ViT's native grid
Sweeping the serving floor over 448/576/640/704/720/736/768/896/1024² (full
1458-sample eval per arm, run-to-run noise ±0.001) put the plateau at 704–736²:
floor
patch grid on a 400×580 capture
overall
4×4 exact
448²
23×33
0.6115
0.390
640²
33×48
0.6357
0.425
720²
37×53
0.6412
0.406
768²
39×57
0.6368
0.449
1024²
53×77
0.6243
0.370
+3.0 points overall and reCAPTCHA 3×3 exact 0.648 → 0.715. num_position_embeddings: 2304
is 48×48 patches = 768² for a square image, but real captures are 400×580
portrait, so 768² of area already puts the long side at 57 patches. The area
that saturates the grid exactly is 640² — and it scores worse. Mild
position-embedding extrapolation plus real pixels beats staying inside the
grid; it falls apart past ~67 patches. Floor == ceiling, so every image arrives
at one size and the band cannot drift.
License
CaptchaKraken Source-Available License v1.1 — see LICENSE.
Use it, modify it, build commercially on it where captcha solving is an
internal component of a product that delivers value beyond the solve — scrapers,
anti-detection browsers, automation frameworks, QA and accessibility tooling.
You may not sell the solve: no reselling or offering for a fee a captcha
solving service or API whose primary value is solving captchas, no thin
wrappers exposing this model's solving capability, and no relaying its outputs
through a paid or public captcha-solving API. Those require a separate written
commercial agreement.
Copyright (c) 2026 CaptchaKraken LLC. All rights reserved.