Quickstart
Get KEPCA running on your site in under five minutes.
1. Add the widget script
Place the loader script in your page's <head> or before the closing </body> tag:
<script src="https://cdn.kepca.com/v1/maptcha.js" defer></script>For self-hosted deployments, point to your own domain:
<script src="https://captcha.yourdomain.com/v1/maptcha.js" defer></script>2. Place the widget in your form
Add the <maptcha-widget> custom element wherever you want the checkbox to appear:
<form id="login-form" action="/login" method="POST">
<input name="email" type="email" required />
<input name="password" type="password" required />
<maptcha-widget
data-sitekey="mpt_site_abc123"
data-theme="auto"
data-lang="en"
></maptcha-widget>
<button type="submit">Sign In</button>
</form>3. Listen for the verify event
When verification succeeds the widget emits a verify event containing the signed token:
<script>
const widget = document.querySelector('maptcha-widget');
widget.addEventListener('verify', (e) => {
// Attach the token to a hidden form field
const hidden = document.createElement('input');
hidden.type = 'hidden';
hidden.name = 'maptcha_token';
hidden.value = e.detail.token;
document.getElementById('login-form').appendChild(hidden);
});
widget.addEventListener('error', (e) => {
console.error('MAPtcha error:', e.detail.error);
});
</script>4. Verify the token on your backend
When the form is submitted, send the maptcha_token value to the KEPCA verify endpoint. Replace YOUR_SECRET_KEY with the secret key from your dashboard.
cURL
curl -X POST https://api.kepca.com/v1/siteverify \
-H "Content-Type: application/json" \
-d '{
"secret": "YOUR_SECRET_KEY",
"token": "TOKEN_FROM_FORM",
"ip": "CLIENT_IP_ADDRESS"
}'JavaScript (Node.js / Bun)
const res = await fetch('https://api.kepca.com/v1/siteverify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: process.env.MAPTCHA_SECRET,
token: req.body.maptcha_token,
ip: req.headers['x-forwarded-for'] || req.socket.remoteAddress,
}),
});
const { success, score } = await res.json();
if (!success) {
return res.status(403).json({ error: 'captcha_failed' });
}PHP
$response = file_get_contents('https://api.kepca.com/v1/siteverify', false,
stream_context_create([
'http' => [
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => json_encode([
'secret' => $_ENV['MAPTCHA_SECRET'],
'token' => $_POST['maptcha_token'],
'ip' => $_SERVER['REMOTE_ADDR'],
]),
],
])
);
$result = json_decode($response, true);
if (!$result['success']) {
http_response_code(403);
exit('Captcha verification failed');
}Python
import requests, os
result = requests.post("https://api.kepca.com/v1/siteverify", json={
"secret": os.environ["MAPTCHA_SECRET"],
"token": request.form["maptcha_token"],
"ip": request.remote_addr,
}).json()
if not result["success"]:
abort(403, "Captcha verification failed")Laravel
Using the official kepca/maptcha-laravel SDK:
composer require kepca/maptcha-laravel// config/services.php
'maptcha' => [
'secret' => env('MAPTCHA_SECRET'),
],// In your controller
use Kepca\Maptcha\Facades\Maptcha;
$result = Maptcha::verify($request->input('maptcha_token'), $request->ip());
if (!$result->isSuccess()) {
return back()->withErrors(['captcha' => 'Verification failed']);
}.NET
Using the official Kepca.Maptcha NuGet package:
dotnet add package Kepca.Maptcha// Program.cs
builder.Services.AddMaptcha(options => {
options.SecretKey = builder.Configuration["Maptcha:SecretKey"];
});// In your controller
public class LoginController : Controller
{
private readonly IMaptchaClient _maptcha;
public LoginController(IMaptchaClient maptcha) => _maptcha = maptcha;
[HttpPost]
public async Task<IActionResult> Login(LoginRequest req)
{
var result = await _maptcha.VerifyAsync(req.MaptchaToken, HttpContext.Connection.RemoteIpAddress?.ToString());
if (!result.IsHuman()) return Forbid();
// proceed with login
}
}WordPress
Install the KEPCA Captcha plugin from the WordPress plugin directory or upload the kepca-captcha folder to wp-content/plugins/.
- Go to Settings > KEPCA in the WordPress admin.
- Enter your Site Key and Secret Key.
- Select which forms to protect (login, registration, comments, WooCommerce checkout).
- Save changes.
The plugin automatically injects the widget into selected forms and verifies tokens server-side.
5. Configuration options
| Attribute | Values | Default |
|---|---|---|
data-sitekey | Your site key | (required) |
data-mode | adaptive, invisible, checkbox, always-challenge | adaptive |
data-theme | light, dark, auto | auto |
data-lang | en, tr, de, fr, es, ar, zh, ja, ru | auto-detect |
data-endpoint | Custom API URL | Production default |
Modes explained
- adaptive — the system decides the challenge level based on risk scoring. Most users pass invisibly.
- invisible — always attempt invisible verification first. Falls back to PoW only on failure.
- checkbox — always show the checkbox. Good for login pages where you want visible confirmation.
- always-challenge — always issue a challenge. Useful for high-security forms.
Next steps
- How It Works -- understand the request lifecycle and risk scoring
- Challenge Types -- all six challenge types with configuration
- Security -- rate limiting, key rotation, and token verification
- Enterprise -- team management, custom domains, and billing
- Widget API -- full list of attributes, events, and CSS custom properties
- REST API -- server-side endpoints for verification, events, and admin
