Extended
Advanced integration options, verification flow, and API reference.
SDK (Preferred)
bun add @requestguard/js
import RequestGuard from "@requestguard/js";
RequestGuard.captcha({
el: ".rg-captcha",
theme: "dark",
autoVerify: false,
onVerify: (result) => {
document.getElementById("contact-send").disabled = !result.token;
}
});
<div class="rg-captcha"></div>
<button id="contact-send" disabled>Send</button>
Script Tag
<script src="https://requestguard.com/js/captcha.js"></script>
<div class="rg-captcha"></div>
<button id="contact-send" disabled>Send</button>
<script>
RequestGuard.captcha({
el: ".rg-captcha",
theme: "dark",
autoVerify: false,
onVerify: (result) => {
document.getElementById("contact-send").disabled = !result.token;
}
});
</script>
What onVerify Means
When the user completes the challenge, the widget exchanges the proof-of-work solution for a short-lived verification token from RequestGuard.
With the default autoVerify: true, the SDK verifies that token in the browser by calling https://requestguard.com/api/captcha/siteverify. onVerify fires after that background check and gives you { success, token, challenge_ts }. Use this mode when the CAPTCHA is only gating client-side UX and you do not need to verify the token again on form submit.
With autoVerify: false, onVerify fires as soon as the widget returns a token and gives you { success: true, token }. Use this mode for contact forms, signup forms, checkout flows, and any workflow where your backend must verify the submitted token before processing the action.
Tokens expire quickly and are single-use by default, which prevents replay. If browser auto-verification consumes a token, a later backend verification of the same token will fail unless you explicitly call siteverify with keepToken: true.
Contact Form Pattern
<form id="contact-form">
<input name="email" type="email" required />
<textarea name="message" required></textarea>
<div class="rg-captcha"></div>
<button id="contact-send" disabled>Send</button>
</form>
<script src="https://requestguard.com/js/captcha.js"></script>
<script>
const send = document.getElementById("contact-send");
RequestGuard.captcha({
el: ".rg-captcha",
autoVerify: false,
onVerify: (result) => {
send.disabled = !result.token;
},
onReset: () => {
send.disabled = true;
},
onError: () => {
send.disabled = true;
}
});
</script>
On submit, read the hidden rg-captcha-token field from the form and verify it on your server before accepting the submission.
Invisible Mode
Use invisible mode to run verification in the background without showing the widget.
RequestGuard.captcha({
el: ".rg-captcha",
invisible: true,
autoVerify: false,
onVerify: (result) => {
if (result.token) {
document.getElementById("contact-send").disabled = false;
}
}
});
Language Override
Language is auto-detected from the browser by default. To force a specific language:
RequestGuard.captcha({
el: ".rg-captcha",
language: "de"
});
Verify Tokens Server-Side
For protected actions, set autoVerify: false and verify the submitted rg-captcha-token on your own backend.
POST https://requestguard.com/api/captcha/siteverify
{
"response": "<token-from-client>",
"origin": "https://example.com"
}
Response
{
"success": true,
"challenge_ts": "2026-01-27T10:11:12.000Z"
}
origin is optional, but recommended. It should be the origin where the widget was embedded. RequestGuard compares it with the origin recorded when the challenge was issued.
If you need to verify in the browser and then verify again on your backend, call siteverify with keepToken: true for the browser-side verification. Most form integrations should avoid that and use autoVerify: false instead.
Options
| Option | Type | Description |
|---|---|---|
el | string | HTMLElement | Target element (required) |
theme | ”auto” | “light” | “dark” | Widget theme (default: auto) |
invisible | boolean | Hide the widget and auto-run verification (default: false) |
onVerify | function | Called after background verification when autoVerify is enabled, or after token redemption when autoVerify: false |
onError | function | Called when the widget reports an error |
onReset | function | Called when the widget resets |
fieldName | string | Hidden input name (default: rg-captcha-token) |
autoVerify | boolean | Verify token automatically in the browser (default: true). Set to false when your backend will verify the submitted token. |
verifyUrl | string | Override verification endpoint |
api | string | Override API base used by the widget (default: /api/captcha/) |
host | string | Override RequestGuard host for self-hosting |
origin | string | Override origin sent to RequestGuard (default: window.location.origin) |
instanceId | string | Custom instance ID for multi-captcha pages |
title | string | Iframe title for accessibility |
width | string | Iframe width (default: 100%) |
height | string | Iframe height (default: 90px) |
borderRadius | string | Iframe border radius (default: 12px) |
Listening for Verification
You can listen via the instance or a DOM event:
<script>
const instance = RequestGuard.captcha({ el: ".rg-captcha" });
instance.on("verified", (event) => {
console.log("verified token", event.detail.token);
});
document.addEventListener("rg:captcha:verified", (event) => {
console.log("verified token", event.detail.token);
});
</script>
API Endpoints
Challenge
POST https://requestguard.com/api/captcha/challenge
Returns challenge data and a challenge token for the widget.
Redeem
POST https://requestguard.com/api/captcha/redeem
Body:
{
"token": "<challenge-token>",
"solutions": [123, 456, 789]
}
Returns a short-lived verification token.
Site Verify
POST https://requestguard.com/api/captcha/siteverify
Body:
{
"response": "<verification-token>",
"origin": "https://example.com",
"keepToken": false
}
Notes
- No dashboard setup or domain registration is required.
- The widget is delivered via iframe to keep branding and updates consistent.
- Tokens expire automatically (typically within 20 minutes).
- Use server-side verification for security.
- Do not verify the same token twice unless the first verification uses
keepToken: true.