REST API reference
Self-hosted captcha solver over HTTP. Base URL public:
https://ircaptcha.isrealllairdrop.net
· local: http://127.0.0.1:8877
Authentication
Bearer token enforced at nginx on the public domain. Localhost has no auth.
| Scope | Auth | Notes |
|---|---|---|
GET /, /health, /docs, /redoc, /openapi.json, /api-docs |
Public | Dashboard, liveness, interactive docs |
POST /solve, GET /status, GET /logs |
Bearer required | Missing/invalid token → 403 |
# Header on every protected call Authorization: Bearer <SOLVER_TOKEN> # Token lives on the server (chmod 600), not in this page: # /root/projects/captcha-solver/.solver-token.env
Dashboard stores the token in localStorage on your browser only. Never commit or paste the raw token into chat logs.
Endpoints
All JSON. Content-Type for POST: application/json.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /health |
public | Liveness + supported types |
| GET | /status |
Bearer | Per-type online map + in-flight jobs |
| GET | /logs?lines=50 |
Bearer | Recent solve events (ring buffer, max 100 kept; lines 1–200) |
| POST | /solve |
Bearer | Solve captcha — dispatch by type |
| GET | /docs |
public | Swagger UI (Try it out + Authorize) |
| GET | /redoc |
public | ReDoc reference |
| GET | /openapi.json |
public | Raw OpenAPI schema |
POST /solve — body fields
Required fields depend on type. SSRF guard rejects private/loopback URLs unless SOLVER_ALLOW_PRIVATE=1.
| Field | Type | Used by | Notes |
|---|---|---|---|
type | string | all | Required. Dispatch key. |
sitekey | string | turnstile / recaptcha / hcaptcha | Required for widget types. Not used by page-level types. |
url | string | most | Page / origin. Required except botguard/perimeterx/aliyun defaults. |
action | string | turnstile / recaptcha / hcaptcha | reCAPTCHA action; hCaptcha "invisible" selects invisible path. |
cdata | string | turnstile | Customer data bound into token. |
real_page | bool | turnstile / recaptcha / hcaptcha | Drive live target page instead of stub. |
timeout_s | int | all | Deadline seconds (default 60). Expiry → HTTP 408. |
proxy | string | cloudflare / awswaf / datadome / px / akamai / … | scheme://user:pass@host:port. Cookie solvers are IP-bound. |
pre_actions | array | real_page / page-level | [{type, selector, value, timeout}] — click/fill/select/press/wait |
post_fetch | array | real_page | Same-session API calls after solve. Use __TOKEN__ placeholder. |
version | string | recaptcha | v2 | v3 | invisible (default v2) |
enterprise | bool | recaptcha | Load enterprise.js |
secret | string | recaptcha v3 | Optional site secret to also return score |
verify_url / verify_payload | — | turnstile | Solve-and-verify from same session |
email / password | string | botguard | Google OAuth flow token harvest |
referer | string | datadome | Framing referer for correct config |
render_flow | string | perimeterx | Default outlook_signup |
scene_id / prefix / region | string | aliyun | Required scene_id + prefix; region sgp|cn|intl |
public_key | string | arkose | Required. Arkose site public key from target embed. |
url / page_url | string | arkose | Page that must fire /fc/gfct/ (either field accepted). |
game_type | string | arkose | Optional hint (default 4). Live type still comes from gfct. |
Arkose: surl / max_waves are not request fields (older docs were wrong). Service URL auto-detects from gfct; waves capped internally at 10. Multi-wave solves often need timeout_s 90–120.
Captcha types
Pass as type on POST /solve.
| type | Needs | Returns (success) | Status |
|---|---|---|---|
turnstile | sitekey + url | token | PASS |
recaptcha | sitekey + url (+ version) | token (+ score if secret) | MIXED — v3 OK · v2 image fail |
hcaptcha | sitekey + url | token | PASS |
cloudflare | url (+ proxy) | cf_clearance + cookies + UA | PASS |
awswaf | url (+ proxy) | aws-waf-token / cookies | PASS |
botguard | email (+ password optional) | bgRequest token + cookies | PASS |
datadome | url + referer (+ proxy) | datadome cookie | PASS |
perimeterx | proxy (+ render_flow) | _px3 | PASS |
akamai | url (+ proxy) | _abck | PASS |
aliyun | scene_id + prefix | token_obj / token JSON | PASS |
arkose | public_key + url/page_url | token (fc_token) + variant + waves | MIXED — models 23/24 · full E2E needs real gfct page |
Honest matrix: reCAPTCHA v2 image is still failing on the free path. Arkose ONNX pack is production-ready for classify (23/24 variants from funcaptchamodel.unix.do); full token harvest needs a live target that fires /fc/gfct/ — public demos usually do not. Missing model: threed_rollball_animal.onnx.
Response contract
Two rules cover every response. Never mix them.
HTTP 200 — solve ran
{
"type": "turnstile",
"solved": true,
"token": "…",
"method": "route",
"elapsed": 4.1
}
Read solved. Failures that still ran are 200 with solved:false + error.
4xx / 5xx — request never solved
{
"detail": "url is required"
}
No solved field. See error table below.
cURL examples
Replace $TOKEN. Do not hardcode secrets in scripts that get committed.
# Health (public) curl -sS https://ircaptcha.isrealllairdrop.net/health # Status (Bearer) curl -sS https://ircaptcha.isrealllairdrop.net/status \ -H "Authorization: Bearer $TOKEN" # Logs (last 20) curl -sS "https://ircaptcha.isrealllairdrop.net/logs?lines=20" \ -H "Authorization: Bearer $TOKEN" # Turnstile curl -sS -X POST https://ircaptcha.isrealllairdrop.net/solve \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "type": "turnstile", "sitekey": "0x4AAAAAAA…", "url": "https://target.com" }' # reCAPTCHA v3 Enterprise curl -sS -X POST https://ircaptcha.isrealllairdrop.net/solve \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "type": "recaptcha", "version": "v3", "enterprise": true, "sitekey": "6Lc…", "url": "https://target.com", "action": "login" }' # Cloudflare clearance (IP-bound — pass proxy) curl -sS -X POST https://ircaptcha.isrealllairdrop.net/solve \ -H "Authorization: Bearer ***" \ -H "Content-Type: application/json" \ -d '{ "type": "cloudflare", "url": "https://protected.example.com", "proxy": "http://user:pass@host:port", "timeout_s": 60 }' # Arkose FunCaptcha — needs real page that fires /fc/gfct/ (placeholder will fail honestly) curl -sS -X POST https://ircaptcha.isrealllairdrop.net/solve \ -H "Authorization: Bearer ***" \ -H "Content-Type: application/json" \ -d '{ "type": "arkose", "public_key": "A0DE7B75-1138-44F2-B132-ED188CEB66F3", "url": "https://login.example.com/login", "timeout_s": 120 }' # Local (no Bearer needed on :8877) curl -sS -X POST http://127.0.0.1:8877/solve \ -H "Content-Type: application/json" \ -d '{"type":"turnstile","sitekey":"0x4AAAAAAA…","url":"https://target.com"}'
Errors
| Code | When |
|---|---|
400 | Unsupported type, missing sitekey/url/scene_id, SSRF-blocked host |
403 | Public domain without valid Bearer (nginx) |
408 | Exceeded timeout_s |
422 | Body failed schema validation |
500 | Unhandled solver crash |
Operator notes
- Cookie solvers (cloudflare, awswaf, datadome, perimeterx, akamai): replay from the same proxy IP + matching UA/TLS when possible.
- Success signal: always read top-level
solved— do not branch only ontoken(cloudflare usescf_clearance). - Interactive docs: open /docs, click Authorize, paste Bearer, then Try it out. Operator HTML: /api-docs.
- Dashboard: / →
/uistores token in localStorage and calls the same REST endpoints. - Arkose: models from
funcaptchamodel.unix.do(23/24 loadable). No public full-E2E demo. Seearkose/README.md. - Scope: solver harvests tokens/cookies only — account creation / form recon is the caller's job.