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.

STEP 01

Create an account

Sign up via CodeForgeX SSO — no separate registration needed.

Sign Up Free
STEP 02

Register your site

Go to Dashboard → Sites → Add Site and enter your domain. You'll get a site key and a secret key instantly.

Add Site
STEP 03

Embed the widget

Add one script tag and one div to your HTML form. Replace YOUR_SITE_KEY with your site key.

STEP 04

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).
Your Secret Key must never appear in frontend code, JavaScript files, or public repositories. It is only used in server-side code.

Embed the Widget

Add the reForge widget script once per page, then place the .reforge-captcha div inside your form.

HTMLFrontend
<!-- 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

AttributeRequiredValuesDescription
data-sitekeyYesYour site keyThe public site key from your dashboard.
data-typeNocheckbox / invisible / managed / imageWidget challenge type. Defaults to checkbox.
data-themeNoauto / dark / lightWidget colour theme. Defaults to auto.
data-sizeNonormal / compactWidget size variant. Defaults to normal.
data-langNoen / 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.

Invisible mode attaches to the form's 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.

Request
POST https://reforgecaptcha.cloud/api/verify
Content-Type: application/json

{
  "secret": "secret_YOUR_SECRET_KEY",
  "token":  "TOKEN_FROM_FORM_SUBMISSION"
}
cURL
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":  []
}
FieldTypeDescription
successbooleanTrue if the token is valid and the score meets your site threshold.
challenge_tsstringUTC timestamp of when the challenge was completed.
hostnamestringThe hostname the widget was embedded on.
scorefloatRisk score from 0.0 (bot) to 1.0 (human). Use this for nuanced decisions.
actionstringOptional action name set on the widget via data-action.
error-codesarrayEmpty 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:

CodeMeaning
missing-input-secretThe secret field was not sent in the request.
invalid-input-secretThe secret key does not match any active site or is disabled.
missing-input-responseThe token field was not sent in the request.
invalid-input-responseThe token is not valid — possibly forged or already used.
timeout-or-duplicateThe token has already been used or expired (2-minute TTL).
low-scoreThe token is valid but the risk score is below your site threshold.
method-not-allowedRequest was not a POST request.
internal-errorAn 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