Invisible hCaptcha: no checkbox, same token.
Invisible hCaptcha is the checkbox widget with the box removed. The page calls
hcaptcha.execute() when it wants a token, hCaptcha scores the session in
the background, and a challenge modal appears only if that score demands it. The
output is unchanged: a P1_ token in h-captcha-response.
Here is how the mode works and what it means when you need to solve one.
The three widget sizes
hCaptcha's widget takes a size parameter (or data-size attribute).
The configuration docs list two values for the visible widget, normal and
compact, with normal as the default. The third value,
invisible, has its own setup and its own docs page, because it changes who
initiates the flow: with a checkbox the visitor starts it by clicking, with invisible
the page starts it in JavaScript.
| Size | What the visitor sees | How the token is requested |
|---|---|---|
normal (default) | The standard "I am human" checkbox widget | Visitor clicks the checkbox; a challenge may follow |
compact | A smaller checkbox for narrow layouts | Same click flow as normal |
invisible | Nothing at all | The page calls hcaptcha.execute(); a challenge modal appears only if risk demands it |
Sites pick invisible mode to keep the captcha out of the UI. Signup, login, and checkout forms are the common cases: the visitor sees a normal submit button, and verification happens behind it. People also use "invisible hCaptcha" loosely to mean the paid Passive behavior settings, which control how often anyone is challenged. Those are separate dials: size is a free rendering option set in the widget code, behavior is a plan feature set per sitekey in the dashboard. Both are covered below.
How invisible mode runs
There are two ways a site wires it up. The simplest is automatic binding:
put the h-captcha class directly on the submit button with a
data-sitekey and a data-callback. Clicking the button triggers
the hCaptcha flow, and the callback receives the token when one exists:
<!-- Automatic binding: the h-captcha class goes on the button itself. -->
<button class="h-captcha"
data-sitekey="f5ab1c2d-7e8f-4a9b-b1c2-d3e4f5a6b7c8"
data-callback="onSubmit">
Sign up
</button>
<script>
function onSubmit(token) {
// token is a normal P1_ hCaptcha token; submit the form with it.
document.querySelector('form').submit();
}
</script>
The second is programmatic binding: render the widget invisibly into a
container, then call hcaptcha.execute() from your own code whenever you
want a token. The docs describe execute() as triggering the hCaptcha
workflow programmatically, "generally used in invisible mode":
<!-- Programmatic binding: render invisible, then trigger it yourself. -->
<div id="captcha-box"></div>
<script>
const widgetId = hcaptcha.render('captcha-box', {
sitekey: 'f5ab1c2d-7e8f-4a9b-b1c2-d3e4f5a6b7c8',
size: 'invisible',
callback: (token) => {
// Fires once a token exists, challenge or not.
document.querySelector('form').submit();
}
});
// Call this from your own submit handler. Low-risk sessions mint a
// token silently; everyone else gets the familiar challenge modal.
hcaptcha.execute(widgetId);
</script>
Either way, the moment of truth is the same. When execute() fires, hCaptcha
evaluates the session. If it looks low-risk, the token mints silently and the callback
runs with no user interaction at all. If the session meets hCaptcha's challenge
criteria, the standard challenge modal pops over the page, identical to what a checkbox
user would see after clicking. Invisible removes the checkbox, not the challenge. The
challenge itself can be any of the usual rounds; see
hCaptcha challenge types for what those
look like.
Passive and 99.9% Passive: the paid no-challenge modes
Above invisible rendering, hCaptcha sells behavior settings that control how often
anyone is challenged at all. On Pro plans the sitekey can be set to
"99.9% Passive", a No-CAPTCHA mode that aims to challenge fewer than
0.1% of users; it is the default behavior for new Pro sitekeys and is configured per
sitekey in the dashboard. Enterprise plans add a fully "Passive"
No-CAPTCHA mode on top, plus the per-request risk signals (rqdata) that
bind each challenge to a session.
"Passive" does not mean unprotected. hCaptcha states that whether a visual challenge is shown or not, other security controls, including dynamic proof-of-work, run on every request.
If the site is on enterprise hCaptcha, the sitekey alone may not be enough to solve it. Enterprise pages often pass a fresh
rqdatablob per challenge, which you must capture and forward withtype: "hcaptcha_enterprise". See hCaptcha enterprise rqdata for how to spot it and what to send.
The output is identical
This is the part that matters whether you are integrating hCaptcha or automating past
it. Checkbox, compact, invisible, 99.9% Passive: every mode ends in the same place. A
P1_ token lands in the form's h-captcha-response field, the
server posts it to siteverify, and the token is single-use and valid for
roughly 120 seconds:
<!-- Identical output either way: -->
<textarea name="h-captcha-response">P1_eyJ0eXAi...UV8w</textarea>
A backend cannot tell from the token whether it came from a checkbox click or a silent
execute() call; the mode only changes how the token gets requested. Format,
expiry, and verification are covered in
the hCaptcha token explained.
Finding the sitekey when nothing renders
With no visible widget there is no obvious element to inspect, but the sitekey is
still in the page; the browser needs it to load the widget. Check the
data-sitekey on the bound button, the sitekey field in the
hcaptcha.render() call, or the ?sitekey= parameter on the
hCaptcha iframe's src URL in DevTools. Searching the rendered DOM for the
string sitekey finds it in every case.
How to find an hCaptcha sitekey walks through
each method with examples.
Solving an invisible sitekey
Because the output is identical, solving is too. NoneCap explicitly supports invisible
sitekeys, and the request is byte-for-byte the one you would send for a checkbox
widget: the public sitekey plus the page url, posted to
/v1/solves:
curl "https://api.nonecap.com/v1/solves?wait=90" \
-H "Authorization: Bearer $NONECAP_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "hcaptcha",
"sitekey": "f5ab1c2d-7e8f-4a9b-b1c2-d3e4f5a6b7c8",
"url": "https://target.example/signup"
}' {
"id": "solve_01HQF7K3JKWZX",
"object": "solve",
"type": "hcaptcha",
"status": "solved",
"token": "P1_eyJ0eXAi...UV8w",
"credits_charged": 1
}
Set the returned token as the value of h-captcha-response
(and fire the site's callback if it gates submission on one), then submit within the
~120-second window. You never call execute() yourself; that call exists to
ask hCaptcha for a token, and you already have one. The same flow drops into
Playwright,
Puppeteer, or
Selenium runs, and the
official SDKs wrap it in one solve() call.
One practical note for automation: invisible pages usually read the token from the
hidden field at submit time, so injecting the token and submitting the form is enough.
If the page caches a callback promise from execute(), invoke the callback
function directly with the token instead. The API
reference covers polling and webhook_url delivery if you would rather
not block on ?wait.
Last updated June 2026.
Frequently asked
How do I know a site uses invisible hCaptcha?
api.js script from hcaptcha.com in the network tab, an hcaptcha.render() call with size: 'invisible', or a hidden h-captcha-response field that fills in after you click submit. The hCaptcha iframes also appear in the Elements panel even when nothing is drawn on screen.Does invisible hCaptcha ever show a challenge?
hcaptcha.execute() runs, hCaptcha scores the session, and a session that meets its challenge criteria gets the standard challenge modal over the page. The paid "99.9% Passive" behavior setting pushes the challenge rate below 0.1% of users, but it does not remove challenges entirely.Is the token from invisible mode different from the checkbox token?
P1_ token, delivered to the same h-captcha-response field, verified at the same siteverify endpoint, single-use and valid for roughly 120 seconds. See the hCaptcha token explained for the full lifecycle.Can NoneCap solve invisible hCaptcha sitekeys?
type: "hcaptcha" plus the sitekey and page url to POST /v1/solves. Billing starts at one credit per challenge round, charged on success only, at $0.25 to $0.50 per 1,000 credits. New accounts get 100 free credits. See pricing.