npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

angular-google-recaptcha-v3

v1.1.0

Published

A modern, standalone Google reCAPTCHA library for Angular supporting v2, v3, enterprise, reactive forms, and signals. Fully compatible with Angular versions 17.1–22

Downloads

421

Readme

angular-google-recaptcha-v3

A production-grade, enterprise-ready, tree-shakable Angular library for integrating Google reCAPTCHA v2 (Checkbox & Invisible), v3, and Enterprise. Fully compatible with Angular 17.1 through 22, SSR‑safe (Universal), and native Angular Signals‑ready.

Interactive Live Demo (Playground)


Key Features

  • Full Angular Compatibility: Out‑of‑the‑box support for Angular 17.1 to 22.
  • First‑Class Signals Support: Decoupled angular-google-recaptcha-v3/signals entry point for modern reactive applications.
  • SSR & Hydration Safe: Strictly guards DOM operations on the server side using isPlatformBrowser.
  • Zoneless Support: Executes heavy execution logic outside Zone.js context for high performance.
  • Dynamic Re‑Render: V2 widget automatically re‑renders when inputs (theme, size, tabIndex, siteKey) change! No manual cleanup required!
  • Tree‑Shakable Secondary Entry Points: Only import what you use (core, v2, v3, enterprise, signals, forms, testing).
  • ControlValueAccessor (CVA): Native support for Reactive Forms and Template‑driven Forms.
  • Region & Domain Flex: Easily switch between google.com and recaptcha.net (for restricted regions).

Folder & Entrypoint Architecture

To provide clean architectural separation and optimize bundle sizes, the codebase utilizes isolated secondary entry points:

  • angular-google-recaptcha-v3/core: Script loading lifecycle, dynamic configuration tokens.
  • angular-google-recaptcha-v3/v2: V2 Checkbox and Invisible component.
  • angular-google-recaptcha-v3/v3: Score‑based execution service.
  • angular-google-recaptcha-v3/enterprise: Score‑based Enterprise service.
  • angular-google-recaptcha-v3/forms: Angular Forms ControlValueAccessor directive.
  • angular-google-recaptcha-v3/signals: Reactive signals wrapper (Angular 16+ only).
  • angular-google-recaptcha-v3/testing: Mock services and providers for Jest/Karma test isolation.

Installation

npm install angular-google-recaptcha-v3

Configure your global settings during the application bootstrap phase:

Standard Module Bootstrapping (Angular 17+)

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RECAPTCHA_CONFIG, RecaptchaConfig } from 'angular-google-recaptcha-v3/core';
import { AppComponent } from './app.component';

const recaptchaConfig: RecaptchaConfig = {
  v2SiteKey: 'YOUR_V2_SITE_KEY',
  v3SiteKey: 'YOUR_V3_SITE_KEY',
  recaptchaDomain: 'google.com'
};

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [
    { provide: RECAPTCHA_CONFIG, useValue: recaptchaConfig }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

Standalone Bootstrapping (Angular 17+)

import { bootstrapApplication } from '@angular/platform-browser';
import { RECAPTCHA_CONFIG, RecaptchaConfig } from 'angular-google-recaptcha-v3/core';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, {
  providers: [
    {
      provide: RECAPTCHA_CONFIG,
      useValue: {
        v2SiteKey: 'YOUR_V2_SITE_KEY',
        v3SiteKey: 'YOUR_V3_SITE_KEY',
        useEnterprise: false
      } as RecaptchaConfig
    }
  ]
});

Usage Examples

1. reCAPTCHA v2 Checkbox with Reactive Forms

import { Component, signal } from '@angular/core';
import { FormGroup, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';
import { RecaptchaV2Component } from 'angular-google-recaptcha-v3/v2';
import { RecaptchaValueAccessorDirective } from 'angular-google-recaptcha-v3/forms';

@Component({
  selector: 'app-login',
  template: `
    <form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
      <input formControlName="username" type="text" placeholder="Username" />
      
      <!-- Toggle theme to test dynamic re-render! -->
      <div style="margin: 1rem 0;">
        <label style="margin-right: 1rem;">
          <input type="radio" [value]="'light'" (change)="setTheme('light')" [checked]="theme() === 'light'"> Light
        </label>
        <label>
          <input type="radio" [value]="'dark'" (change)="setTheme('dark')" [checked]="theme() === 'dark'"> Dark
        </label>
      </div>
      
      <!-- CVA Directive Automatically Binds value to FormGroup -->
      <angular-google-recaptcha-v3 
        [siteKey]="'YOUR_V2_SITE_KEY'"
        [theme]="theme()"
        formControlName="recaptcha">
      </angular-google-recaptcha-v3>
      
      <button [disabled]="loginForm.invalid" type="submit">Login</button>
    </form>
  `,
  standalone: true,
  imports: [ReactiveFormsModule, RecaptchaV2Component, RecaptchaValueAccessorDirective]
})
export class LoginComponent {
  theme = signal<'light' | 'dark'>('light');
  
  loginForm = new FormGroup({
    username: new FormControl('', Validators.required),
    recaptcha: new FormControl(null, Validators.required)
  });
  
  setTheme(newTheme: 'light' | 'dark'): void {
    this.theme.set(newTheme);
  }

  onSubmit() {
    console.log(this.loginForm.value);
  }
}

Dynamic Re‑Render Feature: RecaptchaV2Component now supports automatic re‑rendering when any of its inputs (siteKey, theme, size, tabIndex) change! This means you can dynamically switch between light/dark themes, or normal/compact/invisible sizes at runtime without any manual cleanup!

2. reCAPTCHA v3 Execution Service (RxJS & Promise)

import { Component, inject } from '@angular/core';
import { RecaptchaV3Service } from 'angular-google-recaptcha-v3/v3';

@Component({
  selector: 'app-payment',
  template: `
    <div style="display: flex; gap: 1rem;">
      <button (click)="processPaymentRxjs()">Pay Now (RxJS)</button>
      <button (click)="processPaymentAsync()">Pay Now (Async/Await)</button>
    </div>
  `,
  standalone: true
})
export class PaymentComponent {
  private recaptchaV3 = inject(RecaptchaV3Service);

  processPaymentRxjs(): void {
    this.recaptchaV3.execute('checkout').subscribe({
      next: (token) => {
        // Send token to backend API for verification assessment
        console.log('Action token resolved (RxJS):', token);
      },
      error: (err) => {
        console.error('Resolution error (RxJS):', err);
      }
    });
  }
  
  async processPaymentAsync(): Promise<void> {
    try {
      const token = await this.recaptchaV3.executeAsync('checkout');
      console.log('Action token resolved (Async/Await):', token);
    } catch (err) {
      console.error('Resolution error (Async/Await):', err);
    }
  }
}

3. Reactive Signals Integration (Angular 16+)

import { Component, effect, inject } from '@angular/core';
import { RecaptchaSignalService } from 'angular-google-recaptcha-v3/signals';
import { RecaptchaV2Component } from 'angular-google-recaptcha-v3/v2';

@Component({
  selector: 'app-signals-page',
  template: `
    <angular-google-recaptcha-v3 
      [siteKey]="'YOUR_V2_SITE_KEY'"
      (resolved)="recaptchaSignals.setToken($event)"
      (error)="recaptchaSignals.setError('Load Error occurred')">
    </angular-google-recaptcha-v3>

    @if (recaptchaSignals.verified()) {
      <p>Verification successful! Token: {{ recaptchaSignals.token() }}</p>
    }
  `,
  standalone: true,
  imports: [RecaptchaV2Component]
})
export class SignalsPageComponent {
  recaptchaSignals = inject(RecaptchaSignalService);
  
  constructor() {
    // Intercept state reactively
    effect(() => {
      if (this.recaptchaSignals.verified()) {
        console.log('User verified with token:', this.recaptchaSignals.token());
      }
    });
  }
}

4. Custom Error Handling

The library provides specifically typed error classes so you can easily catch and handle distinct failure scenarios (such as configuration issues, script loading failures, or Google rejecting the execution).

import { Component, inject } from '@angular/core';
import { RecaptchaV3Service } from 'angular-google-recaptcha-v3/v3';
import { 
  RecaptchaConfigurationError, 
  RecaptchaExecuteError, 
  RecaptchaLoadError 
} from 'angular-google-recaptcha-v3/core';

@Component({
  selector: 'app-error-demo',
  template: `<button (click)="submit()">Submit</button>`,
  standalone: true
})
export class ErrorDemoComponent {
  private recaptchaV3 = inject(RecaptchaV3Service);

  submit(): void {
    this.recaptchaV3.execute('submit_action').subscribe({
      next: (token) => console.log('Success:', token),
      error: (err: unknown) => {
        if (err instanceof RecaptchaConfigurationError) {
          console.error('Missing siteKey configuration:', err.message);
        } else if (err instanceof RecaptchaLoadError) {
          console.error('Failed to load Google reCAPTCHA script:', err.message);
        } else if (err instanceof RecaptchaExecuteError) {
          console.error('Google rejected execution:', err.message);
        } else {
          console.error('Unknown error:', err);
        }
      }
    });
  }

### 5. Tracking Script Load Status

You can inject `RecaptchaLoaderService` to monitor the real-time script loading state (`idle`, `loading`, `loaded`, or `error`). This is useful for rendering loading spinners or custom load-error screens:

```typescript
import { Component, inject } from '@angular/core';
import { AsyncPipe } from '@angular/common';
import { RecaptchaLoaderService } from 'angular-google-recaptcha-v3/core';

@Component({
  selector: 'app-load-monitor',
  standalone: true,
  imports: [AsyncPipe],
  template: `
    @if (status$ | async; as status) {
      @if (status === 'loading') {
        <div>Loading reCAPTCHA API...</div>
      } @else if (status === 'loaded') {
        <div>reCAPTCHA ready!</div>
      } @else if (status === 'error') {
        <div style="color: red;">Failed to load script.</div>
      }
    }
  `
})
export class LoadMonitorComponent {
  private loader = inject(RecaptchaLoaderService);
  public status$ = this.loader.scriptLoadStatus$;
}

SSR (Server‑Side Rendering) Support

The library contains native safety guards. When rendering on a server environment, the script loading will gracefully bypass DOM manipulation and execute empty mock resolutions. This ensures standard universal/SSR pipelines do not trigger window or document reference execution errors.


Unit Testing Setup

The library provides testing mocks under the /testing sub‑entrypoint.

import { TestBed } from '@angular/core/testing';
import { RecaptchaV3Service } from 'angular-google-recaptcha-v3/v3';
import { RecaptchaMockV3Service } from 'angular-google-recaptcha-v3/testing';

describe('MyService', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        { provide: RecaptchaV3Service, useClass: RecaptchaMockV3Service }
      ]
    });
  });

  // Your unit tests...
});

Migration Guide (From ng-recaptcha)

If migrating from legacy packages like ng-recaptcha:

  1. Remove old configurations and modules from your app imports.
  2. Update imports from ng-recaptcha to angular-google-recaptcha-v3/v2, angular-google-recaptcha-v3/v3, or angular-google-recaptcha-v3/core.
  3. Provide settings using the unified configuration injection token: RECAPTCHA_CONFIG.
  4. Replace event listeners (resolved) with signals using RecaptchaSignalService if using Angular 16+.

FAQ & Troubleshooting

Why is my reCAPTCHA script not loading?

  • Double‑check that you provided v2SiteKey or v3SiteKey inside the RECAPTCHA_CONFIG InjectionToken.
  • Verify that your network has direct access to google.com or switch config settings to use recaptchaDomain: 'recaptcha.net'.

Is it compatible with Angular Zoneless mode?

Yes. The library is built with zoneless capability, utilizing custom element zones via NgZone.runOutsideAngular to handle script callbacks without triggering change detection cycles redundantly.