How to find an hCaptcha sitekey.

An hCaptcha sitekey is the public UUID that identifies a widget, and it is sitting in the page right now. The fastest way to read it is the data-sitekey attribute in DevTools. For invisible widgets it hides in the render() call or on the iframe URL instead. Here is how to find it every way, and what the sitekey gets you.

What a sitekey is

Every hCaptcha widget is tied to a sitekey, a UUID like f5ab1c2d-7e8f-4a9b-b1c2-d3e4f5a6b7c8 that tells hCaptcha which site the challenge belongs to. It is public on purpose: the browser has to know it to render the widget, so it always appears somewhere in the page. The matching secret key lives on the site owner’s server and is used only at siteverify time, so you never see it from the front end.

To solve an hCaptcha programmatically you need two things: the sitekey and the url of the page the challenge appears on. Both are front-end values you can read in a few seconds.

Method 1: inspect the widget in DevTools

The classic drop-in widget renders a <div class="h-captcha"> with the key on its data-sitekey attribute. Right-click the captcha, choose Inspect, and read it straight off the element:

The h-captcha div
<!-- The classic drop-in: the key is the data-sitekey attribute. -->
<div class="h-captcha"
     data-sitekey="f5ab1c2d-7e8f-4a9b-b1c2-d3e4f5a6b7c8"></div>

<!-- After a solve, hCaptcha injects the token into a hidden field: -->
<textarea name="h-captcha-response">P1_eyJ0eXAi...UV8w</textarea>

If the element collapsed into an iframe, look at the wrapping <div> just outside it. The data-sitekey lives on the container, not on the iframe hCaptcha injects.

Method 2: View Source and search for data-sitekey

For server-rendered widgets the attribute is already in the raw HTML. Open View Source (or press Ctrl-U), then Ctrl-F for data-sitekey. The UUID right after it is the key. If View Source comes up empty, the widget is rendered by JavaScript after load, so search the live DOM in the Elements panel instead, or use Method 3.

Method 3: pull it from the invisible widget

Invisible widgets often render no visible box and no data-sitekey div. The key still has to reach hCaptcha, so it shows up in one of two places. The first is the explicit hcaptcha.render() call in the page’s script:

hcaptcha.render()
<!-- Explicit render: the key is the first argument's sitekey field. -->
<script>
  hcaptcha.render('captcha-box', {
    sitekey: 'f5ab1c2d-7e8f-4a9b-b1c2-d3e4f5a6b7c8',
    size: 'invisible',
    callback: onSolved
  });
</script>

The second is the hCaptcha iframe itself. Find the iframe in the Elements panel and read the sitekey= parameter on its src URL:

iframe src ?sitekey=
<!-- Invisible widgets often expose the key only on the iframe URL. -->
<iframe
  src="https://newassets.hcaptcha.com/captcha/v1/.../static/hcaptcha.html#frame=challenge&id=...&sitekey=f5ab1c2d-7e8f-4a9b-b1c2-d3e4f5a6b7c8&...">
</iframe>

A reliable catch-all: search the rendered DOM for the literal string sitekey. Between the container attribute, the render call, and the iframe URL, it turns up every time.

Method 4: read it programmatically

If you are already driving the page with a headless browser, let it read the key for you. In Playwright, grab the attribute off the first matching element:

Playwright · Python
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    page = p.chromium.launch().new_page()
    page.goto("https://target.example/login")

    # Read the sitekey straight off the rendered widget.
    sitekey = page.locator("[data-sitekey]").first.get_attribute("data-sitekey")
    print(sitekey, page.url)   # the two values NoneCap needs

The same idea in Puppeteer uses page.$eval:

Puppeteer · Node
import puppeteer from "puppeteer";

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("https://target.example/login");

// Read the sitekey straight off the rendered widget.
const sitekey = await page.$eval("[data-sitekey]", (el) =>
  el.getAttribute("data-sitekey")
);
console.log(sitekey, page.url()); // the two values NoneCap needs

The selector [data-sitekey] covers the common case. For an invisible widget with no such attribute, read the iframe src instead and parse the sitekey query parameter out of it.

Sitekey types and what to send

The sitekey itself does not tell you the widget mode, but the mode decides what you send NoneCap. Here is how the three line up:

Where the sitekey lives per widget type, and the matching NoneCap request
Widget typeWhere the sitekey livesWhat you tell NoneCap
CheckboxA visible widget renders; data-sitekey sits on its <div class="h-captcha">type: "hcaptcha" + sitekey + url
InvisibleNo visible box; the key is in the hcaptcha.render() call or the iframe ?sitekey=type: "hcaptcha" + sitekey + url
Enterprise (rqdata)Same data-sitekey, but the page also passes a fresh rqdata blob per challengetype: "hcaptcha_enterprise" + sitekey + url + rqdata

What the sitekey and url get you

Once you have the sitekey and the page url, you have everything NoneCap needs to mint a token. POST them to /v1/solves, block for the result with ?wait=N, and read back a real P1_ token:

Create an hCaptcha solve
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/login"
  }'
Response
{
  "id":              "solve_01HQF7K3JKWZX",
  "object":          "solve",
  "type":            "hcaptcha",
  "status":          "solved",
  "token":           "P1_eyJ0eXAi...UV8w",
  "credits_charged": 1
}

Submit that token as the form’s h-captcha-response and the page treats it as a real pass. NoneCap returns tokens that invisible and enterprise sitekeys accept, not just image-recognition output. The full solve object and every language sample are in the API reference.

Enterprise sitekeys need more than the sitekey

For enterprise hCaptcha, the sitekey alone is not enough. Each challenge is bound to a fresh rqdata blob that the page generates per request and ties to the session, so you have to capture that blob too and send it with type: "hcaptcha_enterprise". Reading data-sitekey looks identical; the extra step is grabbing the live rqdata. See hCaptcha enterprise rqdata for how to find and forward it.

Wiring this into a real run? The same sitekey read drops straight into a Playwright or Puppeteer flow: read the key, mint the token, inject it into h-captcha-response, and submit.

Last updated June 2026.

Frequently asked

What does an hCaptcha sitekey look like?
It is a UUID, eight hex characters then three groups of four then twelve, for example f5ab1c2d-7e8f-4a9b-b1c2-d3e4f5a6b7c8. It is public by design: it identifies the site that owns the widget and is safe to read from page source. The secret half (the key used at siteverify) stays on the site owner’s server and is never exposed in the browser.
I cannot find data-sitekey in the HTML. Where else is it?
Invisible widgets often render no <div class="h-captcha"> at all. Look for the sitekey passed into the hcaptcha.render() call in the page’s JavaScript, or open the hCaptcha iframe in DevTools and read the sitekey= parameter on its src URL. Searching the rendered DOM for the string sitekey finds it in every case.
Is the sitekey the same as the secret key?
No. The sitekey is the front-end identifier baked into the widget and is meant to be public. The secret key is a separate value the site keeps server-side and sends to api.hcaptcha.com/siteverify to validate a token. NoneCap only needs the public sitekey and the page url; it never sees or needs the secret.
What can I do once I have the sitekey and url?
Send both to POST /v1/solves and NoneCap mints a real P1_ token you submit as the form’s h-captcha-response. Billing is one credit per hCaptcha challenge round, charged on success only, and credits run $0.40 to $0.50 per 1,000. New accounts get 100 free credits. See pricing.

Start solving hCaptcha in minutes.

100 free credits on signup. Pay per solve, credits never expire, failed solves auto-refunded.