Skip to content

Drupal Module

The EU CAPTCHA Drupal module integrates the EU CAPTCHA widget and server-side verification into your Drupal site with no custom code required. It supports Drupal core forms and several popular contributed modules out of the box.

  • Version: 1.0.0
  • Requires: Drupal 10+ or 11+, PHP 8.1+
  • License: BSD-2-Clause
  • Download: eu_captcha.zip

Supported forms

Form Module required
Drupal User Login
Drupal User Registration
Drupal Password Reset
Comments
Contact Forms Core Contact module
Webform submissions Webform module
Content (Node) Forms

We are happy to include support for more form types. Please contact support if you need additional destinations covered.

Installation

Option A — Upload via admin UI

  1. Download eu_captcha.zip.
  2. Go to Extend → Add new module and upload the zip file, or extract the eu_captcha folder to web/modules/custom/.
  3. Go to Extend, find EU-Captcha under the Security package, and enable it.

Option B — Drush

drush en eu_captcha
drush cr

After enabling, go to Configuration → System → EU-Captcha Settings (/admin/config/system/eu-captcha) to configure the module.

Configuration

Quick Setup

Click Quick Setup on the settings page. A modal opens loading the EU CAPTCHA dashboard in an embedded iframe. Complete the registration flow inside the modal — the module receives your sitekey and secret automatically via postMessage and saves them without you copying anything.

If you are on a different admin page, clicking Quick Setup in the notice bar navigates you to the settings page and opens the modal automatically.

Manual credentials

If you already have a sitekey and secret from the dashboard, enter them directly in the API Settings section.

Field Description
Public Sitekey Your public sitekey (UUID format). Safe to display on the frontend.
Secret Your secret key (Base64 format). Stored in Drupal configuration — never sent to the browser. The field is never pre-filled; leave it blank to keep the stored value.

Protected destinations

Check each form type you want to protect. The widget is injected and server-side verification is enforced only for the destinations you enable.

Destination Description
user_login Drupal user login form
user_register Drupal user registration form
user_pass Drupal password reset form
comment Comment forms for any content type
contact Core Contact module forms
webform Webform module submission forms
node Node add/edit forms for any content type

API options

Option Default Description
Check CDN / Proxy Headers On When enabled, the module reads the visitor's real IP from HTTP_CLIENT_IP, X-Forwarded-For, or X-Real-IP before falling back to the request IP. Enable this if your site sits behind a CDN or load balancer.
Failsafe Off When disabled (default), a network error reaching the verification API causes the form submission to be blocked. When enabled, transport-level errors (timeouts, DNS failures) are treated as a passed verification so submissions go through. Invalid tokens are still rejected regardless of this setting.

Widget Styling

Option Default Description
Theme Light Controls the widget colour scheme. Choose Light or Dark.
Height (px) Optional fixed height in pixels (minimum 48). Leave empty to use the widget default.
Width (px) Optional fixed width in pixels (minimum 1). Leave empty to use the widget default.

Save & Test

Use the Save & Test button to save your credentials and immediately run a live API call to verify that the sitekey and secret are correct.

Permissions

Permission Description
administer eu captcha Grants access to the settings page and dismissal of the admin notice. Assign to trusted administrators only.

How it works

  1. The module loads https://cdn.eu-captcha.eu/verify.js (with async defer) on every page where a protected form is rendered.
  2. It injects <div class="eu-captcha" data-sitekey="..."> inside each enabled form via hook_form_alter.
  3. On form submission, it reads eu-captcha-response from the POST data and sends a server-side request to https://api.eu-captcha.eu/v1/verify with the token, visitor IP, and User-Agent.
  4. Submissions are accepted or rejected based on the API response. Errors are logged to the Drupal watchdog (eu_captcha channel).

Custom integration

If you want to protect a form that the module does not handle natively, call the helper functions directly.

1. Render the widget in your form:

function mymodule_form_my_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
  _eu_captcha_attach_widget($form);
  $form['#validate'][] = '_eu_captcha_validate_token';
}

_eu_captcha_attach_widget() adds the <div class="eu-captcha" ...> element and enqueues verify.js. _eu_captcha_validate_token() is the standard form validation callback that checks the submitted token.

2. Verify a token manually:

$token  = \Drupal::request()->request->get('eu-captcha-response', '');
$passed = _eu_captcha_verify_token((string) $token);

if (!$passed) {
  // reject the submission
}

_eu_captcha_verify_token() returns true on success and false on failure. On network error it returns the value of the Failsafe setting.

Third-party services

The module communicates with the following external hosts:

Host Purpose
cdn.eu-captcha.eu Loads verify.js on pages with protected forms
api.eu-captcha.eu Server-side token verification on each form submission
app.eu-captcha.eu EU CAPTCHA dashboard loaded in the Quick Setup iframe

EU CAPTCHA sets no cookies and collects no personal data in the browser, making it GDPR-compliant without a cookie banner. Data sent to api.eu-captcha.eu on each verification: sitekey, secret, captcha response token, visitor IP address, visitor User-Agent string. Refer to the EU CAPTCHA Privacy Policy for details on how this data is processed.

Troubleshooting

The widget does not appear on a form

  • Confirm the destination is ticked under Protected Destinations and that you clicked Save Changes.
  • Check that the sitekey is saved and in valid UUID format. The settings page shows a ✅ / ❌ indicator next to the field.
  • Open browser DevTools → Network and verify that verify.js loaded without errors.
  • If a Content Security Policy is active, add cdn.eu-captcha.eu to script-src and connect-src.

Form submissions are blocked even for real users

  • Verify the sitekey and secret are correct using Save & Test.
  • Check that the sitekey was created for this domain. Each sitekey is tied to the domain specified at creation — create a new sitekey if needed.

Submissions always pass even for empty tokens

  • Confirm the secret is correct. A wrong secret puts the API into bypass mode (train: true) where all submissions appear successful.

The module blocks all submissions when your CDN is active

  • Enable Check CDN / Proxy Headers in API Settings so the module forwards the real visitor IP rather than the CDN's address.

After saving settings, the secret field is empty

  • This is expected. Drupal password fields are never pre-filled for security reasons. Leaving the field blank preserves the stored secret — only enter a value when you want to change it.

What happens during an EU CAPTCHA outage?

By default the module blocks submissions when the API is unreachable (fail closed). Enable Failsafe to accept submissions during outages (fail open). See the Failsafe option above.