{"id":14978685,"url":"https://github.com/chvarkov/google-recaptcha","last_synced_at":"2026-01-18T05:17:16.431Z","repository":{"id":43646252,"uuid":"301532582","full_name":"chvarkov/google-recaptcha","owner":"chvarkov","description":"Google recaptcha module for NestJS❤","archived":false,"fork":false,"pushed_at":"2025-03-28T16:48:02.000Z","size":1450,"stargazers_count":84,"open_issues_count":0,"forks_count":13,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-12T14:56:13.296Z","etag":null,"topics":["google-recaptcha","google-recaptcha-v2","google-recaptcha-v3","nestjs","nestjs-backend","nestjs-library","nestjs-module","recaptcha"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chvarkov.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-10-05T20:32:45.000Z","updated_at":"2025-03-28T16:43:23.000Z","dependencies_parsed_at":"2023-02-18T17:30:19.842Z","dependency_job_id":"50930e2c-6711-43df-a132-d82bc49e3964","html_url":"https://github.com/chvarkov/google-recaptcha","commit_stats":{"total_commits":205,"total_committers":11,"mean_commits":"18.636363636363637","dds":"0.35609756097560974","last_synced_commit":"44f12d014fe48dbb299fabd72e6fdf43f7606572"},"previous_names":[],"tags_count":59,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chvarkov%2Fgoogle-recaptcha","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chvarkov%2Fgoogle-recaptcha/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chvarkov%2Fgoogle-recaptcha/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chvarkov%2Fgoogle-recaptcha/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chvarkov","download_url":"https://codeload.github.com/chvarkov/google-recaptcha/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254553958,"owners_count":22090417,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["google-recaptcha","google-recaptcha-v2","google-recaptcha-v3","nestjs","nestjs-backend","nestjs-library","nestjs-module","recaptcha"],"created_at":"2024-09-24T13:58:11.641Z","updated_at":"2026-01-18T05:17:16.415Z","avatar_url":"https://github.com/chvarkov.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Google recaptcha module\n\nThis package provides protection for endpoints using [reCAPTCHA](https://www.google.com/recaptcha/about/) for [NestJS](https://docs.nestjs.com/) REST and GraphQL applications. By integrating with reCAPTCHA, this package helps to prevent automated abuse such as spam and bots, improving the security and reliability of your application.\n\n[![NPM Version](https://img.shields.io/npm/v/@nestlab/google-recaptcha.svg)](https://www.npmjs.com/package/@nestlab/google-recaptcha)\n[![Licence](https://img.shields.io/npm/l/@nestlab/google-recaptcha.svg)](https://github.com/chvarkov/google-recaptcha/blob/master/LICENSE)\n[![NPM Downloads](https://img.shields.io/npm/dm/@nestlab/google-recaptcha.svg)](https://www.npmjs.com/package/@nestlab/google-recaptcha)\n[![Build status](https://github.com/chvarkov/google-recaptcha/actions/workflows/test.yml/badge.svg)](https://github.com/chvarkov/google-recaptcha/actions/workflows/test.yml)\n[![Coverage Status](https://chvarkov.github.io/google-recaptcha/badges/coverage.svg)](https://github.com/chvarkov/google-recaptcha/actions)\n\n\n## Table of Contents\n\n* [Installation](#installation)\n* [Changes](#changes)\n* [Configuration](#configuration)\n  * [Options](#options)\n  * [REST application](#rest-application)\n    * [reCAPTCHA v2](#rest-recaptcha-v2)\n    * [reCAPTCHA v3](#rest-recaptcha-v3)\n    * [reCAPTCHA Enterprise](#rest-recaptcha-enterprise)\n  * [Graphql application](#graphql-application)\n    * [reCAPTCHA v2](#graphql-recaptcha-v2)\n    * [reCAPTCHA v3](#graphql-recaptcha-v3)\n    * [reCAPTCHA Enterprise](#graphql-recaptcha-enterprise)\n* [Usage](#usage)\n  * [REST application](#usage-in-rest-application)\n  * [Graphql application](#usage-in-graphql-application)\n  * [Validate in service](#validate-in-service)\n  * [Validate in service (Enterprise)](#validate-in-service-enterprise)\n  * [Dynamic Recaptcha configuration](#dynamic-recaptcha-configuration)\n  * [Error handling](#error-handling)\n* [Contribution](#contribution)\n* [License](#license)\n\nUsage example [here](https://github.com/chvarkov/google-recaptcha-example)\n\n\n## Installation\n\n```\n$ npm i @nestlab/google-recaptcha\n```\n\n## Changes\n\nThe list of changes made in the project can be found in the [CHANGELOG.md](./CHANGELOG.md) file.\n\n## Configuration\n\n### Options\n\n**GoogleRecaptchaModuleOptions**\n\n| Property          | Description |\n|-------------------|-------------|\n| `response`        | **Required.**\u003cbr\u003e Type: `(request) =\u003e string`\u003cbr\u003e Function that returns response (recaptcha token) by request |\n| `secretKey`       | Optional.\u003cbr\u003e Type: `string`\u003cbr\u003e Google recaptcha secret key. Must be set if you don't use reCAPTCHA Enterprise |\n| `debug`           | Optional.\u003cbr\u003e Type: `boolean` \u003cbr\u003e Default: `false` \u003cbr\u003e Enables logging requests, responses, errors and transformed results |\n| `logger`          | Optional.\u003cbr\u003e Type: `Logger` \u003cbr\u003e Default: `new Logger()` \u003cbr\u003e Instance of custom logger that extended from Logger (@nestjs/common) |\n| `skipIf`          | Optional.\u003cbr\u003e Type: `boolean` \\| `(request) =\u003e boolean \\| Promise\u003cboolean\u003e` \u003cbr\u003e Function that returns true if you allow the request to skip the recaptcha verification. Useful for involing other check methods (e.g. custom privileged API key) or for development or testing |\n| `enterprise`      | Optional.\u003cbr\u003e Type: `GoogleRecaptchaEnterpriseOptions` \u003cbr\u003e Options for using reCAPTCHA Enterprise API. Cannot be used with `secretKey` option.  |\n| `network`         | Optional.\u003cbr\u003e Type: `GoogleRecaptchaNetwork` \\| `string`\u003cbr\u003e Default: `GoogleRecaptchaNetwork.Google` \u003cbr\u003e If your server has trouble connecting to https://google.com then you can set networks:\u003cbr\u003e `GoogleRecaptchaNetwork.Google` = 'https://www.google.com/recaptcha/api/siteverify'\u003cbr\u003e`GoogleRecaptchaNetwork.Recaptcha` = 'https://recaptcha.net/recaptcha/api/siteverify'\u003cbr\u003e or set any api url |\n| `score`           | Optional.\u003cbr\u003e Type: `number` \\| `(score: number) =\u003e boolean`\u003cbr\u003e Score validator for reCAPTCHA v3 or enterprise. \u003cbr\u003e `number` - minimum available score. \u003cbr\u003e `(score: number) =\u003e boolean` - function with custom validation rules. |\n| `actions`         | Optional.\u003cbr\u003e Type: `string[]`\u003cbr\u003e Available action list for reCAPTCHA v3 or enterprise. \u003cbr\u003e You can make this check stricter by passing the action property parameter to `@Recaptcha(...)` decorator. |\n| `remoteIp`        | Optional.\u003cbr\u003e Type: `(request) =\u003e string`\u003cbr\u003e A function that returns a remote IP address from the request |\n| `axiosConfig`     | Optional.\u003cbr\u003e Type: `AxiosRequestConfig`\u003cbr\u003e Allows to setup proxy, response timeout, https agent etc... |\n| `global`     \t\t| Optional.\u003cbr\u003e Type: `boolean` \u003cbr\u003e Default: `false` Defines a module in the [global scope](https://docs.nestjs.com/modules#global-modules). |\n\n**GoogleRecaptchaEnterpriseOptions**\n\n| Property        | Description |\n|-----------------|-------------|\n| `projectId`     | **Required.**\u003cbr\u003e Type: `string`\u003cbr\u003e Google Cloud project ID |\n| `siteKey`       | **Required.**\u003cbr\u003e Type: `string`\u003cbr\u003e [reCAPTCHA key](https://cloud.google.com/recaptcha-enterprise/docs/keys) associated with the site/app. |\n| `apiKey`        | **Required.**\u003cbr\u003e Type: `string`\u003cbr\u003e API key associated with the current project. \u003cbr\u003eMust have permission `reCAPTCHA Enterprise API`. \u003cbr\u003e You can manage credentials [here](https://console.cloud.google.com/apis/credentials). |\n\n\nThe module provides two static methods for configuration: `forRoot` and `forRootAsync`.\n\n**forRoot**\n\n\u003e forRoot(options: GoogleRecaptchaModuleOptions): DynamicModule\n\nThe `forRoot` method accepts a `GoogleRecaptchaModuleOptions` object that configures the module. This method should be used in the root `AppModule`. \u003cbr/\u003eExample usage:\n\n```typescript\n@Module({\n    imports: [\n        GoogleRecaptchaModule.forRoot({\n            secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,\n            response: req =\u003e req.headers.recaptcha,\n        })\n    ],\n})\nexport class AppModule {\n}\n```\n\n**forRootAsync**\n\n\u003e forRootAsync(options: ModuleAsyncOptions): DynamicModule\n\nThe `forRootAsync` method is similar to `forRoot`, but allows for asynchronous configuration.\u003cbr/\u003e\nIt accepts a `GoogleRecaptchaModuleAsyncOptions` object that returns a configuration object or a Promise that resolves to a configuration object. \u003cbr/\u003e\nRead more about [ConfigService](https://docs.nestjs.com/techniques/configuration#getting-started) and [custom getter function](https://docs.nestjs.com/techniques/configuration#custom-getter-functions).\n\nExample usage:\n\n```typescript\n@Module({\n    imports: [\n        GoogleRecaptchaModule.forRootAsync({\n            imports: [ConfigModule],\n            useFactory: (configService: ConfigService) =\u003e configService.googleRecaptchaOptions,\n            inject: [ConfigService],\n        })\n    ],\n})\nexport class AppModule {\n}\n```\n\n### REST application\n\n#### REST reCAPTCHA V2\n\n```typescript\n@Module({\n    imports: [\n        GoogleRecaptchaModule.forRoot({\n            secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,\n            response: req =\u003e req.headers.recaptcha,\n            skipIf: process.env.NODE_ENV !== 'production',\n        }),\n    ],\n})\nexport class AppModule {\n}\n```\n\n**Tip: header names transforming to lower case.**\n\n**For example:** If you send 'Recaptcha' header then use `(req) =\u003e req.headers.recaptcha`\n\n\u003cbr/\u003e\n\n#### REST reCAPTCHA V3\n\n```typescript\n@Module({\n    imports: [\n        GoogleRecaptchaModule.forRoot({\n            secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,\n            response: req =\u003e req.headers.recaptcha,\n            skipIf: process.env.NODE_ENV !== 'production',\n            actions: ['SignUp', 'SignIn'],\n            score: 0.8,\n        }),\n    ],\n})\nexport class AppModule {\n}\n```\n\n**Tip: header names transforming to lower case.**\n\n**For example:** If you send 'Recaptcha' header then use `(req) =\u003e req.headers.recaptcha`\n\n\u003cbr/\u003e\n\n#### REST reCAPTCHA Enterprise\n\n```typescript\n@Module({\n    imports: [\n        GoogleRecaptchaModule.forRoot({\n            response: (req) =\u003e req.headers.recaptcha,\n            skipIf: process.env.NODE_ENV !== 'production',\n            actions: ['SignUp', 'SignIn'],\n            score: 0.8,\n            enterprise: {\n                projectId: process.env.RECAPTCHA_ENTERPRISE_PROJECT_ID,\n                siteKey: process.env.RECAPTCHA_ENTERPRISE_SITE_KEY,\n                apiKey: process.env.RECAPTCHA_ENTERPRISE_API_KEY,\n            },\n        }),\n    ],\n})\nexport class AppModule {\n}\n```\n\n**Tip: header names transforming to lower case.**\n\n**For example:** If you send 'Recaptcha' header then use `(req) =\u003e req.headers.recaptcha`\n\n### Graphql application\n\n#### Graphql reCAPTCHA V2\n\n```typescript\n@Module({\n    imports: [\n        GoogleRecaptchaModule.forRoot({\n            secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,\n            response: (req: IncomingMessage) =\u003e (req.headers.recaptcha || '').toString(),\n            skipIf: process.env.NODE_ENV !== 'production',\n        }),\n    ],\n})\nexport class AppModule {\n}\n```\n\n**Tip: header names transforming to lower case.**\n\n**For example:** If you send 'Recaptcha' header then use `(req: IncomingMessage) =\u003e (req.headers.recaptcha || '').toString()`\n\n\u003cbr/\u003e\n\n#### Graphql reCAPTCHA V3\n\n```typescript\n@Module({\n    imports: [\n        GoogleRecaptchaModule.forRoot({\n            secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,\n            response: (req: IncomingMessage) =\u003e (req.headers.recaptcha || '').toString(),\n            skipIf: process.env.NODE_ENV !== 'production',\n            actions: ['SignUp', 'SignIn'],\n            score: 0.8,\n        }),\n    ],\n})\nexport class AppModule {\n}\n```\n\n**Tip: header names transforming to lower case.**\n\n**For example:** If you send 'Recaptcha' header then use `(req: IncomingMessage) =\u003e (req.headers.recaptcha || '').toString()`\n\n\u003cbr/\u003e\n\n#### Graphql reCAPTCHA Enterprise\n\n```typescript\n@Module({\n    imports: [\n        GoogleRecaptchaModule.forRoot({\n            response: (req: IncomingMessage) =\u003e (req.headers.recaptcha || '').toString(),\n            skipIf: process.env.NODE_ENV !== 'production',\n            actions: ['SignUp', 'SignIn'],\n            score: 0.8,\n            enterprise: {\n                projectId: process.env.RECAPTCHA_ENTERPRISE_PROJECT_ID,\n                siteKey: process.env.RECAPTCHA_ENTERPRISE_SITE_KEY,\n                apiKey: process.env.RECAPTCHA_ENTERPRISE_API_KEY,\n            },\n        }),\n    ],\n})\nexport class AppModule {\n}\n```\n\n**Tip: header names transforming to lower case.**\n\n**For example:** If you send 'Recaptcha' header then use `(req) =\u003e req.headers.recaptcha`\n\n\n**Configuration for reCAPTCHA Enterprise**\n\n```typescript\n@Module({\n    imports: [\n        GoogleRecaptchaModule.forRoot({\n            response: (req) =\u003e req.headers.recaptcha,\n            skipIf: process.env.NODE_ENV !== 'production',\n            actions: ['SignUp', 'SignIn'],\n            score: 0.8,\n            enterprise: { \n                projectId: process.env.RECAPTCHA_ENTERPRISE_PROJECT_ID, \n                siteKey: process.env.RECAPTCHA_ENTERPRISE_SITE_KEY, \n                apiKey: process.env.RECAPTCHA_ENTERPRISE_API_KEY, \n            },\n        }),\n    ],\n})\nexport class AppModule {\n}\n```\n\n## Usage\n\n### Usage in REST application\n\nTo protect your REST endpoints, you can use the `@Recaptcha` decorator.\u003cbr/\u003eExample:\n\n```typescript\n\n@Controller('feedback')\nexport class FeedbackController {\n    @Recaptcha()\n    @Post('send')\n    async send(): Promise\u003cany\u003e {\n        // TODO: Your implementation.\n    }\n}\n\n```\n\nYou can also override the default property that contains reCAPTCHA for a specific endpoint.\u003cbr/\u003e\n\n```typescript\n\n@Controller('feedback')\nexport class FeedbackController {\n    @Recaptcha({response: req =\u003e req.body.recaptha})\n    @Post('send')\n    async send(): Promise\u003cany\u003e {\n        // TODO: Your implementation.\n    }\n}\n\n```\n\nAdditionally, you can override reCAPTCHA v3 options.\u003cbr/\u003e\n\n```typescript\n\n@Controller('feedback')\nexport class FeedbackController {\n    @Recaptcha({response: req =\u003e req.body.recaptha, action: 'Send', score: 0.8})\n    @Post('send')\n    async send(): Promise\u003cany\u003e {\n        // TODO: Your implementation.\n    }\n}\n\n```\n\nTo get the verification result, you can use the @RecaptchaResult() decorator.\u003cbr/\u003e\n\n```typescript\n\n@Controller('feedback')\nexport class FeedbackController {\n    @Recaptcha()\n    @Post('send')\n    async send(@RecaptchaResult() recaptchaResult: RecaptchaVerificationResult): Promise\u003cany\u003e {\n        console.log(`Action: ${recaptchaResult.action} Score: ${recaptchaResult.score}`);\n        // TODO: Your implementation.\n    }\n}\n\n```\n\nIf you want to use the Google reCAPTCHA guard in combination with other guards, you can use the `@UseGuards` decorator.\u003cbr/\u003e\n```typescript\n\n@Controller('feedback')\nexport class FeedbackController {\n    @SetRecaptchaOptions({action: 'Send', score: 0.8})\n    @UseGuards(Guard1, GoogleRecaptchaGuard, Guard2)\n    @Post('send')\n    async send(): Promise\u003cany\u003e {\n        // TODO: Your implementation.\n    }\n}\n\n```\n\nYou can find a usage example in the following [link](https://github.com/chvarkov/google-recaptcha-example).\n\n### Usage in Graphql application\n\nTo protect your resolver, use the `@Recaptcha` decorator.\n\n```typescript\n@Recaptcha()\n@Resolver(of =\u003e Recipe)\nexport class RecipesResolver {\n    @Query(returns =\u003e Recipe)\n    async recipe(@Args('id') id: string): Promise\u003cRecipe\u003e {\n        // TODO: Your implementation.\n    }\n}\n```\n\nObtain verification result:\n\n```typescript\n@Recaptcha()\n@Resolver(of =\u003e Recipe)\nexport class RecipesResolver {\n    @Query(returns =\u003e Recipe)\n    async recipe(@Args('id') id: string,\n                 @RecaptchaResult() recaptchaResult: RecaptchaVerificationResult): Promise\u003cRecipe\u003e {\n        console.log(`Action: ${recaptchaResult.action} Score: ${recaptchaResult.score}`);\n        // TODO: Your implementation.\n    }\n}\n```\n\nYou can override the default recaptcha property for a specific endpoint.\n\n```typescript\n@Recaptcha()\n@Resolver(of =\u003e Recipe)\nexport class RecipesResolver {\n    @Query(returns =\u003e Recipe)\n    async recipe(@Args('id') id: string): Promise\u003cRecipe\u003e {\n        // TODO: Your implementation.\n    }\n\n    // Overridden default header. This query using X-Recaptcha header \n    @Recaptcha({response: (req: IncomingMessage) =\u003e (req.headers['x-recaptcha'] || '').toString()})\n    @Query(returns =\u003e [Recipe])\n    recipes(@Args() recipesArgs: RecipesArgs): Promise\u003cRecipe[]\u003e {\n        // TODO: Your implementation.\n    }\n}\n```\n\n### Validate in service\n\n```typescript\n@Injectable()\nexport class SomeService {\n    constructor(private readonly recaptchaValidator: GoogleRecaptchaValidator) {\n    }\n\n    async someAction(recaptchaToken: string): Promise\u003cvoid\u003e {\n        const result = await this.recaptchaValidator.validate({\n            response: recaptchaToken,\n            score: 0.8,\n            action: 'SomeAction',\n        });\n        \n        if (!result.success) {\n            throw new GoogleRecaptchaException(result.errors);\n        }\n        // TODO: Your implemetation\n    }\n}\n```\n\n### Validate in service (Enterprise)\n\n```typescript\n@Injectable()\nexport class SomeService {\n    constructor(private readonly recaptchaEnterpriseValidator: GoogleRecaptchaEnterpriseValidator) {\n    }\n\n    async someAction(recaptchaToken: string): Promise\u003cvoid\u003e {\n        const result = await this.recaptchaEnterpriseValidator.validate({\n            response: recaptchaToken,\n            score: 0.8,\n            action: 'SomeAction',\n        });\n        \n        if (!result.success) {\n            throw new GoogleRecaptchaException(result.errors);\n        }\n        \n        const riskAnalytics = result.getEnterpriseRiskAnalytics();\n        \n        // TODO: Your implemetation\n    }\n}\n```\n\n### Dynamic Recaptcha configuration\nThe `RecaptchaConfigRef` class provides a convenient way to modify Recaptcha validation parameters within your application.\nThis can be particularly useful in scenarios where the administration of Recaptcha is managed dynamically, such as by an administrator.\nThe class exposes methods that allow the customization of various Recaptcha options.\n\n\n**RecaptchaConfigRef API:**\n\n```typescript\n@Injectable()\nclass RecaptchaConfigRef {\n  // Sets the secret key for Recaptcha validation.\n  setSecretKey(secretKey: string): this;\n\n  // Sets enterprise-specific options for Recaptcha validation\n  setEnterpriseOptions(options: GoogleRecaptchaEnterpriseOptions): this;\n\n  // Sets the score threshold for Recaptcha validation.\n  setScore(score: ScoreValidator): this;\n\n  // Sets conditions under which Recaptcha validation should be skipped.\n  setSkipIf(skipIf: SkipIfValue): this;\n}\n```\n\n**Usage example:**\n\n```typescript\n@Injectable()\nexport class RecaptchaAdminService implements OnApplicationBootstrap {\n\tconstructor(private readonly recaptchaConfigRef: RecaptchaConfigRef) {\n\t}\n\n\tasync onApplicationBootstrap(): Promise\u003cvoid\u003e {\n\t\t// TODO: Pull recaptcha configs from your database \n\n\t\tthis.recaptchaConfigRef\n\t\t\t.setSecretKey('SECRET_KEY_VALUE')\n\t\t\t.setScore(0.3);\n\t}\n\n\tasync updateSecretKey(secretKey: string): Promise\u003cvoid\u003e {\n\t\t// TODO: Save new secret key to your database\n\n\t\tthis.recaptchaConfigRef.setSecretKey(secretKey);\n\t}\n}\n```\n\nAfter call `this.recaptchaConfigRef.setSecretKey(...)` - `@Recaptcha` guard and `GoogleRecaptchaValidator` will use new secret key.\n\n### Error handling\n\n**GoogleRecaptchaException**\n\n`GoogleRecaptchaException` extends `HttpException` extends `Error`.\n\nThe `GoogleRecaptchaException` is an exception that can be thrown by the `GoogleRecaptchaGuard` when an error occurs. It extends the `HttpException` class provided by NestJS, which means that it can be caught by an ExceptionFilter in the same way as any other HTTP exception.\n\nOne important feature of the `GoogleRecaptchaException` is that it contains an array of Error Code values in the errorCodes property. These values  can be used to diagnose and handle the error.\n\n\n\n| Error code                       | Description | Status code |\n|----------------------------------|-------------|-------------|\n| `ErrorCode.MissingInputSecret`   | The secret parameter is missing. (Throws from reCAPTCHA api). | 500         |\n| `ErrorCode.InvalidInputSecret`   | The secret parameter is invalid or malformed. (Throws from reCAPTCHA api). | 500         |\n| `ErrorCode.MissingInputResponse` | The response parameter is missing. (Throws from reCAPTCHA api). | 400         |\n| `ErrorCode.InvalidInputResponse` | The response parameter is invalid or malformed. (Throws from reCAPTCHA api). | 400         |\n| `ErrorCode.BadRequest`\t       | The request is invalid or malformed. (Throws from reCAPTCHA api). | 500         |\n| `ErrorCode.TimeoutOrDuplicate`   | The response is no longer valid: either is too old or has been used previously. (Throws from reCAPTCHA api). | 400         |\n| `ErrorCode.UnknownError`         | Unknown error. (Throws from reCAPTCHA api). | 500         |\n| `ErrorCode.ForbiddenAction`      | Forbidden action. (Throws from guard when expected action not equals to received). | 400         |\n| `ErrorCode.LowScore`             | Low score (Throws from guard when expected score less than received). | 400         |\n| `ErrorCode.InvalidKeys`          | keys were copied incorrectly, the wrong keys were used for the environment (e.g. development vs production), or if the keys were revoked or deleted from the Google reCAPTCHA admin console.. (Throws from reCAPTCHA api). | 400         |\n| `ErrorCode.NetworkError`         | Network error (like ECONNRESET, ECONNREFUSED...). | 500         |\n| `ErrorCode.SiteMismatch`         | Site mismatch (Throws from reCAPTCHA Enterprise api only). | 400         |\n| `ErrorCode.BrowserError`         | Browser error (Throws from reCAPTCHA Enterprise api only). | 400         |\n\n\n**GoogleRecaptchaNetworkException**\n\nThe `GoogleRecaptchaNetworkException` is an exception that extends the `GoogleRecaptchaException` class and is thrown in the case of a network error. \u003cbr/\u003e It contains a `networkErrorCode` property, which contains the error code of the network error, retrieved from the `code` property of the `AxiosError` object.\n\nYou can handle it via [ExceptionFilter](https://docs.nestjs.com/exception-filters).\n\nExample exception filter implementation.\n\n```typescript\n\n@Catch(GoogleRecaptchaException)\nexport class GoogleRecaptchaFilter implements ExceptionFilter {\n    catch(exception: GoogleRecaptchaException, host: ArgumentsHost): any {\n        // TODO: Your exception filter implementation\n    }\n}\n\n```\n\nAnd add your filter to application\n\n```typescript\n\nasync function bootstrap() {\n    const app = await NestFactory.create(AppModule);\n    app.useGlobalFilters(new ErrorFilter(), new GoogleRecaptchaFilter());\n    await app.listen(3000);\n}\nbootstrap();\n\n\n```\n\n## Contribution\n\nWe welcome any contributions to improve our package! If you find a bug, have a feature request, or want to suggest an improvement, feel free to submit an issue on our GitHub repository.\n\nIf you want to contribute to the codebase directly, please follow our contributing guidelines outlined in the [CONTRIBUTING.md](./CONTRIBUTING.md) file in the repository.\n\nWe value the contributions of our community and appreciate all efforts to make this package better for everyone. Thank you for your support!\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](./LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchvarkov%2Fgoogle-recaptcha","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchvarkov%2Fgoogle-recaptcha","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchvarkov%2Fgoogle-recaptcha/lists"}