Quick Start
Get reForge Captcha running on your site in under 2 minutes. You need a registered account and a site key — that's it.
Create an account
Sign up via CodeForgeX SSO — no separate registration needed.
Sign Up FreeRegister your site
Go to Dashboard → Sites → Add Site and enter your domain. You'll get a site key and a secret key instantly.
Add SiteEmbed the widget
Add one script tag and one div to your HTML form. Replace YOUR_SITE_KEY with your site key.
Verify server-side
On form submission, send the token to our verify endpoint with your secret key. Never trust the client alone.
Register a Site
Before embedding a widget, register your domain in the dashboard. Each site gets a unique Site Key (public, used in the widget) and a Secret Key (private, used server-side).
What to fill in
- Site Name — A label for your own reference (e.g. "My Blog Contact Form").
- Domain — The domain without
https://, e.g.example.com. Subdomains are matched automatically if enabled. - Widget Type — Choose Checkbox, Invisible, Managed, or Image Challenge.
- Score Threshold — The minimum score (0.0–1.0) a request must achieve to pass without a manual challenge.
- Theme — Dark, Light, or Auto (follows the visitor's OS setting).
Embed the Widget
Add the reForge widget script once per page, then place the .reforge-captcha div inside your form.
<!-- Load the widget script once, anywhere on the page -->
<script src="https://reforgecaptcha.cloud/assets/js/widget.js" async defer></script>
<form method="POST" action="/submit">
<!-- Your form fields -->
<input type="email" name="email" placeholder="you@example.com">
<!-- The widget div -->
<div class="reforge-captcha"
data-sitekey="site_YOUR_SITE_KEY"
data-theme="auto"
data-type="checkbox">
</div>
<button type="submit">Submit</button>
</form>Data Attributes
| Attribute | Required | Values | Description |
|---|---|---|---|
data-sitekey | Yes | Your site key | The public site key from your dashboard. |
data-type | No | checkbox / invisible / managed / image | Widget challenge type. Defaults to checkbox. |
data-theme | No | auto / dark / light | Widget colour theme. Defaults to auto. |
data-size | No | normal / compact | Widget size variant. Defaults to normal. |
data-lang | No | en / nl / de / fr / es… | Widget UI language. Defaults to en. |
On successful verification the widget injects a hidden field named reforge-captcha-token into the parent form. This token is what you send to the verify API.
Server-Side Verification
When your form is submitted, read the reforge-captcha-token from the POST body and verify it against the API using your Secret Key. Never skip this step — the widget alone does not guarantee security.
PHP Example
<?php
$token = $_POST['reforge-captcha-token'] ?? '';
$secret = 'secret_YOUR_SECRET_KEY';
$response = file_get_contents('https://reforgecaptcha.cloud/api/verify', false,
stream_context_create(['http' => [
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => json_encode(['secret' => $secret, 'token' => $token]),
]])
);
$result = json_decode($response, true);
if (!$result['success']) {
// Bot or verification failed
http_response_code(403);
exit('CAPTCHA verification failed.');
}
if ($result['score'] < 0.5) {
// Suspicious — optionally require extra verification
exit('Request flagged as suspicious.');
}
// Human confirmed — process the form
?>Node.js Example
const fetch = require('node-fetch'); // or native fetch in Node 18+
app.post('/submit', async (req, res) => {
const token = req.body['reforge-captcha-token'];
const secret = 'secret_YOUR_SECRET_KEY';
const resp = await fetch('https://reforgecaptcha.cloud/api/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ secret, token }),
});
const result = await resp.json();
if (!result.success || result.score < 0.5) {
return res.status(403).json({ error: 'CAPTCHA failed' });
}
// Process the form...
res.json({ ok: true });
});Checkbox Widget
The classic one-click "I'm not a robot" challenge. The visitor clicks the checkbox, the risk engine scores the interaction in the background, and the token is injected into the form. Low friction, widely understood.
<div class="reforge-captcha"
data-sitekey="site_YOUR_SITE_KEY"
data-type="checkbox"
data-theme="auto">
</div>Best for: Contact forms, comment forms, newsletter sign-ups, general login forms.
Invisible Widget
No visible widget at all. The risk engine runs silently as the visitor interacts with the page. A token is generated automatically when the form is submitted. A small "Protected by reForge Captcha" badge appears in the corner to satisfy legal transparency requirements.
<div class="reforge-captcha"
data-sitekey="site_YOUR_SITE_KEY"
data-type="invisible">
</div>Best for: Checkout flows, high-conversion landing pages, any form where you want zero friction for real users.
submit event automatically. Make sure your submit button is a standard <button type="submit"> inside the same form element.Managed Widget
Managed mode is adaptive. For visitors with a high risk score (clearly human), the form submits without any visible challenge. For borderline scores, a checkbox is shown. For low scores (likely bot), a harder image challenge may be presented. You get the best of all modes automatically.
<div class="reforge-captcha"
data-sitekey="site_YOUR_SITE_KEY"
data-type="managed"
data-theme="dark">
</div>Best for: Login forms, registration pages, any situation where you want maximum bot blocking with minimum friction for real users.
Image Challenge Widget
Presents a grid of images where the visitor must select all matching a category (e.g. "select all traffic lights"). High cognitive difficulty for bots, straightforward for humans. Use this for high-security endpoints.
<div class="reforge-captcha"
data-sitekey="site_YOUR_SITE_KEY"
data-type="image"
data-theme="auto">
</div>Best for: Admin login pages, password reset flows, high-value form submissions, API endpoints exposed to the public.
API Reference
The reForge Captcha REST API is simple and JSON-based. All endpoints are at https://reforgecaptcha.cloud/api/.
POST /verify
Verify a captcha token server-side. This is the only endpoint most integrations need.
POST https://reforgecaptcha.cloud/api/verify
Content-Type: application/json
{
"secret": "secret_YOUR_SECRET_KEY",
"token": "TOKEN_FROM_FORM_SUBMISSION"
}curl -X POST https://reforgecaptcha.cloud/api/verify \
-H "Content-Type: application/json" \
-d '{"secret":"secret_YOUR_SECRET_KEY","token":"USER_TOKEN"}'POST /widget-token
Called internally by the widget JS to generate a scored token. You do not call this directly in your server code. It is documented here for transparency.
POST https:/reforgecaptcha.cloud/api/widget-token
Content-Type: application/json
{
"sitekey": "site_YOUR_SITE_KEY",
"type": "checkbox",
"hostname": "example.com",
"mouse_movements": 14,
"time_ms": 3200
}Response Format
The verify endpoint always returns a JSON object with the following fields:
{
"success": true,
"challenge_ts": "2025-01-15 14:32:07",
"hostname": "example.com",
"score": 0.92,
"action": "",
"error-codes": []
}| Field | Type | Description |
|---|---|---|
success | boolean | True if the token is valid and the score meets your site threshold. |
challenge_ts | string | UTC timestamp of when the challenge was completed. |
hostname | string | The hostname the widget was embedded on. |
score | float | Risk score from 0.0 (bot) to 1.0 (human). Use this for nuanced decisions. |
action | string | Optional action name set on the widget via data-action. |
error-codes | array | Empty on success. See error codes below on failure. |
Error Codes
When success is false, the error-codes array will contain one or more of the following:
| Code | Meaning |
|---|---|
missing-input-secret | The secret field was not sent in the request. |
invalid-input-secret | The secret key does not match any active site or is disabled. |
missing-input-response | The token field was not sent in the request. |
invalid-input-response | The token is not valid — possibly forged or already used. |
timeout-or-duplicate | The token has already been used or expired (2-minute TTL). |
low-score | The token is valid but the risk score is below your site threshold. |
method-not-allowed | Request was not a POST request. |
internal-error | An unexpected server error occurred. Retry the request. |
Framework Examples
Laravel
// In your controller
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
public function submit(Request $request)
{
$response = Http::post('https://reforgecaptcha.cloud/api/verify', [
'secret' => config('services.reforge.secret'),
'token' => $request->input('reforge-captcha-token'),
])->json();
if (!$response['success'] || $response['score'] < 0.5) {
return back()->withErrors(['captcha' => 'CAPTCHA verification failed.']);
}
// Process the form...
}WordPress
<?php
// In your form handler
$token = sanitize_text_field($_POST['reforge-captcha-token'] ?? '');
$secret = get_option('reforge_secret_key');
$response = wp_remote_post('https://reforgecaptcha.cloud/api/verify', [
'body' => json_encode(['secret' => $secret, 'token' => $token]),
'headers' => ['Content-Type' => 'application/json'],
]);
$result = json_decode(wp_remote_retrieve_body($response), true);
if (!$result['success']) {
wp_die('CAPTCHA verification failed.');
}Python / Django
import requests
def verify_captcha(token: str) -> bool:
resp = requests.post(
'https://reforgecaptcha.cloud/api/verify',
json={
'secret': 'secret_YOUR_SECRET_KEY',
'token': token,
},
timeout=5,
)
data = resp.json()
return data.get('success') and data.get('score', 0) >= 0.5
# In your view
def contact(request):
if request.method == 'POST':
token = request.POST.get('reforge-captcha-token', '')
if not verify_captcha(token):
return HttpResponseForbidden('CAPTCHA failed')
# process form...React / Next.js
// pages/api/submit.js (Next.js API route)
export default async function handler(req, res) {
if (req.method !== 'POST') return res.status(405).end();
const { 'reforge-captcha-token': token, ...formData } = req.body;
const verify = await fetch('https://reforgecaptcha.cloud/api/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: process.env.REFORGE_SECRET_KEY,
token,
}),
});
const result = await verify.json();
if (!result.success || result.score < 0.5) {
return res.status(403).json({ error: 'CAPTCHA failed' });
}
// Handle formData...
res.status(200).json({ ok: true });
}
// Component
// Load <script src="https://reforgecaptcha.cloud/assets/js/widget.js" /> in _document.js
// Then use the div in your form:
// <div className="reforge-captcha" data-sitekey="site_KEY" data-type="checkbox" />Questions?
If you run into an issue not covered here, reach out at hello@codeforgex.studio.
Get Started Free