Skip to main content Skills Marketplace Discover and explore AI skills built by the community.
Related occupations SOC
Based on SOC occupation classification
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Copy promptShow prompt details A direct command skips the review prompt. Inspect the source before running it.
npx skills add https://github.com/johnalbertini14-glitch/openclaw-skills --skill capmonsterThe command stays on one line. Scroll horizontally to inspect it before copying.
Prefer a local copy? Download the files currently available to SkillsMP.
Download Zip Downloading... More from this repository name capmonster description Solve CAPTCHAs (reCAPTCHA v2/v3, hCaptcha, Cloudflare Turnstile, image CAPTCHAs) using CapMonster Cloud API. Use when browser automation encounters CAPTCHA challenges.
CapMonster Cloud CAPTCHA Solver
Solve CAPTCHAs programmatically via CapMonster Cloud API during browser automation.
API Info
Base URL : https://api.capmonster.cloud
API Key : ${CAPMONSTER_API_KEY}
Docs : https://docs.capmonster.cloud/
Python Client : tools/capmonster-cloud/capmonster_api.py
Pricing (per 1000 solves)
Type Price Avg Time reCAPTCHA v2 $0.60 10-30s reCAPTCHA v3 $0.90 5-15s hCaptcha $1.50 10-30s Cloudflare Turnstile $1.20 5-15s Image CAPTCHA $0.04 2-5s
Quick Reference
Check Balance
curl -s -X POST https://api.capmonster.cloud/getBalance \
-H "Content-Type: application/json" \
-d '{"clientKey": "${CAPMONSTER_API_KEY}"}' | jq .balance
Using Python Client
import sys
sys.path.insert(0 , '/Users/eason/clawd/tools/capmonster-cloud' )
capmonster_api CapMonsterClient
client = CapMonsterClient( )
( )
token = client.solve_recaptcha_v2(
website_url= ,
website_key=
)
from
import
"${CAPMONSTER_API_KEY}"
print
f"Balance: ${client.get_balance()} "
"https://example.com/page-with-captcha"
"6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
Complete Workflow: Browser Automation + CAPTCHA Solving
Step 1: Detect CAPTCHA on Page Take a browser snapshot and check for CAPTCHA indicators:
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);
})()"
}
Step 2: Extract Site Key
document .querySelector ('[data-sitekey]' )?.dataset .sitekey
document .querySelector ('iframe[src*="recaptcha"]' )?.src .match (/k=([^&]+)/ )?.[1 ]
window .___grecaptcha_cfg ?.clients ?.[0 ]?.Y ?.Y ?.sitekey
document .querySelector ('script[src*="recaptcha/api.js?render="]' )?.src .match (/render=([^&]+)/ )?.[1 ]
window .___grecaptcha_cfg ?.clients ?.[0 ]?.Y ?.Y ?.sitekey
document .querySelector ('[data-hcaptcha-sitekey], .h-captcha[data-sitekey]' )?.dataset .sitekey ||
document .querySelector ('[data-hcaptcha-sitekey]' )?.getAttribute ('data-hcaptcha-sitekey' )
document .querySelector ('.cf-turnstile[data-sitekey], [data-turnstile-sitekey]' )?.dataset .sitekey
Step 3: Submit to CapMonster API
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 "
import sys
sys.path.insert(0 , '/Users/eason/clawd/tools/capmonster-cloud' )
from capmonster_api import CapMonsterClient
client = CapMonsterClient("${CAPMONSTER_API_KEY}" )
token = client.solve_recaptcha_v2(
website_url="https://scholar.google.com/" ,
website_key="EXTRACTED_SITEKEY"
)
token = client.solve_recaptcha_v3(
website_url="https://example.com/" ,
website_key="EXTRACTED_SITEKEY" ,
min_score=0.7 ,
page_action="submit"
)
token = client.solve_hcaptcha(
website_url="https://example.com/" ,
website_key="EXTRACTED_SITEKEY"
)
token = client.solve_turnstile(
website_url="https://example.com/" ,
website_key="EXTRACTED_SITEKEY"
)
Step 4: Poll 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\": \"${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().
Step 5: Inject Solution into Page
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';
})()"
}
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';
})()"
}
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';
})()"
}
Step 6: Submit the Form After injecting the token, submit the form:
browser action=act profile=chrome request={"kind" :"click" ,"ref" :"submit button ref" }
browser action=act profile=chrome request={
"kind" : "evaluate" ,
"fn" : "document.querySelector('form').submit()"
}
Google Scholar Specific Google Scholar uses invisible reCAPTCHA v2 that triggers on suspicious activity.
Detection
const isBlocked = document .body .textContent .includes ('unusual traffic' ) ||
document .body .textContent .includes ('我們的系統' ) ||
!!document .querySelector ('iframe[src*="recaptcha"]' );
Extract Site Key
const iframe = document .querySelector ('iframe[src*="recaptcha"]' );
const sitekey = iframe?.src .match (/k=([^&]+)/ )?.[1 ];
Solve and Submit import sys
sys.path.insert(0 , '/Users/eason/clawd/tools/capmonster-cloud' )
from capmonster_api import CapMonsterClient
client = CapMonsterClient("${CAPMONSTER_API_KEY}" )
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.
Image CAPTCHA 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}" )
text = client.solve_image_captcha(image_path="/tmp/captcha.png" )
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} " )
All-in-One Shell Script Save as solve-recaptcha.sh:
#!/bin/bash
API_KEY="${CAPMONSTER_API_KEY} "
WEBSITE_URL="$1 "
SITEKEY="$2 "
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 "
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
Troubleshooting
Token Invalid / Expired
Tokens expire in ~2 minutes
Inject and submit immediately after receiving
Make sure websiteURL matches the actual page URL
ERROR_CAPTCHA_UNSOLVABLE
Retry 2-3 times
Check if sitekey is correct
Page may have additional protections
ERROR_RECAPTCHA_TIMEOUT
Network issue between CapMonster and target
Try again, or use proxy version (RecaptchaV2Task)
Token Injected but Form Fails
Site may validate token server-side with IP check
Try using proxy version with your IP
Some sites need callback to be triggered
Finding the Callback
JSON .stringify (___grecaptcha_cfg, (k, v ) => typeof v === 'function' ? '[Function]' : v, 2 )
document .querySelector ('[data-callback]' )?.dataset .callback
Best Practices
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
Cost Estimation Use Case CAPTCHAs/day Monthly Cost Light (research) 10 ~$0.18 Medium (scraping) 100 ~$1.80 Heavy (automation) 1000 ~$18.00
Current balance is ~$10, good for ~16,000 reCAPTCHA v2 solves.