The reCaptcha module adds a Javascript with hook_captcha(). I want to add another attribute "type" to this script tag. I can't find a hook to achieve this.

Here is the code from the recaptcha.module (line 118):

$captcha['form']['recaptcha_widget'] = [
        '#markup' => '<div' . new Attribute($attributes) . '></div>',
        '#suffix' => $noscript,
        '#attached' => [
          'html_head' => [
                '#tag' => 'script',
                '#attributes' => [
                  'src' => Url::fromUri($recaptcha_src, ['query' => ['hl' => \Drupal::service('language_manager')->getCurrentLanguage()->getId()], 'absolute' => TRUE])->toString(),
                  'async' => TRUE,
                  'defer' => TRUE,

When I try to access the script tag with e.g. hook_page_attachments_alter() or any other hook_preprocess_xxxx() it is missing. I also tried to increase my module weight.

  • The code you tried already, especially the hook_page_attachments_alter() version would be helpful for figuring out what needs to be possibly adjusted to get this to work. Aug 22, 2020 at 14:43
  • @StefanosPetrakis I didn't write any code, I just set a breakpoint and tried to find the script tag added by the recaptcha module. But it was not included in the data array (added after execution of this hook). Aug 23, 2020 at 8:45

2 Answers 2


I would suggest using a #process callback and avoid code duplication. This is what such a solution could look like:

 * Implements hook_element_info_alter().
function my_module_element_info_alter(array &$element) {
  if (isset($element['captcha'])) {
    $element['captcha']['#process'][] = '_custom_recaptcha_process';

 * Add type attribute to recaptcha form element.
 * @return array
 *   The processed element.
 * @see captcha_element_info()
 * @see image_captcha_element_info_alter()
function _custom_recaptcha_process($element) {
  $recatchaWidgetHtmlHead = &$element['captcha_widgets']['recaptcha_widget']['#attached']['html_head'] ?? [];
  array_walk($recatchaWidgetHtmlHead, function(&$captcha_widget) { 
    if ($captcha_widget[1] === 'recaptcha_api') {
      $captcha_widget[0]['#attributes']['type'] = 'value';
  return $element;

and this would be the output:

enter image description here

Good luck!


Since hook_captcha() is a hook, you can override it by implementing it in your own custom module.

As long as your module has higher weight, it will run after recaptcha_captcha.

So basically copy all the code in recaptcha_captcha and rename the function name to mymodule_captcha and add the type to the #attributes array and you're golden.

In this rare case, the only way appears to be patching the module directly.

Hopefully you're using a composer managed site and all you have to do is create a patch and have composer auto apply it for you.

  • Sorry, I tried that before, but the hook does not invoke mymodule_captcha(). That's somthing I also don't understand. Something is missing here. Aug 22, 2020 at 11:57
  • @JoachimFeltkamp are you on D7 or D8 or D9? and you doubled checked your custom module is enabled?
    – No Sssweat
    Aug 22, 2020 at 12:14
  • and did you rename the mymodule part to the actual name of your module? and you checked with the modules weight module that your custom module has indeed higher weight?
    – No Sssweat
    Aug 22, 2020 at 12:21
  • 1
    I am on D8 and D9. Yes I checked all this. The hook_catcha() function implements a new captcha type. The hook seems only to be invoked, when I select reCAPTCHA (from mymodule) as default captcha in the Captcha config form. Aug 22, 2020 at 14:52
  • @JoachimFeltkamp after trying it out myself. I experienced the same issues. When I put a breakpoint on the custom module, it never breaks. Which means the hook is not ran. However, if add the type directly to the reCaptcha module, it works. Thus, seems the only way is to alter the module directly. Hopefully, you're using a composer manage site, and all you have to do is create a patch and have composer auto apply it for you when you do composer install or composer update
    – No Sssweat
    Aug 23, 2020 at 1:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.