If your scraper or test suite stopped at an hCaptcha widget sometime in the last two years, the service you used to send it to may be part of the problem.
2Captcha removed hCaptcha from its API documentation around the start of 2025. CapSolver's hCaptcha documentation page has returned a 404 since January 2025. If your code was written against either one for hCaptcha, you need a different place to send those jobs.
This post covers how token-based solving works, what to do when the site is yours, and one way to wire a solver into a script.
First: is it your own site?
If the hCaptcha widget sits on an app you control and you only need your end-to-end tests to get past it, you don't need a solving service. hCaptcha publishes test keys for this. In your test environment, set the widget's sitekey to 10000000-ffff-ffff-ffff-000000000001 and your server's secret to the matching test secret from hCaptcha's docs. The widget then passes without a challenge and siteverify accepts the dummy token, so your CI never depends on a third party.
Everything below is for sites you don't control: a scraper collecting public data, a monitoring job, or a test that runs against a staging environment someone else owns.
How token-based solving works
When a person solves an hCaptcha, the widget gets back a token that starts with P1_. The page puts it in a hidden form field called h-captcha-response (or hands it to a JavaScript callback), and the site's backend checks it with hCaptcha's siteverify endpoint before it lets the request through.
A token-based solver gives you that same token without a browser on your side. The flow has four steps:
- Read the widget's sitekey from the page. It's in the
data-sitekeyattribute of the hCaptchadiv, or in thesitekey=parameter of the widget's iframe URL. - Send the sitekey and the page URL to the solver API.
- Get a
P1_token back. - Submit it the way the page would: in
h-captcha-response, or through the callback the site registered.
Two details trip people up. A token is single use and expires after about two minutes, so request it right before you submit, not at the start of a long job. And some sites check that the browser submitting the token matches the one that earned it, so send the User-Agent the solver returns with the token.
Calling NoneCap
NoneCap is a hosted API that only handles hCaptcha, including invisible widgets and enterprise sitekeys that carry rqdata. You send a sitekey and a URL and get a token back. Failed solves aren't charged.
With Python and requests:
import os, requests res = requests.post( "https://api.nonecap.com/v1/solves", params={"wait": 30}, headers={"Authorization": f"Bearer {os.environ['NONECAP_KEY']}"}, json={ "type": "hcaptcha", "sitekey": "f5ab1c2d-7e8f-4a9b-b1c2-d3e4f5a6b7c8", "url": "https://target.example/login", }, ) solve = res.json() token = solve["token"] # P1_... user_agent = solve["user_agent"] # send this as your User-Agent when you submit The wait parameter (1 to 90 seconds) holds the request open until the solve finishes. If it's still running when the window closes, you get a 202 with a null token, and you poll GET /v1/solves/{id} until the status is solved, failed or expired.
The same call from Node 18+, with no SDK:
const res = await fetch("https://api.nonecap.com/v1/solves?wait=30", { method: "POST", headers: { Authorization: `Bearer ${process.env.NONECAP_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ type: "hcaptcha", sitekey: "f5ab1c2d-7e8f-4a9b-b1c2-d3e4f5a6b7c8", url: "https://target.example/login", }), }); const solve = await res.json(); In Playwright or Puppeteer, you'd read the sitekey from the page, make this call, write the token into the h-captcha-response textarea (plus the g-recaptcha-response compatibility field if the page has one), then submit the form or fire the widget's callback for invisible sitekeys.
One more thing helps over time. A token can pass hCaptcha and still be refused by the site that asked for it. When that happens, report the solve ID to POST /v1/feedback with "outcome": "rejected". It's the only way the service learns that a site turned a token down.
If your code already speaks 2Captcha or CapSolver
You may not need to rewrite anything. NoneCap has compatibility endpoints for both request formats:
- 2Captcha's
in.php/res.php: point the client atapi.nonecap.com/compat/2captchaand use a NoneCap key. - CapSolver's
createTask/getTaskResult(also used by Anti-Captcha and CapMonster clients): use the base URLhttps://api.nonecap.com/compat/capsolverwith a NoneCap key asclientKey.
The rest of your code stays as it is.
Where to go next
The full API reference, with cURL and Go examples alongside the ones above, is at nonecap.com/api-reference. There are integration guides for Selenium, Playwright, Puppeteer, Scrapy and Go at nonecap.com/solutions, and a plain-text version of all the docs for coding assistants at nonecap.com/llms.txt.


![AMR AI and Embodied Intelligence — Ch.18: GPU and Accelerator Design [KR]](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fospxyzadkcmpo8xjqyok.png)