Google reCAPTCHA v3 in Angular SSR with secure backend verification

Have you ever entered a website and, when filling in a form, had to "prove" that you are a human being?

That validation with slightly distorted text or image selection is known as reCAPTCHA, a Google security resource designed to protect websites against spam and abusive activity by distinguishing humans from automated bots.

In this article we are going to explain how to install reCAPTCHA step by step in an Angular project and verify the token in the backend.

Indexable summary

The important point in this implementation is that the browser only obtains a temporary reCAPTCHA token. The final verification must happen in the backend, where the private key is stored and where the response from Google can be trusted before accepting a form submission or API action.

If you are building a newer Angular SSR project and prefer hCaptcha, the related article hCaptcha in Angular with backend verification follows a similar security pattern. For APIs that should not expose credentials to the browser, see also the Nginx and FastAPI proxy pattern.

Current reCAPTCHA integrations should treat each token as short-lived and single-use: Google documents a two-minute validation window, and the backend must call siteverify before accepting the protected action. In modern Angular projects, especially standalone or SSR apps, keep the public site key in Angular but keep the secret key only in the backend.

The older ng-recaptcha examples in this article are useful to understand the flow, but before using them in a new Angular version, check package compatibility. If you want a more recent low-friction alternative, compare the same backend-verification pattern with Cloudflare Turnstile.

Production checklist for reCAPTCHA v3

  • Generate the token immediately before the protected action and verify it once, within two minutes.
  • Send the token in the request body over HTTPS; never place the secret key or a reusable credential in Angular.
  • On the backend, require success, the expected hostname and the expected action. For v3, evaluate the score using thresholds measured with your own traffic.
  • Reject duplicate, expired and malformed tokens and log error codes without storing unnecessary personal data.
  • Combine reCAPTCHA with rate limits, input validation, authorization and business rules. A CAPTCHA is a risk signal, not a replacement for API security.
  • Use separate development and production keys, monitor quotas and provide a usable retry path when verification fails.

Official references: server-side token verification, reCAPTCHA v3 actions and scores and current Angular HttpClient setup.

Here is the repository https://github.com/al118345/angular_recaptcha_gooogle for reference and the following explanatory video:

Register in Google reCAPTCHA

In this article we assume that you already have a Gmail account.

The first step is to register at https://www.google.com/recaptcha/admin/create. Once you access the page and log into your Gmail account, the following form will appear and must be filled in.

Important: create two registrations, one for the chosen domain and another one for localhost in order to perform tests before going into production.

reCAPTCHA registration form

Once the form has been completed, the next screen will appear with the information about the key needed to use the service.

Generated reCAPTCHA keys

Historical Angular HttpClientModule implementation

This section preserves the original NgModule and ng-recaptcha exercise. For a new project, check the package's compatibility with your Angular version, configure HTTP through the current Angular provider API and do not bypass peer-dependency conflicts with --force.

First of all, through the following repository link https://github.com/al118345/angular_recaptcha_gooogle/tree/main/src/app/components/asincrono you can access an example of this type of communication. For the backend side, you have the following example in the repository https://github.com/al118345/TestComunicacionApiRest_Angular.

To perform this installation, the project must be split between a frontend and a backend. On the frontend side, in this part of the project we chose to use an Angular library that allows communication with the backend. The library is calledHttpClient.

The original material also compared this approach with an XMLHttpRequest package. Modern browser applications normally use their framework HTTP client or fetch; the synchronous XMLHttpRequest example below is retained only to explain the evolution of the implementation.

With HttpClientModule, the communication will be asynchronous. The frontend handles the user interaction and the backend communicates with Google, but the user does not perceive that work. Navigation does not stop and you can, for example, show a loading state while waiting for the response on the page.

From Angular, we install the ng-recaptcha package with the following command:

In addition, we create the following service to communicate with the Python API.

We import the module into our app with the following code:

And we add the functionality to the component:

Finally, we modify the API so it can receive the frontend request by creating the following route in the project https://github.com/al118345/envio_email_api_python.

To finish, at https://www.google.com/u/3/recaptcha/admin/ you can consult a view like the following image where you can check how many people have logged in and the average score obtained.

reCAPTCHA control panel

Running example with async verification

Async Google reCAPTCHA example using HttpClient

Are you a robot? According to Google reCAPTCHA, at the moment you are:

You are a robot

Historical synchronous XMLHttpRequest version

Do not use synchronous XMLHttpRequest for a new web application: it blocks the main thread and damages usability. This complete section is preserved as a historical exercise; production code should use asynchronous HttpClient or fetch and show explicit loading, retry and error states.

Important: with this installation, the execution of your page will stop until the captcha result is obtained. That means it cannot show a loading message or perform any kind of scrolling meanwhile.

First of all, through the following repository link https://github.com/al118345/angular_recaptcha_gooogle/tree/main/src/app/components/sincrono you can access an example of this type of communication. For the backend you have the following example in the repository https://github.com/al118345/TestComunicacionApiRest_Angular.

To perform this installation, the project must be split between a frontend and a backend. The frontend will handle user interaction and the backend will communicate with Google.

From Angular we install the ng-recaptcha package with the following command:

In addition, we create the following service to communicate with the Python API.

We import the module into our app with the following code:

And we add the functionality to the component:

Finally, we modify the API so it can receive the frontend request by creating the following route in the project https://github.com/al118345/envio_email_api_python.

To finish, at https://www.google.com/u/3/recaptcha/admin/ you can consult a view like the following image where you can check how many people have logged in and the average score obtained.

reCAPTCHA control panel

Running example

Synchronous XmlHttpRequest example

Are you a robot? According to Google reCAPTCHA:

You are a robot