Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Solve CAPTCHAs (reCAPTCHA v2/v3, hCaptcha, Cloudflare Turnstile, image CAPTCHAs) using CapMonster Cloud API. Use when browser automation encounters CAPTCHA c...
Solve CAPTCHAs (reCAPTCHA v2/v3, hCaptcha, Cloudflare Turnstile, image CAPTCHAs) using CapMonster Cloud API. Use when browser automation encounters CAPTCHA c...
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.
Solve CAPTCHAs programmatically via CapMonster Cloud API during browser automation.
Base URL: https://api.capmonster.cloud API Key: ${CAPMONSTER_API_KEY} Docs: https://docs.capmonster.cloud/ Python Client: tools/capmonster-cloud/capmonster_api.py
TypePriceAvg TimereCAPTCHA v2$0.6010-30sreCAPTCHA v3$0.905-15shCaptcha$1.5010-30sCloudflare Turnstile$1.205-15sImage CAPTCHA$0.042-5s
curl -s -X POST https://api.capmonster.cloud/getBalance \ -H "Content-Type: application/json" \ -d '{"clientKey": "${CAPMONSTER_API_KEY}"}' | jq .balance
import sys sys.path.insert(0, '/Users/eason/clawd/tools/capmonster-cloud') from capmonster_api import CapMonsterClient client = CapMonsterClient("${CAPMONSTER_API_KEY}") # Check balance print(f"Balance: ${client.get_balance()}") # Solve reCAPTCHA v2 token = client.solve_recaptcha_v2( website_url="https://example.com/page-with-captcha", website_key="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-" )
Take a browser snapshot and check for CAPTCHA indicators: // Via browser action=act evaluate browser action=act profile=chrome request={ "kind": "evaluate", "fn": "(() => { const indicators = { recaptchaV2: !!document.querySelector('.g-recaptcha, [data-sitekey], iframe[src*=\"recaptcha\"]'), recaptchaV3: !!document.querySelector('script[src*=\"recaptcha/api.js?render=\"]'), hcaptcha: !!document.querySelector('.h-captcha, [data-hcaptcha-sitekey], iframe[src*=\"hcaptcha\"]'), turnstile: !!document.querySelector('.cf-turnstile, [data-sitekey], iframe[src*=\"turnstile\"]') }; return JSON.stringify(indicators); })()" }
reCAPTCHA v2: // Option A: From data-sitekey attribute document.querySelector('[data-sitekey]')?.dataset.sitekey // Option B: From iframe src document.querySelector('iframe[src*="recaptcha"]')?.src.match(/k=([^&]+)/)?.[1] // Option C: From grecaptcha object window.___grecaptcha_cfg?.clients?.[0]?.Y?.Y?.sitekey reCAPTCHA v3: // From script src document.querySelector('script[src*="recaptcha/api.js?render="]')?.src.match(/render=([^&]+)/)?.[1] // Or from grecaptcha config window.___grecaptcha_cfg?.clients?.[0]?.Y?.Y?.sitekey hCaptcha: document.querySelector('[data-hcaptcha-sitekey], .h-captcha[data-sitekey]')?.dataset.sitekey || document.querySelector('[data-hcaptcha-sitekey]')?.getAttribute('data-hcaptcha-sitekey') Cloudflare Turnstile: document.querySelector('.cf-turnstile[data-sitekey], [data-turnstile-sitekey]')?.dataset.sitekey
Using curl (shell): # Create task TASK_ID=$(curl -s -X POST https://api.capmonster.cloud/createTask \ -H "Content-Type: application/json" \ -d '{ "clientKey": "${CAPMONSTER_API_KEY}", "task": { "type": "RecaptchaV2TaskProxyless", "websiteURL": "https://scholar.google.com/", "websiteKey": "SITEKEY_HERE" } }' | jq -r .taskId) echo "Task ID: $TASK_ID" Using Python: import sys sys.path.insert(0, '/Users/eason/clawd/tools/capmonster-cloud') from capmonster_api import CapMonsterClient client = CapMonsterClient("${CAPMONSTER_API_KEY}") # For reCAPTCHA v2 token = client.solve_recaptcha_v2( website_url="https://scholar.google.com/", website_key="EXTRACTED_SITEKEY" ) # For reCAPTCHA v3 token = client.solve_recaptcha_v3( website_url="https://example.com/", website_key="EXTRACTED_SITEKEY", min_score=0.7, page_action="submit" # Check page source for action name ) # For hCaptcha token = client.solve_hcaptcha( website_url="https://example.com/", website_key="EXTRACTED_SITEKEY" ) # For Turnstile token = client.solve_turnstile( website_url="https://example.com/", website_key="EXTRACTED_SITEKEY" )
Using curl: # Poll until ready (max 120 seconds) for i in {1..60}; do RESULT=$(curl -s -X POST https://api.capmonster.cloud/getTaskResult \ -H "Content-Type: application/json" \ -d "{\"clientKey\": \"${CAPMONSTER_API_KEY}\", \"taskId\": $TASK_ID}") STATUS=$(echo "$RESULT" | jq -r .status) if [ "$STATUS" = "ready" ]; then TOKEN=$(echo "$RESULT" | jq -r '.solution.gRecaptchaResponse // .solution.token') echo "Token: $TOKEN" break fi echo "Status: $STATUS, waiting..." sleep 2 done The Python client handles polling automatically with solve_and_wait().
reCAPTCHA v2/v3: // Via browser evaluate browser action=act profile=chrome request={ "kind": "evaluate", "fn": "(() => { const token = 'CAPMONSTER_TOKEN_HERE'; // Method 1: Set textarea value (most common) const textarea = document.querySelector('#g-recaptcha-response, [name=\"g-recaptcha-response\"]'); if (textarea) { textarea.value = token; textarea.style.display = 'block'; // Some sites hide it } // Method 2: Also set any iframe response document.querySelectorAll('iframe[src*=\"recaptcha\"]').forEach(iframe => { try { const doc = iframe.contentDocument || iframe.contentWindow.document; const ta = doc.querySelector('#g-recaptcha-response'); if (ta) ta.value = token; } catch(e) {} }); // Method 3: Trigger callback if exists if (typeof ___grecaptcha_cfg !== 'undefined') { const clients = ___grecaptcha_cfg.clients; for (let cid in clients) { const client = clients[cid]; // Find callback const callback = client?.Y?.Y?.callback || client?.Y?.callback; if (typeof callback === 'function') { callback(token); } } } return 'Token injected'; })()" } hCaptcha: browser action=act profile=chrome request={ "kind": "evaluate", "fn": "(() => { const token = 'CAPMONSTER_TOKEN_HERE'; // Set response textarea const textarea = document.querySelector('[name=\"h-captcha-response\"], [name=\"g-recaptcha-response\"]'); if (textarea) textarea.value = token; // Trigger callback if (typeof hcaptcha !== 'undefined') { // Find widget ID const widget = document.querySelector('.h-captcha'); const widgetId = widget?.dataset.hcaptchaWidgetId || 0; // Some sites have custom callbacks } return 'hCaptcha token injected'; })()" } Cloudflare Turnstile: browser action=act profile=chrome request={ "kind": "evaluate", "fn": "(() => { const token = 'CAPMONSTER_TOKEN_HERE'; // Set the hidden input const input = document.querySelector('[name=\"cf-turnstile-response\"]'); if (input) input.value = token; // Also set any callback data attribute const container = document.querySelector('.cf-turnstile'); if (container && container.dataset.callback) { const callbackName = container.dataset.callback; if (typeof window[callbackName] === 'function') { window[callbackName](token); } } return 'Turnstile token injected'; })()" }
After injecting the token, submit the form: // Click submit button browser action=act profile=chrome request={"kind":"click","ref":"submit button ref"} // Or trigger form submission browser action=act profile=chrome request={ "kind": "evaluate", "fn": "document.querySelector('form').submit()" }
Google Scholar uses invisible reCAPTCHA v2 that triggers on suspicious activity.
// Check if blocked const isBlocked = document.body.textContent.includes('unusual traffic') || document.body.textContent.includes('ๆๅ็็ณป็ตฑ') || !!document.querySelector('iframe[src*="recaptcha"]');
// Scholar's recaptcha iframe const iframe = document.querySelector('iframe[src*="recaptcha"]'); const sitekey = iframe?.src.match(/k=([^&]+)/)?.[1]; // Usually: 6LfwuyUTAAAAAOAmoS0fdqijC2PbbdH4kjq62Y1b
import sys sys.path.insert(0, '/Users/eason/clawd/tools/capmonster-cloud') from capmonster_api import CapMonsterClient client = CapMonsterClient("${CAPMONSTER_API_KEY}") # Scholar's known sitekey (may change) token = client.solve_recaptcha_v2( website_url="https://scholar.google.com/scholar?q=test", website_key="6LfwuyUTAAAAAOAmoS0fdqijC2PbbdH4kjq62Y1b" ) print(f"Token: {token[:50]}...") Then inject via browser automation.
For traditional image CAPTCHAs (text recognition): import base64 import sys sys.path.insert(0, '/Users/eason/clawd/tools/capmonster-cloud') from capmonster_api import CapMonsterClient client = CapMonsterClient("${CAPMONSTER_API_KEY}") # From file text = client.solve_image_captcha(image_path="/tmp/captcha.png") # From base64 with open("/tmp/captcha.png", "rb") as f: b64 = base64.b64encode(f.read()).decode() text = client.solve_image_captcha(image_base64=b64) print(f"CAPTCHA text: {text}")
Save as solve-recaptcha.sh: #!/bin/bash # Usage: ./solve-recaptcha.sh <website_url> <sitekey> API_KEY="${CAPMONSTER_API_KEY}" WEBSITE_URL="$1" SITEKEY="$2" # Create task echo "Creating task..." RESPONSE=$(curl -s -X POST https://api.capmonster.cloud/createTask \ -H "Content-Type: application/json" \ -d "{ \"clientKey\": \"$API_KEY\", \"task\": { \"type\": \"RecaptchaV2TaskProxyless\", \"websiteURL\": \"$WEBSITE_URL\", \"websiteKey\": \"$SITEKEY\" } }") TASK_ID=$(echo "$RESPONSE" | jq -r .taskId) ERROR_ID=$(echo "$RESPONSE" | jq -r .errorId) if [ "$ERROR_ID" != "0" ]; then echo "Error: $(echo "$RESPONSE" | jq -r .errorDescription)" exit 1 fi echo "Task ID: $TASK_ID" # Poll for result echo "Waiting for solution..." for i in {1..60}; do RESULT=$(curl -s -X POST https://api.capmonster.cloud/getTaskResult \ -H "Content-Type: application/json" \ -d "{\"clientKey\": \"$API_KEY\", \"taskId\": $TASK_ID}") STATUS=$(echo "$RESULT" | jq -r .status) if [ "$STATUS" = "ready" ]; then TOKEN=$(echo "$RESULT" | jq -r '.solution.gRecaptchaResponse') COST=$(echo "$RESULT" | jq -r '.cost') echo "โ Solved! Cost: \$$COST" echo "" echo "TOKEN:" echo "$TOKEN" exit 0 fi printf "." sleep 2 done echo "" echo "โ Timeout after 120 seconds" exit 1
Tokens expire in ~2 minutes Inject and submit immediately after receiving Make sure websiteURL matches the actual page URL
Retry 2-3 times Check if sitekey is correct Page may have additional protections
Network issue between CapMonster and target Try again, or use proxy version (RecaptchaV2Task)
Site may validate token server-side with IP check Try using proxy version with your IP Some sites need callback to be triggered
// Check grecaptcha config for callback JSON.stringify(___grecaptcha_cfg, (k, v) => typeof v === 'function' ? '[Function]' : v, 2) // Or check data-callback attribute document.querySelector('[data-callback]')?.dataset.callback
Extract sitekey fresh - Don't hardcode, sites may rotate Use correct URL - Must match the page showing CAPTCHA Inject quickly - Tokens expire in ~120 seconds Check for v3 - Some sites use v3 (invisible), need pageAction Monitor balance - Set up low-balance alerts Retry on failure - CapMonster may fail occasionally
Use CaseCAPTCHAs/dayMonthly CostLight (research)10~$0.18Medium (scraping)100~$1.80Heavy (automation)1000~$18.00 Current balance is ~$10, good for ~16,000 reCAPTCHA v2 solves.
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.