NoneCap API · v1
Get a key →
01 · getting started

The NoneCap hCaptcha API.

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

  1. Sign in to the dashboard and mint an API key (nc_live_…).
  2. POST a solve to /v1/solves. Add ?wait=N (1-90 s) to block until the solve completes.
  3. 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

id string optional
Prefixed ULID, e.g. solve_01HQF7K3JKWZX.
object "solve" optional
Constant.
type string · enum optional
Captcha type. See Captcha types below.
hcaptchahcaptcha_enterprise
status string · enum optional
Current state. Terminal states are solved, failed, cancelled and expired.
pendingsolvingsolvedfailedcancelledexpired
sitekey string optional
Echoed from the original request.
url string optional
Echoed from the original request.
token string · nullable optional
Present iff status = solved.
error object · nullable optional
Present on failed, cancelled, and expired; null otherwise. See Errors.
credits_charged integer · nullable optional
Final billed amount. null until terminal.
created_at string · RFC 3339 optional
When the job was accepted.
started_at string · nullable optional
When a worker picked it up.
finished_at string · nullable optional
When the solve reached a terminal state.
queue_ms integer · 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_ms integer · 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).

Lifecycle

pending → solving → solved
                  → failed
                  → expired     (exceeded time budget / reclaimed)

pending | solving → cancelled   (via DELETE)

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

hcaptcha captcha type optional
Required: sitekey, url. Optional: user_agent, proxy. Returns a P1_ token.
hcaptcha_enterprise captcha type optional
Required: sitekey, url, rqdata. Optional: user_agent, proxy. Returns a P1_ token.
recaptcha_v2 reserved optional
Reserved for future expansion.
recaptcha_v3 reserved optional
Reserved for future expansion.
cloudflare_turnstile reserved optional
Reserved for future expansion.
funcaptcha reserved optional
Reserved for future expansion.

Create a solve

POST https://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

type string required
Captcha type to solve.
hcaptchahcaptcha_enterprise
sitekey string required
The sitekey hCaptcha gave you.
url string required
Page URL where the challenge appears.
rqdata string optional
Required for hcaptcha_enterprise; carries the IP-bound challenge data.
user_agent string optional
Match the user agent your real client uses.
proxy string | object optional
URL string (http://user:pass@host:port) or object form with host, port, scheme, username, password.
webhook_url string optional
Receive a solve.completed callback when the solve reaches a terminal state.

Query parameters

wait integer 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

GET https://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

id string required
Prefixed ULID of the solve, e.g. solve_01HQF7K3JKWZX.

Query parameters

wait integer 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

GET https://api.nonecap.com /v1/solves

Cursor-paginated history of solves for the authenticated account. Newest first.

Query parameters

limit integer optional
Number of solves to return. Default 20, range 1-100.
starting_after string optional
Pagination cursor: id of the last solve from the previous page.
status string optional
Filter by solve status.
pendingsolvingsolvedfailedcancelledexpired
type string 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

DELETE https://api.nonecap.com /v1/solves/{id}

Cancel a pending or solving solve. The credit is refunded automatically.

Path parameters

id string 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

GET https://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.
id string optional
Prefixed ULID, e.g. user_01HQ….
email string optional
Verified email on the account.
credits_balance integer optional
Available solves remaining.
created_at string · RFC 3339 optional
Account creation timestamp.
04 · webhooks

Webhooks

Rolling out Spec'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.

Headers sent

  • Content-Type: application/json
  • User-Agent: NoneCap-Webhook/1
  • X-NoneCap-Event: solve.completed
  • X-NoneCap-Signature: t=<unix_seconds>,v1=<hex_hmac_sha256>

Signature scheme

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.
  • Retry schedule: +30 s, +5 min, +30 min (3 attempts total).
  • After the final failure the webhook is dropped. The solve itself is unaffected: fetch it from /v1/solves/{id} as a fallback.

Event types

NoneCap currently emits one event type:

solve.completed event optional
Fires when a solve reaches any terminal state: solved, failed, cancelled, or expired. data carries the full solve object.

Dispatch on data.status to tell success from failure. A single solve.completed covers all terminal cases.