capmonster
Solve CAPTCHAs (reCAPTCHA v2/v3, hCaptcha, Cloudflare Turnstile, image CAPTCHAs) using CapMonster Cloud API. Use when browser automation encounters CAPTCHA challenges.
安装 / 下载方式
TotalClaw CLI推荐
totalclaw install clawskills:clawskills~easonc13-capmonstercURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/clawskills%3Aclawskills~easonc13-capmonster/file -o easonc13-capmonster.md# 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
```bash
curl -s -X POST https://api.capmonster.cloud/getBalance \
-H "Content-Type: application/json" \
-d '{"clientKey": "${CAPMONSTER_API_KEY}"}' | jq .balance
```
### Using Python Client
```python
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-"
)
```
---
## Complete Workflow: Browser Automation + CAPTCHA Solving
### Step 1: Detect CAPTCHA on Page
Take a browser snapshot and check for CAPTCHA indicators:
```javascript
// 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);
})()"
}
```
### Step 2: Extract Site Key
**reCAPTCHA v2:**
```javascript
// 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:**
```javascript
// 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:**
```javascript
document.querySelector('[data-hcaptcha-sitekey], .h-captcha[data-sitekey]')?.dataset.sitekey ||
document.querySelector('[data-hcaptcha-sitekey]')?.getAttribute('data-hcaptcha-sitekey')
```
**Cloudflare Turnstile:**
```javascript
document.querySelector('.cf-turnstile[data-sitekey], [data-turnstile-sitekey]')?.dataset.sitekey
```
### Step 3: Submit to CapMonster API
**Using curl (shell):**
```bash
# 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:**
```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"
)
```
### Step 4: Poll for Solution
**Using curl:**
```bash
# 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()`.
### Step 5: Inject Solution into Page
**reCAPTCHA v2/v3:**
```javascript
// 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:**
```javascript
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:**
```javascript
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:
```javascript
// 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 Specific
Google Scholar uses **invisible reCAPTCHA v2*