natbox.io

CaptchaBox / Docs

CaptchaBox documentation

Last updated 6 November 2026 · By Mohammad AlSaraf

Everything you need to protect a form: two lines of HTML and one server check. Free for 10,000 checks a month.

Guides for your platform

Quick start

1. Get keys. Sign in to the client area (a free account is enough) and add your site and its domain. You get a site key, which is public, and a secret, which stays on your server. Subdomains work automatically. To try things first, use the test keys.

2. Add the widget inside your form:

<script src="https://captcha.natbox.io/v1/widget.js" async defer></script>

<form action="https://natbox.io/contact" method="post">
  <input name="email" type="email">
  <div class="captchabox" data-sitekey="YOUR_SITE_KEY"></div>
  <button>Send</button>
</form>

The widget starts its check as soon as the page loads, and puts a token in a hidden field called captchabox-response. If the visitor presses Send before the check is done, the form waits and then sends itself.

3. Check the token on your server before you accept the form:

POST https://captcha.natbox.io/v1/siteverify
Content-Type: application/x-www-form-urlencoded

secret=YOUR_SECRET&response=TOKEN_FROM_THE_FORM

Accept the form only if the answer has "success": true. Never skip this step: the hidden field alone proves nothing.

The siteverify API

Send secret and response as a form (application/x-www-form-urlencoded) or as JSON. The answer always comes with HTTP 200, like reCAPTCHA's and Turnstile's:

{"success": true, "challenge_ts": "2026-11-06T10:15:02Z", "hostname": "example.com", "error-codes": []}
FieldMeaning
successtrue if the token is valid, unused, under 5 minutes old and belongs to this secret's site.
challenge_tsWhen the visitor's puzzle was issued (UTC).
hostnameThe site the visitor solved it on. Check it if one key serves several domains.
error-codesWhy it failed: missing-input-secret, invalid-input-secret, missing-input-response, invalid-input-response, timeout-or-duplicate (expired or already used), rate-limited.

Each token works once and for 5 minutes. The widget gets a fresh one by itself before the old one expires. If your page sends the form with JavaScript and stays open, call captchabox.reset() after each send.

Widget options

AttributeValuesWhat it does
data-sitekeyyour site keyRequired.
data-themeauto, light, darkauto (default) follows the visitor's system setting.
data-sizenormal, compact, invisibleinvisible shows only a small badge.
data-startauto, focus, clickWhen the check starts: on page load (default), when the visitor first uses the form, or when they click the box.
data-langauto, en, ar, es, de, fr, pt, trauto uses the page's language.
data-compatrecaptcha, turnstileAlso fills g-recaptcha-response or cf-turnstile-response, for code written for those services.
data-response-field-namea field nameUse another name than captchabox-response.
data-callback, data-expired-callback, data-error-callbackglobal function namesCalled with the token, when it expires, or with an error code.

JavaScript API

CallWhat it does
captchabox.render(element, {sitekey, theme, size, start, callback})Puts a widget in an element you choose, for pages built with JavaScript. Returns the widget's id.
captchabox.getResponse(id)The current token, or an empty string.
await captchabox.execute(id)Starts the check if needed and resolves with a token. Handy for forms sent with fetch.
captchabox.reset(id)Throws away the token and starts again.

The id can be the number from render, the element itself, or a CSS selector. Leave it out to use the first widget on the page. To call render as soon as the script is ready, load it as widget.js?onload=myFunction.

const token = await captchabox.execute();
await fetch('/api/contact', { method: 'POST', body: JSON.stringify({ email, token }) });
captchabox.reset();

Test keys

These work on any domain, including localhost, and do not count against your limit:

Site keySecretsiteverify answers
cb_test_passcbs_test_passalways success: true
cb_test_failcbs_test_failalways success: false

Widget error codes

Passed to data-error-callback: domain-not-allowed (add the domain to the site in the client area), invalid-sitekey, quota-exceeded (the month's limit is reached), net (CaptchaBox could not be reached) and not-solved.

Limits and plans

Free: 10,000 successful checks a month and up to 10 sites. Plus: 100,000 a month for $2. Pro: 1,000,000 a month for $9. Counts start again on the 1st of each month (UTC). Details on the CaptchaBox page.

Privacy

The widget sets no cookies and stores nothing in the browser. Visitor IP addresses are kept in memory for at most 10 minutes, to limit abuse, and never logged. Details in our privacy policy. Most sites can list CaptchaBox under "spam protection" in their own privacy policy without a consent banner.