5-minute integration
Four steps: create a project, drop in the script, mark your form, and verify on the server. If you already have a project, skip to step 2.
On WordPress? Do step 1 to get your keys, then install the captchaapi.eu plugin and skip the rest. It protects the login, registration, lost-password, and comment forms plus Contact Form 7 - activate it, paste your site key and secret key, and choose which forms to protect. No script tag, no markup, no backend code. Get it from the WordPress.org plugin directory.
1. Create a project and grab your keys
- Sign in and go to Projects.
- Click New Project, give it a name, and optionally add the domain(s) you'll embed the widget on. Leaving Allowed Domains empty means any origin can use the site key.
- On the project detail page you'll now see two keys:
- Site Key - public. Goes into your HTML.
- Secret Key - private. Shown once here after creation; goes into your backend config (not your HTML). You can re-reveal it later with password confirmation.
Copy the secret key somewhere durable (password manager, environment variable) before you navigate away. To reveal it again you'll need to enter your account password.
2. Include the script
Add one tag to your page, ideally just before </body>:
<script>window.CAPTCHA_SITE_KEY = 'YOUR_SITE_KEY';</script>
<script src="https://captchaapi.eu/captcha.js" defer></script>
The script auto-initialises every form that carries the data-captcha attribute. Nothing runs until the user interacts with that form.
3. Mark your form
Add data-captcha to the form, and optionally a [data-captcha-status] element to show the protection state to the user.
<form method="POST" action="/contact" data-captcha>
<input name="email" type="email" required>
<textarea name="message" required></textarea>
<span data-captcha-status></span>
<button type="submit">Send</button>
</form>
When the form submits, the widget inserts a hidden input named captchaapi_response.
Its value is an opaque string your backend sends to the verify endpoint. You don't need to
add it yourself.
4. Verify on your server
On Laravel? Skip step 4 and installcaptchaapi/laravel-composer require captchaapi/laravelgives you the validation rule, Blade component, and Livewire trait pre-wired. See the Laravel section in backend examples.
Put your secret key in an environment variable - never in code or client-side HTML. It's a
single key, format sk_live_...:
CAPTCHA_SECRET_KEY=sk_live_your_secret_here
On the endpoint that receives the form, read captchaapi_response and make one
server-to-server call to the verify endpoint. Send your secret key as a Bearer token and
let the form through only when success is true:
<?php
$response = $_POST['captchaapi_response'] ?? '';
$ch = curl_init('https://captchaapi.eu/api/v1/captcha/verify');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CAPTCHA_SECRET_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['response' => $response]),
]);
$body = curl_exec($ch);
curl_close($ch);
$result = json_decode($body, true);
if (! is_array($result) || ($result['success'] ?? false) !== true) {
http_response_code(422);
exit('Captcha failed.');
}
// proceed with the submission
HTTP 200 does not mean pass - always read the success field. Single-use and
replay protection are enforced on our side: a given captchaapi_response
verifies exactly once, so there's no replay cache for you to run.
That's it. Submissions with a missing or invalid response fail the check - reject them. See Backend examples for ready-made snippets in Laravel, plain PHP, Node.js, Python, and Ruby.
Tip: the verify response'sover_limitfield istruewhen the project is past its monthly challenge quota.successstill comes backtrue(visitors continue to be served on the same baseline difficulty curve as in-quota traffic) so your users aren't punished - it's a signal to upgrade.
Next: full API reference · widget configuration · backend examples.