Skip to content
Myra EU CAPTCHA Online Help Updated · 06 Oct 2026

PHP

For PHP, there are two packages. Both verify the token on the server and give the same result object.

Select the package

Select the package for the PHP version of your application:

Package PHP Technology
myra-security-gmbh/eu-captcha From version 8.0 Named arguments, type declarations, HTTP with Guzzle (guzzlehttp/guzzle ^6.0 or ^7.0)
myra-security-gmbh/eu-captcha-old From version 5.0 No other dependencies, HTTP with file_get_contents() and a stream context

Requirements

The following requirements are met:

Requirement Value
PHP From version 8.0 for eu-captcha, from version 5.0 for eu-captcha-old
Composer Access to the command line of the server
Credentials Public sitekey and secret from the Details view

Install the package

Install the package for PHP 8 with the ^2.0.1 version constraint:

composer require "myra-security-gmbh/eu-captcha:^2.0.1"

Attention

Without the ^2.0.1 version constraint, Composer on PHP 5 to PHP 7 installs the old version 1.x without a message. Its EU_Captcha class does not agree with the examples on this page. The version constraint also excludes version 2.0.0: it sends request fields that the API rejects, so every verification fails. Keep the quotation marks, so that cmd.exe on Windows does not remove the ^ character.

For PHP 5 to PHP 7, install this package instead:

composer require myra-security-gmbh/eu-captcha-old

Embed the widget

Add the script link to each page that has a form to protect:

<script src="https://cdn.eu-captcha.eu/verify.js" async defer></script>

Add the widget to the form:

<div class="eu-captcha" data-sitekey="EUCAPTCHA_SITE_KEY"></div>

Note

In a single-page application with React, Vue, or Angular, embed the widget with the applicable npm package. Then the PHP package does only the verification on the server.

Verify the token

Verify the transmitted token on the server:

<?php

use Myrasec\EuCaptcha;

$captcha = new EuCaptcha(
    sitekey: EUCAPTCHA_SITE_KEY,
    secret:  EUCAPTCHA_SECRET_KEY,
);

$result = $captcha->validate();

if (!$result->success()) {
    // Reject the form submission
}

With eu-captcha-old, give the values as an associative array instead:

<?php

use Myrasec\EuCaptcha;

$captcha = new EuCaptcha([
    'sitekey' => EUCAPTCHA_SITE_KEY,
    'secret'  => EUCAPTCHA_SECRET_KEY,
]);

$result = $captcha->validate();

validate() reads the token from $_POST['eu-captcha-response']. If this field is not in $_POST, the method reads the body of the request as JSON. With eu-captcha, it does this only if the content type of the request contains application/json. Only a simple value counts as a token. The method ignores an array or an object in this position. If the method finds no token, it sends an empty token to the API. The API then counts the attempt all the same. The method gets the IP address of the visitor from the headers of the request.

Options

These options are available:

Option Type Default Effect
sitekey string — Public sitekey. The value is necessary.
secret string — Secret key. The value is necessary and must not occur in the browser.
failDefault bool true Return value for the network condition and the token condition when the API is not available. true permits the transmission, false rejects it.
checkCdnHeaders bool true Gets the IP address of the visitor from the HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR, and HTTP_X_REAL_IP headers before REMOTE_ADDR is used. Set the value to false if the server is not behind an upstream system, or if you give the IP address yourself.
verifyUrl string Address of the production environment Overwrites the address of the /verify endpoint. Use the option for tests.
credentialsUrl string Address of the production environment Overwrites the address of the /verify-credentials endpoint.

Only eu-captcha for PHP 8 has this additional option:

Option Type Default Effect
client ?Client null Your own instance of Guzzle for different settings or for tests.

The result object

validate() gives an EuCaptchaResult object with four methods:

Method Gives true when
success() the API was available, the token is valid, and the API did not set train.
successNetwork() the call of the API completed without a network error or a transmission error.
successToken() the API reported the transmitted token as valid.
isTrain() the API set the train field. The API then did not verify the token. Without a response from the API, the method gives null.

success() counts a response with train: true as a failure. But successToken() gives the unchanged success value of the response.

The API sets train when training mode is on for the sitekey, or when its protection is off. An unknown sitekey or a wrong secret does not set train. Then the verification fails with success: false.

The separate query tells a failed challenge from a malfunction of the API:

<?php

$result = $captcha->validate();

if (!$result->successNetwork()) {
    // Could not reach the API — consider logging or alerting
}

if (!$result->successToken()) {
    // Token was rejected — the submission is likely automated
}

Give the token and the IP address yourself

For different field names, give the token and the IP address yourself:

<?php

$token    = $_POST['my-captcha-field'] ?? '';
$clientIp = $_SERVER['REMOTE_ADDR'];

$result = $captcha->validate($token, $clientIp);

Verify the credentials

With verifyCredentials(), you verify the sitekey and the secret without a token from the browser, for example at the start of the application:

<?php

$captcha = new EuCaptcha(sitekey: EUCAPTCHA_SITE_KEY, secret: EUCAPTCHA_SECRET_KEY);

if (!$captcha->verifyCredentials()) {
    // Credentials are invalid or the API is unreachable — log and alert
}

For a network error or an API error, the method gives false and causes no exception. Thus, the call is also safe during the initialization.

See Verify the sitekey and the secret.

Symfony and Laravel

For the two frameworks, see Symfony and Laravel.

Full example

See React and PHP.