Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Read this skill when a page has a CAPTCHA that needs solving (reCAPTCHA, Turnstile, hCaptcha, or image CAPTCHA).
.claude/skills/kunanonj-aside-captcha-solver/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | -29% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 45% | 0% |
| case-01 | ✗→✓ | ▲ Improved | -28% | 0% |
| case-04 | ✗→✓ | ▲ Improved | -58% | 0% |
| case-05 | ✗→✓ | ▲ Improved | -36% | 0% |
Use the captcha global in REPL. Three methods: click, drag, readText. All return a snapshot tree so you can verify visually.
js// 1. Find widget bounds via snapshot / evaluate const s = await snapshot(page); const bounds = await page.evaluate(`(() => { const el = document.querySelector('iframe'); if (!el) return null; const r = el.getBoundingClientRect(); return { x: r.x, y: r.y, width: r.width, height: r.height }; })()`); // 2. Click and check result const tree = await captcha.click(page, bounds); // tree = post-click snapshot — check if widget shows checkmark / "verified"
js// Drag from the slider handle to the target position const tree = await captcha.drag(page, { x: 150, y: 300 }, { x: 450, y: 300 }); // tree = post-drag snapshot — check if puzzle solved // With more granular steps for precision const tree = await captcha.drag(page, from, to, { steps: 40 });
js// OCR the CAPTCHA image region const text = await captcha.readText(page, { x: 100, y: 200, width: 200, height: 60 }); // → "xK7m2" // Or OCR the full page (if bounds unknown) const text = await captcha.readText(page); // Then fill the input await page.locator('input').fill(text);
captcha.click(page?, bounds): Promise<string>Click within bounds (left-center), wait 3s, return snapshot tree.
captcha.drag(page?, from, to, opts?): Promise<string>Drag between two viewport coordinates. opts.steps controls smoothness (default 20). Returns snapshot tree.
captcha.readText(page?, bounds?): Promise<string | null>Screenshot (optionally clipped to bounds), OCR via vision model, return the text.
page.mouse.click(x, y) reach themannotatedScreenshot() if you need to visually inspect the CAPTCHA stateannotatedScreenshot() + vision to identify cells, then click each one| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-03 | fail→pass | 13,039 | 3,698 | -72% | 1 | 1 | 0% | 1,887 | 1,338 | -29% | 0 | 0 | — |
case-02 | fail→pass | 7,900 | 6,245 | -21% | 1 | 1 | 0% | 1,209 | 1,749 | +45% | 0 | 0 | — |
case-01 | fail→pass | 14,741 | 8,788 | -40% | 1 | 1 | 0% | 1,882 | 1,352 | -28% | 0 | 0 | — |
case-04 | fail→pass | 15,843 | 3,247 | -80% | 1 | 1 | 0% | 2,903 | 1,224 | -58% | 0 | 0 | — |
case-05 | fail→pass | 11,355 | 3,127 | -72% | 1 | 1 | 0% | 2,031 | 1,305 | -36% | 0 | 0 | — |
case-06 | fail→fail | 10,254 | 1,533 | -85% | 1 | 1 | 0% | 1,684 | 828 | -51% | 0 | 0 | — |
case-07 | fail→pass | 6,076 | 1,731 | -72% | 1 | 1 | 0% | 954 | 930 | -3% | 0 | 0 | — |
case-08 | fail→pass | 10,003 | 1,169 | -88% | 1 | 1 | 0% | 1,962 | 782 | -60% | 0 | 0 | — |
case-09 | fail→pass | 13,054 | 1,201 | -91% | 1 | 1 | 0% | 1,914 | 776 | -59% | 0 | 0 | — |
case-10 | fail→pass | 12,647 | 3,081 | -76% | 1 | 1 | 0% | 2,033 | 1,157 | -43% | 0 | 0 | — |
case-11 | pass→pass | 13,237 | 10,061 | -24% | 1 | 1 | 0% | 2,412 | 2,133 | -12% | 0 | 0 | — |
case-12 | pass→pass | 8,659 | 4,824 | -44% | 1 | 1 | 0% | 1,565 | 1,000 | -36% | 0 | 0 | — |
case-13 | fail→pass | 3,974 | 1,144 | -71% | 1 | 1 | 0% | 672 | 751 | +12% | 0 | 0 | — |
case-14 | fail→pass | 6,257 | 2,658 | -58% | 1 | 1 | 0% | 1,249 | 1,153 | -8% | 0 | 0 | — |
case-15 | fail→pass | 5,367 | 1,695 | -68% | 1 | 1 | 0% | 1,151 | 904 | -21% | 0 | 0 | — |
case-16 | fail→pass | 12,238 | 4,861 | -60% | 1 | 1 | 0% | 2,326 | 1,376 | -41% | 0 | 0 | — |
case-17 | pass→fail | 6,633 | 3,060 | -54% | 1 | 1 | 0% | 1,476 | 838 | -43% | 0 | 0 | — |
case-18 | fail→pass | 3,359 | 2,264 | -33% | 1 | 1 | 0% | 564 | 1,011 | +79% | 0 | 0 | — |
case-19 | fail→pass | 8,020 | 1,767 | -78% | 1 | 1 | 0% | 1,367 | 882 | -35% | 0 | 0 | — |
case-20 | pass→pass | 6,856 | 5,859 | -15% | 1 | 1 | 0% | 1,644 | 1,619 | -2% | 0 | 0 | — |
case-21 | pass→pass | 3,996 | 3,195 | -20% | 1 | 1 | 0% | 822 | 1,067 | +30% | 0 | 0 | — |
case-22 | pass→pass | 7,241 | 3,662 | -49% | 1 | 1 | 0% | 1,300 | 1,391 | +7% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +64 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.