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 up to N seconds and return as soon as the solve reaches a terminal state. Still in flight when the window closes? You get 202 with a null token — poll GET /v1/solves/{id} until it's terminal.
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.
403
FORBIDDEN
forbidden: The API key lacks the scope required for this endpoint.
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.
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. When hCaptcha is rate-limiting the sitekey itself the message says so instead: that is upstream of your proxy, so retry shortly rather than switching IP.
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
The challenge rendered but the solver could not read it this time. Retry; if it persists for one challenge type, contact support.
internal_error
An unclassified internal failure in the solving pipeline. Retry; contact support if it persists.
unsolvable_variant
The challenge used an animated variant NoneCap cannot currently solve. Not billed.
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.
proxy_bytesinteger · nullable optional
Bytes that egressed through your metered proxy for this solve. null when the solve ran without a proxy.
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. You're charged only when a solve succeeds (the
amount is metered per round and reported as credits_charged);
failed, cancelled, and expired solves are never charged. Submitting requires a balance of at least 1 credit.
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. Supported schemes: http, https, socks5, socks5h, socks4 (default http). For example socks5://user:pass@host:port.
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.
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. Cancelled solves are never charged, so no credit is spent.
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 ·feedback
Report feedback
POSThttps://api.nonecap.com/v1/feedback
Report the downstream accept / reject verdict for solves
you've already run, so we can watch real token quality in real time and
catch regressions fast. This is the primary, batch endpoint —
buffer verdicts and flush up to 500 at once. There's
no extra charge and no new key or scope: it's gated on the
same solve scope that created the solves (your
existing API key works unchanged). You can only report your own solves.
Body parameters
feedbackarray required
1–500 feedback items. An empty, missing, non-array, or over-cap value is a
422 validation_error on feedback.
The batch is not all-or-nothing — each item is validated and
upserted independently, and one bad solve_id never
discards the good rows.
Feedback item
solve_idstring required
The solve_... id returned by Create a solve.
Must belong to you and be a solved solve. Keep this
id next to the token you submit downstream — it's the only thing you retain
to report the outcome later.
outcomestring · enum required
The downstream verdict. Only accepted and
rejected count toward the acceptance rate;
unknown (verdict undetermined),
unused (token never submitted / expired), and
error (non-token failure — network, 5xx, maintenance)
are recorded but excluded from the quality denominator.
acceptedrejectedunknownunusederror
estadoboolean optional
Raw OSIPTEL signal, stored verbatim: false = accepted,
true = rejected. If present it must agree with
outcome (else the item is a
validation_error).
reasonstring optional
Freeform downstream reason or code (e.g. an OSIPTEL rejection message).
Truncated to 512 characters.
reported_atstring · ISO 8601 optional
Client's instant of the downstream verdict. Advisory only — the server
always stamps its own created_at /
updated_at.
Rules
Own solves only. A foreign or unknown id resolves to a per-item not_eligible.
Solved solves only. A solve that never reached solved is not reportable (not_eligible).
30-day first-report window. The first report must land within 30 days of the solve; a late first report is expired_window. Corrections to an already-reported solve are not age-gated.
Idempotent, last-write-wins. Reporting the same solve_id again overwrites the mutable fields (status: updated); re-sending an identical value is a no-op (status: unchanged). The first reported outcome stays immutable server-side and report_count bumps only on a real change, so verdict flips stay auditable.
Two response shapes
This batch endpoint returns the batch envelope:
{ object: "feedback_batch", recorded, updated, unchanged, failed, results },
where each results entry has a
status of recorded |
updated | unchanged |
error, and a failed item nests a bare{ code, message, param } (no error
wrapper). The single-item alias below returns the
feedback resource directly, or the standard
{ error: { code, message, param } } envelope on
failure. Handle both.
Responses
200
OK
feedback_batch: Always returned once the request is structurally valid — even if some items failed. Inspect per-item status.
400
BAD REQUEST
invalid_request: Body is not a JSON object.
422
UNPROCESSABLE
validation_error: feedback is missing, empty, not an array, or over 500 items (param feedback).
Per-item error.code values inside a
200 batch are
validation_error (bad field),
not_eligible (unknown / foreign / not-solved id), or
expired_window (first report past the 30-day window).
Convenience alias for reporting a single solve — the same validation and
upsert path as one Report feedback batch item, for
low-volume callers and interactive testing. The solve_id
comes from the path, so the body is just the item fields (no
feedback wrapper). High-volume integrations should
use the batch endpoint above.
Body parameters
outcomestring · enum required
The downstream verdict. Only accepted /
rejected count toward the acceptance rate.
acceptedrejectedunknownunusederror
estadoboolean optional
Raw OSIPTEL signal (false = accepted,
true = rejected). Must agree with
outcome.
reasonstring optional
Freeform downstream reason, truncated to 512 characters.
reported_atstring · ISO 8601 optional
Advisory verdict timestamp; the server stamps its own timestamps.
Same rules as the batch endpoint: own solves only, solved
solves only, first report within 30 days, idempotent last-write-wins.
Responses
200
OK
feedback: The feedback resource (same shape whether recorded or updated).
400
BAD REQUEST
invalid_request: Body is not JSON.
404
NOT FOUND
not_found: Unknown id, not your solve, or not a solved solve.
422
UNPROCESSABLE
validation_error: Bad field value (invalid outcome, or estado disagrees with outcome).
422
UNPROCESSABLE
expired_window: First report is past the 30-day window (param solve_id).