Skip to main content

Official Python client for the NoneCap hCaptcha solving API.

Project description

nonecap

CI PyPI Python versions License: MIT

Official Python client for the NoneCap hCaptcha solving API.

Submit a captcha, get back a token. The client handles the polling, the timeouts, and the error cases so you don't write the request loop yourself. Sync and async, fully typed.

Install

pip install nonecap

Python 3.9+. The only dependency is httpx.

Quick start

Grab an API key from dashboard.nonecap.com, then:

from nonecap import NoneCap

nc = NoneCap(api_key="nc_live_...")

solve = nc.solve(
    type="hcaptcha",
    sitekey="10000000-ffff-ffff-ffff-000000000001",
    url="https://example.com/login",
)

print(solve.token)  # the hCaptcha token, ready to submit

solve() submits the captcha and waits until it's done, using the API's long-poll so you aren't hammering it with requests. It returns the solved solve, or raises if the solve fails or your timeout runs out.

Async

Same surface, awaited. Use it as an async context manager so the connection pool gets cleaned up:

import asyncio
from nonecap import AsyncNoneCap

async def main() -> None:
    async with AsyncNoneCap(api_key="nc_live_...") as nc:
        solve = await nc.solve(type="hcaptcha", sitekey="...", url="https://example.com")
        print(solve.token)

asyncio.run(main())

Handling failures

Every error this library raises extends NoneCapError, so you can catch the whole family or pick out the one you care about.

from nonecap import (
    NoneCap,
    SolveFailedError,
    InsufficientCreditsError,
    RateLimitError,
)

try:
    solve = nc.solve(type="hcaptcha", sitekey=sitekey, url=url)
except SolveFailedError as err:
    print("Could not solve it:", err.solve.error.code if err.solve.error else "?")
except InsufficientCreditsError:
    print("Out of credits. Top up at dashboard.nonecap.com")
except RateLimitError:
    print("Too many solves in flight, back off and retry")

The subclasses are AuthenticationError (401), PermissionDeniedError (403), InsufficientCreditsError (402), ValidationError (422/400, with a param naming the bad field), NotFoundError (404), ConflictError (409), RateLimitError (429), APIError (5xx), APIConnectionError and APITimeoutError (the request never landed), and SolveTimeoutError (your solve() budget ran out). SolveFailedError carries the full solve so you can read the underlying error code and the timings.

Enterprise captchas

For hcaptcha_enterprise, rqdata is required. The @overload signatures enforce that in mypy and pyright, so leaving it out fails your type check, and a runtime check backs it up before any network call:

solve = nc.solve(
    type="hcaptcha_enterprise",
    sitekey=sitekey,
    url=url,
    rqdata="...",  # required for enterprise
)

Proxies

Pass a proxy as a dict or a URL string. The solve runs through it, and the bytes are metered back on the solve.

nc.solve(
    type="hcaptcha",
    sitekey=sitekey,
    url=url,
    proxy={"scheme": "http", "host": "1.2.3.4", "port": 8080, "username": "u", "password": "p"},
    # or: proxy="http://u:p@1.2.3.4:8080"
    # scheme can be http, https, socks5, socks5h, or socks4 (default http)
    # e.g. proxy="socks5://u:p@1.2.3.4:1080"
)

Lower-level API

solve() is the convenient path. When you want control over submission and polling, the resource methods map one to one to the REST API:

# Submit without waiting: returns immediately with a pending solve
pending = nc.solves.create(type="hcaptcha", sitekey=sitekey, url=url)

# Submit and hold the connection up to 30s for it to finish
maybe_done = nc.solves.create(type="hcaptcha", sitekey=sitekey, url=url, wait=30)

# Poll one solve, long-polling up to 30s
solve = nc.solves.retrieve(pending.id, wait=30)

# Cancel a pending or in-flight solve
nc.solves.cancel(pending.id)

# List a page of solves
page = nc.solves.list(limit=50, status="solved")

# Or iterate every solve, newest first
for s in nc.solves.list_all():
    print(s.id, s.status)

# Your account and credit balance
me = nc.me()
print(me.credits_balance)

On AsyncNoneCap the same methods are coroutines, and list_all() is an async iterator (async for s in nc.solves.list_all()).

Configuration

NoneCap(
    api_key="nc_live_...",              # required
    base_url="https://api.nonecap.com", # override if you need to
    timeout=100.0,                      # per HTTP request, seconds
    http_client=my_httpx_client,        # inject your own httpx.Client
)

solve() takes its own timeout (seconds, default 180) for the overall wait.

Typing

The package ships a py.typed marker and full inline annotations. Solves come back as frozen dataclasses with the exact field names the API uses (solve.token, solve.credits_charged, solve.queue_ms), so what you read in the API reference is what you get in code.

License

MIT, see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nonecap-0.1.1.tar.gz (14.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nonecap-0.1.1-py3-none-any.whl (12.6 kB view details)

Uploaded Python 3

File details

Details for the file nonecap-0.1.1.tar.gz.

File metadata

  • Download URL: nonecap-0.1.1.tar.gz
  • Upload date:
  • Size: 14.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nonecap-0.1.1.tar.gz
Algorithm Hash digest
SHA256 d6bc58576d8a6562335ddc2af57a024c030c0ff7321f44f75b4ee482481d7f5f
MD5 cf522f69dc6f2d616906cc72c42b4919
BLAKE2b-256 cd7d3e6ec8e44baf1a5bc265a7b1a885bee835e00e87c61b0ff57478d7bb8f80

See more details on using hashes here.

Provenance

The following attestation bundles were made for nonecap-0.1.1.tar.gz:

Publisher: ci.yml on nonecap/nonecap-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nonecap-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: nonecap-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 12.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nonecap-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2c87464a4afba6355b79ad195d78c143d442271b73afaed4baaf47bf97007ca1
MD5 b28b3a9aaf9903652031ad7d1199265d
BLAKE2b-256 479ffa80e07fe6395c63de528b394d53dcb7704d769cb9a50d5e3e75158f63c9

See more details on using hashes here.

Provenance

The following attestation bundles were made for nonecap-0.1.1-py3-none-any.whl:

Publisher: ci.yml on nonecap/nonecap-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page