A RESTful, JSON-over-HTTPS API for solving hCaptcha programmatically.
Send a sitekey and the page URL; we return a real P1_
token your client submits as h-captcha-response: the
same shape hCaptcha hands back after a human solves the challenge.
Base URL
api.nonecap.com/v1
Auth scheme
Bearer token
Content type
application/json
Captcha
hCaptcha
Image-recognition solvers produce low-trust tokens that hCaptcha
enterprise flags within seconds. NoneCap returns a finished token that
passes hCaptcha's server-side checks, so it actually authorises the
request it was issued for.
All endpoints live under https://api.nonecap.com.
HTTPS only. JSON in, JSON out. Authentication on every request.
Quickstart
Sign in to the dashboard and mint an API key (nc_live_…).
POST a solve to /v1/solves. Add ?wait=N (1-90 s) to block until the solve completes.
Inject the returned P1_ token into the target form's h-captcha-response field and submit.
Authentication
API keys are minted from the dashboard. Format: nc_live_ + 32 base64url
characters. Send on every request:
Authorization: Bearer nc_live_a8f2K9...
Errors
401 unauthorized: missing, malformed, revoked, or unknown key.
402 insufficient_credits: valid key but balance < 1; only raised on calls that consume credits.
Sign up in the dashboard to mint a key and claim 100 free credits.
A future nc_test_ prefix is reserved for test-mode keys.
Errors
Every non-2xx response follows the same envelope:
{
"error": {
"code": "insufficient_credits",
"message": "Your account has 0 credits remaining. Top up at https://dashboard.nonecap.com/billing.",
"param": null
}
}
param names the offending request field for validation errors; otherwise null.
HTTP status codes
400
BAD REQUEST
invalid_request: Malformed JSON or missing required structural field.
401
UNAUTHORIZED
unauthorized: Missing, malformed, revoked, or unknown API key.
402
PAYMENT REQUIRED
insufficient_credits: Not enough credits to start the solve.
403
FORBIDDEN
account_locked: The owning account has been locked by an administrator.
404
NOT FOUND
not_found: Solve id unknown or purged after retention.
409
CONFLICT
conflict: Cancel on already-terminal solve.
422
UNPROCESSABLE
validation_error: Bad field value (unknown type, bad url, etc.).
429
RATE LIMITED
rate_limited: Too many requests; slow down.
429
RATE LIMITED
concurrency_limit_exceeded: Too many solves in flight for this account (default 5; contact support to raise). Retry once one completes.
500
SERVER ERROR
internal_error: Unexpected server error.
503
UNAVAILABLE
pool_exhausted: All workers busy; Retry-After header set.
Solve-failure codes
These ride in Solve.error.code on a terminal, non-solved solve.
status is failed, cancelled, or expired.
The request succeeded; the solve didn't produce a token.
challenge_not_loaded
The hCaptcha challenge never displayed. Usually proxy/IP reputation — retry with a different proxy.
token_not_granted
The challenge was completed but hCaptcha did not issue a token. Retry; if it persists, use a higher-quality proxy IP.
challenge_expired
hCaptcha expired the challenge before the solve completed. Retry the solve.
challenge_errored
hCaptcha aborted the challenge widget. Retry the solve.
proxy_error
The supplied proxy failed to connect or auth, or its IP was refused by hCaptcha. Fix or swap the proxy.
target_unreachable
The target url did not load. Verify it is reachable.
vision_error
Internal error in the solving pipeline. Retry; contact support if it persists.
cancelled
The caller cancelled the job.
expired
Solve exceeded its time budget before producing a token (never billed).
Versioning
This is v1. Breaking changes will ship under
v2 with at least 12 months of v1 support.
Resource shapes are additive within a major version: new optional fields
can appear at any time. Clients should ignore unknown fields rather than
treating them as an error.
Pagination
List endpoints use cursor-based pagination. The cursor is the
id of the last item you received; pass it as
starting_after on the next request.
limit: 1-100, default 20.
starting_after: a solve_… id (exclusive cursor).
Responses carry has_more: boolean. There is no separate cursor field: read the last item's id.
02 ·solves
The solve object
A solve represents one captcha-solving job: its parameters,
the worker that picked it up, the resulting token, and how much it cost you.
Attributes
idstring optional
Prefixed ULID, e.g. solve_01HQF7K3JKWZX.
object"solve" optional
Constant.
typestring · enum optional
Captcha type. See Captcha types below.
hcaptchahcaptcha_enterprise
statusstring · enum optional
Current state. Terminal states are solved, failed, cancelled and expired.
pendingsolvingsolvedfailedcancelledexpired
sitekeystring optional
Echoed from the original request.
urlstring optional
Echoed from the original request.
tokenstring · nullable optional
Present iff status = solved.
errorobject · nullable optional
Present on failed, cancelled, and expired; null otherwise. See Errors.
credits_chargedinteger · nullable optional
Final billed amount. null until terminal.
created_atstring · RFC 3339 optional
When the job was accepted.
started_atstring · nullable optional
When a worker picked it up.
finished_atstring · nullable optional
When the solve reached a terminal state.
queue_msinteger · nullable optional
Milliseconds spent waiting in the queue before a worker picked the solve up (started_at − created_at). For a solve that went terminal without ever being picked up — e.g. expired or cancelled while still queued — this is the full wait (finished_at − created_at). null while still pending.
resolve_msinteger · nullable optional
Milliseconds of actual solving (finished_at − started_at). null if the solve never left the queue, or hasn't finished yet. Pair with queue_ms to tell capacity (queue) from solver performance (resolve).
Records are purged after a 30-day retention window; after that
GET /v1/solves/{id} returns 404.
That retention is separate from the expired status above.
Captcha types
hcaptchacaptcha type optional
Required:sitekey, url.
Optional:user_agent, proxy.
Returns a P1_ token.
hcaptcha_enterprisecaptcha type optional
Required:sitekey, url, rqdata.
Optional:user_agent, proxy.
Returns a P1_ token.
recaptcha_v2reserved optional
Reserved for future expansion.
recaptcha_v3reserved optional
Reserved for future expansion.
cloudflare_turnstilereserved optional
Reserved for future expansion.
funcaptchareserved optional
Reserved for future expansion.
Create a solve
POSThttps://api.nonecap.com/v1/solves
Submit a new captcha solve. Credit is debited at submit time and refunded
automatically on failed, cancelled, or expired.
Body parameters
typestring required
Captcha type to solve.
hcaptchahcaptcha_enterprise
sitekeystring required
The sitekey hCaptcha gave you.
urlstring required
Page URL where the challenge appears.
rqdatastring optional
Required for hcaptcha_enterprise; carries the IP-bound challenge data.
user_agentstring optional
Match the user agent your real client uses.
proxystring | object optional
URL string (http://user:pass@host:port) or object form with host, port, scheme, username, password.
webhook_urlstring optional
Receive a solve.completed callback when the solve reaches a terminal state.
Query parameters
waitinteger optional
Block up to N seconds (1-90); return as soon as the solve reaches a terminal state.
Responses
202
ACCEPTED
pending: Async: solve is still in flight.
200
OK
terminal: Set ?wait and the solve reached a terminal state in time.
422
UNPROCESSABLE
validation_error: Malformed body or invalid field value.
402
PAYMENT REQUIRED
insufficient_credits: Balance < 1 credit.
429
TOO MANY
concurrency_limit_exceeded: Account already at its concurrency cap (default 5). Retry once one completes.
503
UNAVAILABLE
pool_exhausted: All workers busy. See Retry-After header.
Retrieve a solve
GEThttps://api.nonecap.com/v1/solves/{id}
Fetch the current state of a solve by id. With ?wait=N
(1-90 s), the call blocks until the solve reaches a terminal state or the
wait expires.
Path parameters
idstring required
Prefixed ULID of the solve, e.g. solve_01HQF7K3JKWZX.
Query parameters
waitinteger optional
Block up to N seconds (1-90); return as soon as the solve reaches a terminal state.
Responses
200
OK
Terminal (solved/failed/cancelled/expired). Returns the full solve object.
202
ACCEPTED
Still pending/solving. Poll again (or use ?wait).
404
NOT FOUND
Solve id unknown or purged after the 30-day retention window.
List solves
GEThttps://api.nonecap.com/v1/solves
Cursor-paginated history of solves for the authenticated account. Newest first.
Query parameters
limitinteger optional
Number of solves to return. Default 20, range 1-100.
starting_afterstring optional
Pagination cursor: id of the last solve from the previous page.
statusstring optional
Filter by solve status.
pendingsolvingsolvedfailedcancelledexpired
typestring optional
Filter by captcha type.
hcaptchahcaptcha_enterprise
Response carries has_more: boolean. There is no
separate cursor field. The cursor is the
id of the last item in data.
Cancel a solve
DELETEhttps://api.nonecap.com/v1/solves/{id}
Cancel a pending or solving
solve. The credit is refunded automatically.
Path parameters
idstring required
Prefixed ULID of the solve to cancel, e.g. solve_01HQF7K3JKWZX.
Responses
200
OK
Cancelled. Returns the solve with status: "cancelled".
409
CONFLICT
conflict: Solve already reached a terminal state and cannot be cancelled.
404
NOT FOUND
not_found: Unknown solve id.
03 ·account
Account & balance
GEThttps://api.nonecap.com/v1/me
Returns the authenticated account plus the current credit balance. Useful
for showing balance in your own dashboard or as a pre-flight before a
batch.
Response
object"account" optional
Constant.
idstring optional
Prefixed ULID, e.g. user_01HQ….
emailstring optional
Verified email on the account.
credits_balanceinteger optional
Available solves remaining.
created_atstring · RFC 3339 optional
Account creation timestamp.
04 ·webhooks
Webhooks
Rolling outSpec'd, delivery rolling out. You can pass webhook_url
on a solve today and it's stored on the record. Outbound delivery starts when the worker ships (phase 3.5).
The signature scheme below is final and won't change.
When a solve reaches a terminal state, NoneCap POSTs the event to
webhook_url. Use the headers below to verify the request came
from us before acting on it.
The signed payload is "<t>.<raw_body>"
(note the literal dot). Verification is HMAC-SHA256 with the webhook secret
from your dashboard. Reject any signature where t
is older than 5 minutes. This defeats replay.
Delivery & retries
Expect a 2xx within 5 seconds. Non-2xx or timeout triggers a retry.