Loading...
Loading...
Solve CAPTCHAs in automated browser sessions using third-party solving services. Use this skill whenever you need to: bypass a CAPTCHA while automating a website, integrate CAPTCHA solving into a Playwright or Puppeteer script, solve reCAPTCHA v2 or v3, hCaptcha, Cloudflare Turnstile, or image-based CAPTCHAs, automate a login or form submission that's blocked by a CAPTCHA, test a page that has CAPTCHA challenges, or write a script that needs to pass a CAPTCHA programmatically. Also triggers for: "recaptcha", "hcaptcha", "turnstile", "captcha solving", "bypass captcha", "solve captcha", "pass captcha challenge", "automate past captcha", "get past robot check", "bot verification". Always use this skill for any CAPTCHA-related automation — even simple cases benefit from correct token injection patterns.
npx skill4agent add biggora/claude-plugins-registry captchaPage with CAPTCHA
│
├─ 1. Extract sitekey + page URL
├─ 2. Submit to solving service (waits 15–45s)
├─ 3. Receive token string
├─ 4. Inject token into hidden field on page
├─ 5. Trigger the CAPTCHA callback
└─ 6. Submit form / continue automation| Type | | How to detect on page |
|---|---|---|
| reCAPTCHA v2 (checkbox) | | |
| reCAPTCHA v2 invisible | | No visible widget; |
| reCAPTCHA v3 | | |
| hCaptcha | | |
| Cloudflare Turnstile | | |
| Image/text CAPTCHA | | |
references/captcha-types.md| Service | Flag | Speed | Cost/1K |
|---|---|---|---|
| 2captcha (recommended) | | 20–40s | ~$1.00 |
| CapMonster Cloud | | 10–30s | ~$0.60 |
| Anti-Captcha | | 15–35s | ~$0.70 |
export CAPTCHA_API_KEY=your_key_here
export CAPTCHA_SERVICE=2captchareferences/services.md# From your project directory — adjust path to match your skill install location
cp ~/.claude/plugins/captcha/scripts/solve_captcha.py ./solve_captcha.pypip installpython solve_captcha.py \
--type recaptcha-v2 \
--sitekey 6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ- \
--pageurl https://www.google.com/recaptcha/api2/demo \
--api-key $CAPTCHA_API_KEY
# → {"success": true, "token": "03AGdBq25...", "type": "recaptcha-v2"}import json, os, subprocess, sys
from playwright.sync_api import sync_playwright
SOLVER = "solve_captcha.py" # must be in same directory or on PATH
def solve(captcha_type, sitekey, pageurl, service=None):
cmd = [sys.executable, SOLVER,
"--type", captcha_type,
"--sitekey", sitekey,
"--pageurl", pageurl]
if service:
cmd += ["--service", service]
result = subprocess.run(cmd, capture_output=True, text=True, env=os.environ)
data = json.loads(result.stdout)
if not data["success"]:
raise RuntimeError(data["error"])
return data["token"]
PAGE_URL = "https://www.google.com/recaptcha/api2/demo"
SITEKEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
# Step 1: start solving (this takes 15–40s) — do it BEFORE opening the browser
token = solve("recaptcha-v2", SITEKEY, PAGE_URL)
# Step 2: now launch and navigate — solve is already done or finishing
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto(PAGE_URL)
# Step 3: inject token — use json.dumps() for safe JS interpolation
import json as _json
token_js = _json.dumps(token)
page.evaluate(f"""
const token = {token_js};
const el = document.querySelector('[name="g-recaptcha-response"]');
if (el) {{ el.value = token; }}
if (window.___grecaptcha_cfg) {{
Object.values(window.___grecaptcha_cfg.clients || {{}}).forEach(c => {{
Object.keys(c).forEach(k => {{
if (c[k]?.callback) c[k].callback(token);
}});
}});
}}
""")
page.click('#recaptcha-demo-submit')
browser.close()Important: Always usewhen embedding a token in JS — never bare f-string interpolation likejson.dumps(token). Token strings are base64url-safe today but the pattern is fragile.'{token}'
page.evaluatebrowser_evaluate(() => {
const q = s => document.querySelector(s);
if (q('.g-recaptcha, [data-sitekey]:not(.h-captcha):not(.cf-turnstile)'))
return { type: 'recaptcha-v2', sitekey: q('[data-sitekey]')?.dataset?.sitekey };
if (q('.h-captcha, [data-hcaptcha-sitekey]'))
return { type: 'hcaptcha', sitekey: q('[data-sitekey]')?.dataset?.sitekey };
if (q('.cf-turnstile'))
return { type: 'turnstile', sitekey: q('.cf-turnstile')?.dataset?.sitekey };
if (q('img[src*="captcha" i], img[alt*="captcha" i]'))
return { type: 'image' };
return { type: null };
})();grecaptcha.execute('SITEKEY', {action: 'ACTION_NAME'})solve_captcha.py# reCAPTCHA v2
python solve_captcha.py --type recaptcha-v2 --sitekey SITEKEY --pageurl URL
# reCAPTCHA v3
python solve_captcha.py --type recaptcha-v3 --sitekey SITEKEY --pageurl URL --action verify
# hCaptcha
python solve_captcha.py --type hcaptcha --sitekey SITEKEY --pageurl URL
# Cloudflare Turnstile
python solve_captcha.py --type turnstile --sitekey SITEKEY --pageurl URL
# Image CAPTCHA (send screenshot of the captcha image)
python solve_captcha.py --type image --image captcha_screenshot.pngreferences/captcha-types.md// 1. Set the hidden response field
document.querySelector('[name="g-recaptcha-response"]').value = TOKEN;
// 2. Trigger the registered callback
if (window.___grecaptcha_cfg) {
Object.values(window.___grecaptcha_cfg.clients || {}).forEach(client => {
Object.keys(client).forEach(key => {
if (client[key]?.callback) client[key].callback(TOKEN);
});
});
}solve_image_grid.pyRequirements: pip install anthropic (or openai as fallback)
Environment: ANTHROPIC_API_KEY or OPENAI_API_KEYCheckbox clicked
│
├─ Grid appeared? → screenshot grid cells → ask vision AI → click matching cells
│ → click Verify
│ → new round? → repeat
└─ No grid (trusted IP) → returns True immediatelyfrom playwright.sync_api import sync_playwright
from solve_image_grid import solve_image_grid # copy from scripts/
with sync_playwright() as p:
page = p.chromium.launch(headless=False).new_page()
page.goto("https://www.google.com/recaptcha/api2/demo")
# Step 1: click the checkbox (inside its iframe)
page.frame_locator('iframe[title="reCAPTCHA"]') \
.locator('.recaptcha-checkbox-border').click()
# Step 2: handle grid if it appears (returns immediately if no grid)
solved = solve_image_grid(page)
if solved:
page.click('#recaptcha-demo-submit')import json, os, subprocess, sys
from solve_image_grid import solve_image_grid
SOLVER = "solve_captcha.py"
SITEKEY = "your-sitekey"
# 1. Click checkbox — may or may not trigger a grid
page.frame_locator('iframe[title="reCAPTCHA"]') \
.locator('.recaptcha-checkbox-border').click()
# 2. Solve grid if it appeared
grid_ok = solve_image_grid(page)
# 3. If the form still needs a token (check for g-recaptcha-response being empty)
token_empty = page.evaluate(
"document.querySelector('[name=\"g-recaptcha-response\"]')?.value === ''"
)
if grid_ok and token_empty:
result = subprocess.run(
[sys.executable, SOLVER, "--type", "recaptcha-v2",
"--sitekey", SITEKEY, "--pageurl", page.url],
capture_output=True, text=True, env=os.environ
)
token = json.loads(result.stdout)["token"]
token_js = json.dumps(token)
page.evaluate(f"""
const t = {token_js};
document.querySelector('[name="g-recaptcha-response"]').value = t;
if (window.___grecaptcha_cfg)
Object.values(window.___grecaptcha_cfg.clients||{{}}).forEach(c=>
Object.keys(c).forEach(k=>{{ if(c[k]?.callback) c[k].callback(t) }})
);
""")frame_locator().locator('td').nth(i)max_rounds=6[]mcp__plugin_playwright_playwright__*1. browser_navigate → go to the page
2. browser_evaluate → run detection JS to find CAPTCHA type and sitekey
3. Bash → python scripts/solve_captcha.py ... (takes 15-40s)
4. browser_evaluate → inject token + trigger callback
5. browser_click → submit button
6. browser_snapshot → verify success| Problem | Cause | Fix |
|---|---|---|
| Token injection has no effect | Response field is hidden/disabled | Make it visible: |
| CAPTCHA reappears after submit | Token expired (>2 min) | Solve and inject immediately before submitting |
| No credits on service | Top up account at service dashboard |
| Solver backed up or reCAPTCHA v3 hard | Retry or switch service; for v3 try increasing |
| Callback not triggered | Site uses custom callback name | Search page source for |
| CAPTCHA passes but site still blocks | Browser fingerprint flagged as bot | Read |
| 2captcha returns wrong text (image) | Low quality image | Crop to just the CAPTCHA, increase contrast before sending |
scripts/solve_captcha.pyscripts/solve_image_grid.pyreferences/captcha-types.mdreferences/services.mdreferences/stealth.md