Skip to content

Angular

EU CAPTCHA provides dedicated packages for each major Angular version. Install the one that matches your Angular release.

Angular version Package Version npm
Angular 19 @myrasec/eu-captcha-angular19 1.0.1 npm
Angular 20 @myrasec/eu-captcha-angular20 1.0.1 npm
Angular 21 @myrasec/eu-captcha-angular21 1.0.1 npm

Server-side verification is identical regardless of frontend framework — see Server-Side Verification.


Installation

Install the package that matches your Angular version:

# Angular 19
npm i @myrasec/eu-captcha-angular19

# Angular 20
npm i @myrasec/eu-captcha-angular20

# Angular 21
npm i @myrasec/eu-captcha-angular21

The examples below use @myrasec/eu-captcha-angular19 — replace the package name with the one you installed.

Basic usage

Standalone component

Import EuCaptchaComponent directly into your component's imports array:

import { Component } from '@angular/core';
import { EuCaptchaComponent, isEuCaptchaDone } from '@myrasec/eu-captcha-angular19';

@Component({
  standalone: true,
  imports: [EuCaptchaComponent],
  template: `
    <form (submit)="handleSubmit($event)">
      <!-- your fields -->
      <eu-captcha sitekey="EUCAPTCHA_SITE_KEY" />
      <button type="submit">Submit</button>
    </form>
  `,
})
export class ContactFormComponent {
  handleSubmit(event: Event): void {
    event.preventDefault();
    if (!isEuCaptchaDone()) {
      // challenge not yet complete
      return;
    }
    // proceed with form submission
  }
}

NgModule-based app

Import EuCaptchaModule once in your AppModule (or any feature module):

import { NgModule } from '@angular/core';
import { EuCaptchaModule } from '@myrasec/eu-captcha-angular19';

@NgModule({
  imports: [EuCaptchaModule],
})
export class AppModule {}

Then use the component in any template within that module:

<eu-captcha sitekey="EUCAPTCHA_SITE_KEY" />

Inputs

Input Type Default Description
sitekey string Your public sitekey (required)
theme string "light" Visual theme: "light" or "dark"
width number 330 Widget width in pixels
height number 100 Widget height in pixels
widgetId string Custom widget ID. If omitted, an ID is auto-generated. Needed when calling euCaptcha.execute().
autostart boolean true Start the challenge automatically on init. Set to false to defer until euCaptcha.execute(widgetId) is called.

Outputs

Output Payload Description
completed string Emitted with the encoded token when the challenge completes.
expired Emitted when the token expires (60 minutes after completion).
error Emitted when the challenge fails due to a network or server error.

Checking completion before submit

The challenge runs asynchronously. Call isEuCaptchaDone() in your submit handler to confirm it has finished before sending the form to your server:

import { isEuCaptchaDone } from '@myrasec/eu-captcha-angular19';

handleSubmit(event: Event): void {
  event.preventDefault();

  if (!isEuCaptchaDone()) {
    // challenge not yet complete — show a message or wait
    return;
  }

  // proceed with form submission
}

Event bindings

Use (completed), (expired), and (error) to react to widget events without listening for window messages manually:

<eu-captcha
  sitekey="EUCAPTCHA_SITE_KEY"
  (completed)="onToken($event)"
  (expired)="onExpired()"
  (error)="onError()"
/>
onToken(token: string): void {
  // challenge complete — token is already written to the hidden input;
  // update state or enable your submit button here
  this.verified = true;
}

onExpired(): void {
  // token has expired — prompt the user to re-verify
  this.verified = false;
}

onError(): void {
  // network or server error during verification
  this.errorMsg = 'CAPTCHA failed. Please try again.';
}

Deferred execution

Set [autostart]="false" and provide a widgetId to suppress the automatic challenge, then trigger it programmatically:

<eu-captcha
  sitekey="EUCAPTCHA_SITE_KEY"
  widgetId="login-captcha"
  [autostart]="false"
  (completed)="submitForm($event)"
/>

<button (click)="execute()">Verify and submit</button>
execute(): void {
  (window as any).euCaptcha.execute('login-captcha');
}

This is useful for forms where you want the challenge to start only when the user clicks the submit button, or when the widget is not immediately visible on page load.

Listening for completion

If you prefer to use the euCaptchaDone window message instead of the (completed) output — for example, to enable a submit button from outside the component — listen for it in ngOnInit/ngOnDestroy:

import { Component, OnInit, OnDestroy } from '@angular/core';

@Component({ /* ... */ })
export class MyComponent implements OnInit, OnDestroy {
  private listener = (msg: MessageEvent) => {
    if (msg.data.type === 'euCaptchaDone') {
      this.submitEnabled = true;
    }
  };

  ngOnInit(): void {
    window.addEventListener('message', this.listener, false);
  }

  ngOnDestroy(): void {
    window.removeEventListener('message', this.listener, false);
  }
}

Retrieving the token

Once complete, the widget injects a hidden input into the surrounding <form>:

<input type="hidden" name="eu-captcha-response" value="<token>" />

If you are submitting via fetch or HttpClient, read the token from the DOM or use the (completed) output:

const token = document.querySelector('input[name="eu-captcha-response"]')?.value ?? '';

Pass it to your server endpoint and verify it with the verification API.