The official NoneCap TypeScript SDK.
nonecap is the official TypeScript client for the NoneCap API.
Submit a captcha, get back a token. The SDK handles the polling, the
timeouts, and the error cases so you don't write the fetch loop yourself.
Zero dependencies, and the types do real work.
Install
npm install nonecap Runs on Node 18+, Bun, Deno, and edge runtimes. Get an API key from dashboard.nonecap.com.
Quick start
The headline is a single call. solve() submits the captcha and
waits until it's done, then returns the solved solve:
import { NoneCap } from "nonecap";
const nc = new NoneCap({ apiKey: process.env.NONECAP_KEY });
// Submit a captcha and wait for the token. One call, no polling loop.
const solve = await nc.solve({
type: "hcaptcha",
sitekey: "10000000-ffff-ffff-ffff-000000000001",
url: "https://example.com/login",
});
console.log(solve.token); // a real hCaptcha token, ready to submit Errors you can branch on
Every error this library throws extends NoneCapError, so you can
catch the whole family or pick out the one you care about. A failed solve
throws SolveFailedError with the full solve attached, so you get
the underlying error code and the timings:
import {
NoneCap,
SolveFailedError,
InsufficientCreditsError,
RateLimitError,
} from "nonecap";
try {
const { token } = await nc.solve({ type: "hcaptcha", sitekey, url });
// use token
} catch (err) {
if (err instanceof SolveFailedError) {
console.error("Could not solve it:", err.solve.error?.code);
} else if (err instanceof InsufficientCreditsError) {
console.error("Out of credits. Top up at dashboard.nonecap.com");
} else if (err instanceof RateLimitError) {
console.error("Too many solves in flight, back off and retry");
} else {
throw err;
}
} Enterprise types that catch mistakes
For hcaptcha_enterprise, rqdata is required. The
parameter type is a discriminated union on type, so the compiler
rejects an enterprise solve that forgets it. You find out at build time, not
in production:
// rqdata is required for enterprise, and the types enforce it:
// leaving it out is a compile error, not a runtime surprise.
const { token } = await nc.solve({
type: "hcaptcha_enterprise",
sitekey,
url,
rqdata, // the fresh, IP-bound challenge blob
}); Lower-level methods
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 blocking, then poll the one solve yourself.
const pending = await nc.solves.create({ type: "hcaptcha", sitekey, url });
const done = await nc.solves.retrieve(pending.id, { wait: 30 });
// Cancel, list, or iterate every solve newest-first.
await nc.solves.cancel(pending.id);
for await (const s of nc.solves.listAll()) console.log(s.id, s.status);
// Your account and credit balance.
const me = await nc.me();
console.log(me.credits_balance); Python
There's an official Python client too:
pip install nonecap.
Same shape as the TypeScript SDK, with sync and async clients, the typed
error tree, and the enterprise rqdata requirement enforced by
mypy and pyright. Source at
github.com/nonecap/nonecap-py,
full guide at Python hCaptcha solver.
# pip install nonecap
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) # a real hCaptcha token, ready to submit
# Async? Same surface: AsyncNoneCap, awaited. Not using JavaScript or Python?
The API is a plain REST endpoint, so any language works. The API reference has runnable examples in cURL, Node, Python, and Go, and the integration guides cover Playwright, Puppeteer, web scraping, and AI agents. Prefer a no-code option? The Chrome extension solves hCaptcha right in your browser.
Last updated June 2026.
Frequently asked
What runtimes does it work on?
fetch and ships zero dependencies. The package is dual ESM and CommonJS with bundled type definitions.Does it handle polling and timeouts for me?
nc.solve() submits the captcha and uses the API's long-poll under the hood, keeping the connection open until the solve finishes or your timeout elapses. It returns the solved solve, or throws a typed error you can branch on.How are errors typed?
NoneCapError, so you can catch the whole family or a specific one: AuthenticationError, InsufficientCreditsError, ValidationError (with the offending param), RateLimitError, NotFoundError, ConflictError, and more. A failed solve throws SolveFailedError with the full solve attached.