npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nonecap

v0.1.0

Published

Official TypeScript client for the NoneCap hCaptcha solving API.

Readme

Submit a captcha, get back a token. The client handles the polling, the timeouts, and the error cases so you do not have to write the fetch loop yourself.

Install

npm install nonecap

Works on Node 18+, Bun, Deno, and edge runtimes. No dependencies.

Quick start

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

import { NoneCap } from "nonecap";

const nc = new NoneCap({ apiKey: process.env.NONECAP_KEY! });

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

console.log(solve.token); // the hCaptcha token, ready to submit

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

Handling failures

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

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 in flight, back off and retry");
  } else {
    throw err;
  }
}

The error subclasses are AuthenticationError (401), PermissionError (403), InsufficientCreditsError (402), ValidationError (422/400, with a param naming the bad field), NotFoundError (404), ConflictError (409), RateLimitError (429), APIError (5xx), and ConnectionError (the request never landed). SolveFailedError carries the full solve so you can read solve.error and the timing fields.

Enterprise captchas

For hcaptcha_enterprise, rqdata is required. The types enforce it, so leaving it out is a compile error, not a runtime surprise.

const { token } = await nc.solve({
  type: "hcaptcha_enterprise",
  sitekey,
  url,
  rqdata: "...", // required for enterprise
});

Proxies

Pass a proxy as a structured object or a URL string. Solves run through it, and the bytes are metered back on the solve.

await nc.solve({
  type: "hcaptcha",
  sitekey,
  url,
  proxy: { scheme: "http", host: "1.2.3.4", port: 8080, username: "u", password: "p" },
  // or: proxy: "http://u:[email protected]:8080"
});

Lower-level API

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

// Submit without waiting: returns immediately with a pending solve
const pending = await nc.solves.create({ type: "hcaptcha", sitekey, url });

// Submit and hold the connection up to 30s for it to finish
const maybeDone = await nc.solves.create({ type: "hcaptcha", sitekey, url }, { wait: 30 });

// Poll one solve, long-polling up to 30s
const solve = await nc.solves.retrieve(pending.id, { wait: 30 });

// Cancel a pending or in-flight solve
await nc.solves.cancel(pending.id);

// List a page of solves
const page = await nc.solves.list({ limit: 50, status: "solved" });

// Or iterate every solve, newest first
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);

Cancelling and timeouts

Pass an AbortSignal to cancel any call, and a timeout to bound how long solve() waits.

const ac = new AbortController();
setTimeout(() => ac.abort(), 60_000);

await nc.solve(
  { type: "hcaptcha", sitekey, url },
  { timeout: 120_000, signal: ac.signal },
);

Configuration

new NoneCap({
  apiKey: "nc_live_...",        // required
  baseURL: "https://api.nonecap.com", // override if you need to
  timeout: 100_000,             // per HTTP request, ms
  fetch: customFetch,           // inject your own fetch
});

License

MIT, see LICENSE.