Add a resilient, image-based human check to any form. One script tag, one div, no user accounts.
Insert this inside your form where you want the CAPTCHA. Everyone uses the same free public key. You can set data-width and data-height (default 260px × 60px). Use px or %, e.g. data-width="20%".
<div class="captchalink-widget"
data-sitekey="pk_free_captchalink_demo"
data-width="260px"
data-height="60px"></div>
<script src="https://captchal.ink/captchalink.js"></script>
The widget injects a hidden field captcha_token into your form. With method="POST" the token is sent in the request body (not in the URL). With method="GET" it appears in the URL. Prefer POST so the token is not visible in the address bar.
POST https://captchal.ink/api/verify.php
Content-Type: application/json
{
"private_key": "sk_free_captchalink_demo_secret",
"token": "token_from_captcha_token_field"
}
Response: {"success": true} or {"success": false, "error": "..."}. Only proceed when success === true.
<?php
$token = $_POST["captcha_token"] ?? $_GET["captcha_token"] ?? "";
if ($token === "") {
echo "Captcha FAIL";
exit;
}
$url = "https://captchal.ink/api/verify.php";
$data = [
"private_key" => "sk_free_captchalink_demo_secret",
"token" => $token
];
$options = [
"http" => [
"header" => "Content-Type: application/json\r\n",
"method" => "POST",
"content" => json_encode($data)
]
];
$context = stream_context_create($options);
$result = @file_get_contents($url, false, $context);
$response = $result ? json_decode($result, true) : null;
if ($response && ($response["success"] ?? false) === true) {
echo "Captcha OK";
} else {
echo "Captcha FAIL";
}
?>
<?php
$token = $_POST["captcha_token"] ?? $_GET["captcha_token"] ?? "";
if ($token === "") {
echo "Captcha FAIL";
exit;
}
$ch = curl_init("https://captchal.ink/api/verify.php");
$data = json_encode([
"private_key" => "sk_free_captchalink_demo_secret",
"token" => $token
]);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
$response = $result ? json_decode($result, true) : null;
if ($response && ($response["success"] ?? false) === true) {
echo "Captcha OK";
} else {
echo "Captcha FAIL";
}
?>
After the user completes the CAPTCHA and submits the form, your backend verifies the token. If verification succeeds, redirect them: header("Location: /welcome"); exit;
If you want a flow like our short links: solve captcha → redirect immediately (no form, no submit button), use the widget alone and listen for the token in JavaScript:
<div class="captchalink-widget"
data-sitekey="pk_free_captchalink_demo"
data-width="260px"
data-height="60px"></div>
<script src="https://captchal.ink/captchalink.js"></script>
<script>
window.addEventListener('message', function(e) {
if (!e.data || e.data.type !== 'captchalink:succeeded' || !e.data.token) return;
fetch('https://captchal.ink/api/verify.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
private_key: "sk_free_captchalink_demo_secret",
token: e.data.token
})
})
.then(function(r) { return r.json(); })
.then(function(data) {
if (data.success) {
window.location.href = '/your-page'; // redirect after solve
} else {
alert('Verification failed.');
location.reload();
}
});
});
</script>
Your backend endpoint should verify the token (see Example 1 or 2) and return {"success": true}. Or build a custom endpoint that verifies the token and returns the redirect URL in JSON, then use window.location.href = data.url;