DOCUMENTATION
Integration Guide
Everything you need to embed CaptchaKit in your signup forms and verify tokens on your server.
Integrate with Claude Code
The fastest way to add CaptchaKit to your app
Copy the prompt below, fill in your site key and API key from your dashboard, and paste it into Claude Code. Claude will find your form, add the widget, and wire up server-side verification — usually in under a minute.
I'm adding CaptchaKit to my app. CaptchaKit replaces the standard CAPTCHA checkbox with a short arcade game — users play for ~10 seconds to prove they're human. It's bot-proof and has zero friction for real users.
How it works:
- A <script> tag loads the widget from https://captchakit.com/widget.js
- A <div data-gamecaptcha data-site-key="..." data-game="connect4"> renders the game inside my form
- When the player passes, a signed token is stored on the div's data-token attribute and a gamecaptcha:pass event fires on document
- I must verify the token server-side before processing the form: POST https://captchakit.com/api/verify with header Authorization: Bearer <api_key> and body { token, siteKey }
- Tokens expire in 10 minutes and can only be used once
My credentials (from my CaptchaKit dashboard at captchakit.com/dashboard):
- Site key: [PASTE YOUR SITE KEY — starts with gc_]
- API key: [PASTE YOUR API KEY — starts with cgv_]
- Game I want to use: connect4
Please:
1. Add the CaptchaKit widget.js script to my page
2. Add the widget div inside my existing form where the CAPTCHA should go
3. Update my form submit handler to read the token and block submission if it's missing
4. Add server-side token verification in my form handler — reject the request if verification failsTips for best results
- • Paste your actual site key and API key — Claude will put them in the right places
- • Tell Claude which specific form or file to modify if your project has more than one
- • If Claude asks to install a package, there is no npm package — the widget is a plain script tag
- • After Claude makes changes, run your dev server and play a game to confirm the token is being sent
Quick Start
The simplest possible integration — two lines of HTML, one verification call.
<!-- Step 1: Add CaptchaKit script to your page (before </body>) -->
<script src="https://captchakit.com/widget.js"></script>
<!-- Step 2: Add the widget inside your form -->
<form id="signup-form">
<input type="email" name="email" placeholder="Email" />
<div
data-gamecaptcha
data-site-key="gc_connect4_your_key_here"
data-game="connect4"
data-theme="dark"
></div>
<!-- data-theme: "dark" (default) or "light" — match your site's background -->
<button type="submit">Sign up</button>
</form>
<!-- Step 3: Read the token on submit -->
<script>
document.getElementById('signup-form').addEventListener('submit', async (e) => {
e.preventDefault();
const token = e.target.querySelector('[data-gamecaptcha]').dataset.token;
if (!token) return alert('Please complete the game first.');
const res = await fetch('/api/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: e.target.email.value, gamecaptchaToken: token }),
});
});
</script>IMPORTANT
Always verify the token on your server before processing form submissions. Client-side checks alone are insufficient — a bot could submit directly to your API.
embed.js Script Tag
The embed.js approach works in any HTML page — no bundler, no framework required. Drop a single <script> tag, add the widget div, and listen for the gc:pass event.
<!-- 1. Load the script (once, anywhere on the page) -->
<script src="https://captchakit.com/embed.js" async></script>
<!-- 2. Drop the widget div wherever you want it in your form -->
<form id="my-form">
<input type="email" name="email" placeholder="Email address" />
<div data-site-key="gc_xxxxx" data-game="connect4"></div>
<button type="submit">Sign up</button>
</form>
<!-- 3. Listen for the gc:pass event to read the token -->
<script>
document.addEventListener('gc:pass', function (e) {
var token = e.detail.token;
// Store it so your submit handler can read it
document.getElementById('my-form').dataset.gcToken = token;
});
document.getElementById('my-form').addEventListener('submit', async function (e) {
e.preventDefault();
var token = this.dataset.gcToken;
if (!token) {
alert('Please complete the game first.');
return;
}
// Send the token to your server for verification
await fetch('/api/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: this.email.value,
gcToken: token,
}),
});
});
</script>DATA ATTRIBUTES
data-site-keyrequiredYour site key from the dashboard (e.g. gc_xxxxx).
data-gameGame ID to show. Defaults to connect4. Options: connect4, whackabot, colormatch, fruitsorter, mazerunner, pacmanlite, stackit.
gc:pass EVENT DETAIL
{ token: string, siteKey: string, game: string }The event fires on documentand bubbles up from a sentinel element at the widget's original position. Send the token to your server and verify it with POST /api/verify.
How Verification Works
The token flow in 4 steps.
Widget loads
The script tag renders the game inside the div. The player's site key is read from the data-site-key attribute.
Player passes the game
When the human wins, the widget calls our server with the site key. The server confirms the key is valid and issues a signed JWT.
Token written to the element
The signed token is stored in data-token on the widget div. Your form submit handler reads it.
You verify server-side
Your server calls POST /api/verify with the token and site key. We return { success: true }. Only then do you process the form.
Token format (JWT, expires in 10 minutes)
{ siteKey: "gc_connect4_xxx", gameId: "connect4", iat: ..., exp: ... }Server Verification
Call this endpoint from your server — never from the browser.
/api/verifyRequest headers
Authorization: Bearer YOUR_API_KEYContent-Type: application/jsonRequest body
{ "token": "...", "siteKey": "gc_..." }✅ Success response
{ "success": true, "gameId": "connect4" }❌ Failure response
{ "success": false, "error": "Invalid or expired token" }// Express example
app.post('/api/signup', async (req, res) => {
const { email, gamecaptchaToken } = req.body;
// Verify the token server-side
const verifyRes = await fetch('https://captchakit.com/api/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY', // from your dashboard
},
body: JSON.stringify({
token: gamecaptchaToken,
siteKey: 'gc_connect4_your_key_here',
}),
});
const { success, gameId } = await verifyRes.json();
if (!success) {
return res.status(400).json({ error: 'Bot detected. Please try again.' });
}
// ✅ Token is valid — proceed with signup
await createUser(email);
res.json({ ok: true });
});Framework Guides
Complete examples for the most common stacks.
'use client'; // Next.js App Router
import { useRef, useState } from 'react';
export default function SignupForm() {
const widgetRef = useRef<HTMLDivElement>(null);
const [loading, setLoading] = useState(false);
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const token = widgetRef.current?.dataset.token;
if (!token) {
alert('Please complete the game first!');
return;
}
setLoading(true);
const res = await fetch('/api/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: (e.target as HTMLFormElement).email.value,
gamecaptchaToken: token,
}),
});
setLoading(false);
if (res.ok) window.location.href = '/welcome';
};
return (
<form onSubmit={handleSubmit}>
<input type="email" name="email" required />
{/* The widget script must be loaded in a script tag,
e.g. in <head> or via next/script with strategy="beforeInteractive" */}
<div
ref={widgetRef}
data-gamecaptcha
data-site-key="gc_connect4_your_key_here"
data-game="connect4"
/>
<button type="submit" disabled={loading}>
{loading ? 'Signing up...' : 'Sign up'}
</button>
</form>
);
}Game Comparison
Choose the game that fits your form and audience.
| GAME | AVG. TIME | DIFFICULTY | BEST FOR | MOBILE |
|---|---|---|---|---|
| 🔴Connect 4 | 15s | Easy | General signups | ✓ |
| 🍒Pac-Man Lite | 8s | Easy | Gaming sites | ✓ |
| 🔨Whack-a-Bot | 12s | Medium | Login forms | ✓ |
| 🎨Color Match | 10s | Medium | Signup flows | ✓ |
| 🌀Maze Runner | 20s | Hard | High-security forms | ✓ |
| 🍎Fruit Sorter | 15s | Medium | E-commerce checkouts | ✓ |
| 🧱Stack It | 10s | Easy | Comment forms | ✓ |
API Reference
All endpoints at a glance.
/api/verify🔑 Auth requiredVerify a game completion token. Requires Authorization: Bearer header.
/api/game-completeCalled by the embed widget internally. Returns a signed JWT on game pass.
/api/auth/me🔑 Auth requiredGet the current authenticated user, their API key, and owned games.