1. Install the package

Install EasyCaptchas with Composer:

composer require surlinio/easycaptchas

The source code and releases are available on GitHub.

Open GitHub repository

2. Start the session and create a code

session_start();
require __DIR__ . '/vendor/autoload.php';

use Surlinio\EasyCaptchas\EasyCaptchas;

$captcha = new EasyCaptchas();
$challenge = $captcha->create('contact');

3. Add the form fields

<input type="hidden" name="captcha_id"
       value="<?= htmlspecialchars($challenge['id']) ?>">

<img src="/captcha-image.php?id=<?= urlencode($challenge['id']) ?>&amp;scope=contact"
     alt="Six-character security code">

<input name="captcha_answer" maxlength="6" autocomplete="off">

4. Create the image endpoint

session_start();
require dirname(__DIR__) . '/vendor/autoload.php';

use Surlinio\EasyCaptchas\EasyCaptchas;

$captcha = new EasyCaptchas();

try {
    $png = $captcha->renderPng(
        (string) ($_GET['id'] ?? ''),
        (string) ($_GET['scope'] ?? 'default')
    );
} catch (RuntimeException) {
    http_response_code(404);
    exit;
}

header('Content-Type: image/png');
header('Cache-Control: no-store');
echo $png;

5. Verify the answer on the server

$valid = $captcha->verify(
    $_POST['captcha_id'] ?? '',
    $_POST['captcha_answer'] ?? '',
    'contact'
);

if (!$valid) {
    $errors['captcha_answer'] = 'The code is incorrect or has expired.';
}
Always validate on the server. JavaScript can improve the experience, but it must never decide whether a submission is valid.

Free under the MIT License

You can use, modify and distribute EasyCaptchas at no cost. No subscription or license key is required.

Security defaults

  • Cryptographically random codes
  • HMAC-protected answers in the session
  • Per-form scope binding
  • Five-minute lifetime
  • Maximum of three attempts
  • Single use after successful verification