Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

verify-hcaptcha

Package Overview
Dependencies
Maintainers
0
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

verify-hcaptcha - npm Package Compare versions

Comparing version 1.0.0 to 2.0.0

251

dist/index.d.ts

@@ -0,145 +1,96 @@

import { z } from 'zod';
/**
*
* A no dependencies, fully typed library to verify hCaptcha tokens
* submitted by users when solving CAPTCHA challenges.
*
* @remarks
*
* Note: this is an unofficial library; we are not affiliated with hCaptcha.com
*
* @example
*
* Verify a token submitted by a user:
*
* ```typescript
* import { verifyHcaptchaToken } from 'verify-hcaptcha';
*
* (async () => {
* const result = await verifyHcaptchaToken({
* token: "USER-SUBMITTED-RESPONSE-TOKEN",
* secretKey: "YOUR-SECRET-KEY",
* siteKey: "YOUR-SITE-KEY",
* });
*
* if (result.success) {
* console.log("User is human");
* } else {
* console.log("User is robot");
* }
* })();
* ```
*
* @example
*
* Verify a token submitted by a user and get the raw response from hCaptcha:
*
* ```typescript
* import { rawVerifyHcaptchaToken } from 'verify-hcaptcha';
*
* (async () => {
* const result = await rawVerifyHcaptchaToken({
* token: "USER-SUBMITTED-RESPONSE-TOKEN",
* secretKey: "YOUR-SECRET-KEY",
* siteKey: "YOUR-SITE-KEY",
* });
*
* if (result.success) {
* console.log("User is human");
* } else {
* console.log("User is robot");
* }
* })();
* ```
*
* @packageDocumentation
*/
/**
* `HcaptchaResponse` represents the response to the verification challenge
* performed by calling {@link verifyHcaptchaToken}.
*
* @see {@link https://docs.hcaptcha.com/#verify-the-user-response-server-side}
*/
export interface HcaptchaResponse {
/**
* True if the token is valid and meets the specified security criteria
* (for example, if the site key is associated to the secret key)
*/
readonly success: boolean;
/**
* Optional: UTC timestamp of the challenge in ISO 8601 format
* (for example, `2021-10-02T18:12:10.149Z`)
*/
readonly challengeTimestamp?: string;
/** Optional: hostname of the website where the challenge was solved */
readonly hostname?: string;
/** Optional: true if the response will be credited */
readonly credit?: boolean;
/**
* Optional: list of error codes
*
* @see {@link HcaptchaError}
*/
readonly errorCodes?: HcaptchaError[];
/** Enterprise-only feature: score for malicious activity */
readonly score?: number;
/** Enterprise-only feature: list of reasons for the malicious activity score */
readonly scoreReasons?: string[];
A fully typed library to verify hCaptcha.com tokens submitted by users when solving captcha challenges.
@remarks
Note: this is an unofficial library; we are not affiliated with hCaptcha.com.
@example
Verify a token submitted by a user:
```typescript
import { verifyHcaptchaToken } from 'verify-hcaptcha';
const result = await verifyHcaptchaToken({
token: "USER-SUBMITTED-RESPONSE-TOKEN",
secretKey: "YOUR-SECRET-KEY",
siteKey: "YOUR-SITE-KEY",
});
if (result.success) {
console.log("User is human");
} else {
console.log("User is robot");
}
```
@packageDocumentation
*/
declare const hCaptchaResponseSchema: z.ZodEffects<z.ZodObject<{
success: z.ZodBoolean;
challenge_ts: z.ZodOptional<z.ZodString>;
hostname: z.ZodOptional<z.ZodString>;
credit: z.ZodOptional<z.ZodBoolean>;
"error-codes": z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"missing-input-secret">, z.ZodLiteral<"invalid-input-secret">, z.ZodLiteral<"missing-input-response">, z.ZodLiteral<"invalid-input-response">, z.ZodLiteral<"invalid-sitekey">, z.ZodLiteral<"missing-remoteip">, z.ZodLiteral<"invalid-remoteip">, z.ZodLiteral<"bad-request">, z.ZodLiteral<"invalid-or-already-seen-response">, z.ZodLiteral<"not-using-dummy-passcode">, z.ZodLiteral<"not-using-dummy-secret">, z.ZodLiteral<"sitekey-secret-mismatch">]>, "many">>;
score: z.ZodOptional<z.ZodNumber>;
"score-reason": z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
success: boolean;
challenge_ts?: string | undefined;
hostname?: string | undefined;
credit?: boolean | undefined;
"error-codes"?: ("missing-input-secret" | "invalid-input-secret" | "missing-input-response" | "invalid-input-response" | "invalid-sitekey" | "missing-remoteip" | "invalid-remoteip" | "bad-request" | "invalid-or-already-seen-response" | "not-using-dummy-passcode" | "not-using-dummy-secret" | "sitekey-secret-mismatch")[] | undefined;
score?: number | undefined;
"score-reason"?: string[] | undefined;
}, {
success: boolean;
challenge_ts?: string | undefined;
hostname?: string | undefined;
credit?: boolean | undefined;
"error-codes"?: ("missing-input-secret" | "invalid-input-secret" | "missing-input-response" | "invalid-input-response" | "invalid-sitekey" | "missing-remoteip" | "invalid-remoteip" | "bad-request" | "invalid-or-already-seen-response" | "not-using-dummy-passcode" | "not-using-dummy-secret" | "sitekey-secret-mismatch")[] | undefined;
score?: number | undefined;
"score-reason"?: string[] | undefined;
}>, {
/** True if the token is valid and meets the specified security criteria (e.g., if the site key is associated to the secret key). */
success: boolean;
/** UTC timestamp of the challenge in ISO 8601 format (e.g., `2021-10-02T18:12:10.149Z`). */
challengeTimestamp: string | undefined;
/** Hostname of the website where the challenge was solved. */
hostname: string | undefined;
/** True if the response will be credited. @deprecated */
credit: boolean | undefined;
/** Error codes. @see {@link https://docs.hcaptcha.com/#siteverify-error-codes-table} */
errorCodes: ("missing-input-secret" | "invalid-input-secret" | "missing-input-response" | "invalid-input-response" | "invalid-sitekey" | "missing-remoteip" | "invalid-remoteip" | "bad-request" | "invalid-or-already-seen-response" | "not-using-dummy-passcode" | "not-using-dummy-secret" | "sitekey-secret-mismatch")[] | undefined;
/** Enterprise-only feature: score for malicious activity. */
score: number | undefined;
/** Enterprise-only feature: list of reasons for the malicious activity score. */
scoreReasons: string[] | undefined;
}, {
success: boolean;
challenge_ts?: string | undefined;
hostname?: string | undefined;
credit?: boolean | undefined;
"error-codes"?: ("missing-input-secret" | "invalid-input-secret" | "missing-input-response" | "invalid-input-response" | "invalid-sitekey" | "missing-remoteip" | "invalid-remoteip" | "bad-request" | "invalid-or-already-seen-response" | "not-using-dummy-passcode" | "not-using-dummy-secret" | "sitekey-secret-mismatch")[] | undefined;
score?: number | undefined;
"score-reason"?: string[] | undefined;
}>;
/**
* `HcaptchaError` collects the errors explaining why a verification challenge failed.
*
* @see {@link HcaptchaResponse}
* @see {@link https://docs.hcaptcha.com/#siteverify-error-codes-table}
*/
export declare type HcaptchaError =
/** Secret key is missing */
"missing-input-secret"
/** Secret key is invalid */
| "invalid-input-secret"
/** User response token is missing */
| "missing-input-response"
/** User response token is invalid */
| "invalid-input-response"
/** Site key is invalid */
| "invalid-sitekey"
/** Remote user IP is invalid */
| "invalid-remoteip"
/** Request is invalid */
| "bad-request"
/** User response token is invalid or has already been checked */
| "invalid-or-already-seen-response"
/** Must use the test site key when using a test verification token */
| "not-using-dummy-passcode"
/** Must use the test secret key when using a test verification token */
| "not-using-dummy-secret"
/** The site key is not associated to the secret key */
| "sitekey-secret-mismatch";
`HcaptchaResponse` represents the response to the verification challenge performed by calling {@link verifyHcaptchaToken}.
@see {@link https://docs.hcaptcha.com/#verify-the-user-response-server-side}
*/
type HcaptchaResponse = z.infer<typeof hCaptchaResponseSchema>;
/**
* `RawHcaptchaResponse` represents the raw response to the verification challenge
* obtained by directly calling the hCaptcha API endpoint
* with {@link rawVerifyHcaptchaToken}.
*
* @see {@link https://docs.hcaptcha.com/#verify-the-user-response-server-side}
*/
export interface RawHcaptchaResponse {
readonly success: boolean;
readonly challenge_ts?: string;
readonly hostname?: string;
readonly credit?: boolean;
readonly "error-codes"?: string[];
readonly score?: number;
readonly score_reason?: string[];
}
/**
* `verifyHcaptchaToken` verifies with the hCaptcha API that the response token
* obtained from a captcha challenge is valid.
*
* @param token - required: the token obtained from a user with a captcha challenge
* @param secretKey - required: the secret key for your account
* @param siteKey - optional but recommended: the site key for the website hosting the captcha challenge
* @param remoteIp - optional: the IP address of the user submitting the challenge
*
* @returns a {@link HcaptchaResponse} with the verification result
*/
export declare function verifyHcaptchaToken({ token, secretKey, siteKey, remoteIp, }: {
`verifyHcaptchaToken` verifies with the hCaptcha.com API that the response token obtained
from a user who solved a captcha challenge is valid.
@param token - required: the token obtained from the user who solved the captcha challenge
@param secretKey - required: the secret key for your account
@param siteKey - optional but recommended: the site key for the website hosting the captcha challenge
@param remoteIp - optional: the IP address of the user who solved the challenge
@returns a {@link HcaptchaResponse} with the verification result
*/
declare function verifyHcaptchaToken({ token, secretKey, siteKey, remoteIp, }: {
token: string;

@@ -150,19 +101,3 @@ secretKey: string;

}): Promise<HcaptchaResponse>;
/**
* `rawVerifyHcaptchaToken` verifies with the hCaptcha API that the response token
* obtained from a captcha challenge is valid and returns the raw hCaptcha response.
*
* @param token - required: the token obtained from a user with a captcha challenge
* @param secretKey - required: the secret key for your account
* @param siteKey - optional but recommended: the site key for the website hosting the captcha challenge
* @param remoteIp - optional: the IP address of the user submitting the challenge
*
* @returns a {@link RawHcaptchaResponse} with the verification result
*/
export declare function rawVerifyHcaptchaToken({ token, secretKey, siteKey, remoteIp, }: {
token: string;
secretKey: string;
siteKey?: string;
remoteIp?: string;
}): Promise<RawHcaptchaResponse>;
//# sourceMappingURL=index.d.ts.map
export { type HcaptchaResponse, verifyHcaptchaToken };

@@ -1,8 +0,79 @@

'use strict'
if (process.env.NODE_ENV === 'production') {
module.exports = require('./verify-hcaptcha.cjs.production.min.js')
} else {
module.exports = require('./verify-hcaptcha.cjs.development.js')
// src/index.ts
import { z } from "zod";
var hCaptchaResponseSchema = z.object({
success: z.boolean(),
challenge_ts: z.string().optional(),
hostname: z.string().optional(),
credit: z.boolean().optional(),
"error-codes": z.array(
z.union([
/** Secret key is missing. */
z.literal("missing-input-secret"),
/** Secret key is invalid. */
z.literal("invalid-input-secret"),
/** User response token is missing. */
z.literal("missing-input-response"),
/** User response token is invalid. */
z.literal("invalid-input-response"),
/** Site key is invalid. */
z.literal("invalid-sitekey"),
/** Remote user IP is missing. */
z.literal("missing-remoteip"),
/** Remote user IP is invalid. */
z.literal("invalid-remoteip"),
/** Request is invalid. */
z.literal("bad-request"),
/** User response token is invalid or has already been checked. */
z.literal("invalid-or-already-seen-response"),
/** Must use the test site key when using a test verification token. */
z.literal("not-using-dummy-passcode"),
/** Must use the test secret key when using a test verification token. */
z.literal("not-using-dummy-secret"),
/** The site key is not associated to the secret key. */
z.literal("sitekey-secret-mismatch")
])
).optional(),
score: z.number().optional(),
"score-reason": z.array(z.string()).optional()
}).transform(({ success, hostname, credit, score, ...rest }) => ({
/** True if the token is valid and meets the specified security criteria (e.g., if the site key is associated to the secret key). */
success,
/** UTC timestamp of the challenge in ISO 8601 format (e.g., `2021-10-02T18:12:10.149Z`). */
challengeTimestamp: rest.challenge_ts,
/** Hostname of the website where the challenge was solved. */
hostname,
/** True if the response will be credited. @deprecated */
credit,
/** Error codes. @see {@link https://docs.hcaptcha.com/#siteverify-error-codes-table} */
errorCodes: rest["error-codes"],
/** Enterprise-only feature: score for malicious activity. */
score,
/** Enterprise-only feature: list of reasons for the malicious activity score. */
scoreReasons: rest["score-reason"]
}));
async function verifyHcaptchaToken({
token,
secretKey,
siteKey,
remoteIp
}) {
const form = new URLSearchParams();
form.append("response", token);
form.append("secret", secretKey);
if (siteKey) {
form.append("sitekey", siteKey);
}
if (remoteIp) {
form.append("remoteip", remoteIp);
}
const response = await fetch("https://api.hcaptcha.com/siteverify", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: form.toString()
});
const json = await response.json();
return hCaptchaResponseSchema.parse(json);
}
export {
verifyHcaptchaToken
};
{
"name": "verify-hcaptcha",
"version": "1.0.0",
"description": "A no dependencies, fully typed library to verify hCaptcha tokens submitted by users",
"author": "Edoardo Scibona",
"license": "MIT",
"source": "src/index.ts",
"main": "dist/index.js",
"module": "dist/verify-hcaptcha.esm.js",
"types": "dist/index.d.ts",
"sideEffects": false,
"exports": {
".": {
"require": "./dist/index.js",
"import": "./dist/verify-hcaptcha.esm.js",
"default": "./dist/index.js"
},
"./package.json": "./package.json"
},
"files": [
"src",
"dist"
],
"engines": {
"node": ">=12"
},
"repository": {
"type": "git",
"url": "https://github.com/velut/verify-hcaptcha.git"
},
"bugs": {
"url": "https://github.com/velut/verify-hcaptcha/issues"
},
"scripts": {
"start": "dts watch",
"build": "tsc --noEmit && dts build --target node",
"test": "dts test --runInBand",
"test:cov": "dts test --runInBand --coverage",
"test:ci": "dts test --runInBand --coverage --ci",
"lint": "dts lint",
"prepare": "dts build",
"size": "size-limit",
"analyze": "size-limit --why",
"release": "np"
},
"husky": {
"hooks": {
"pre-commit": "dts lint"
}
},
"prettier": {
"printWidth": 80,
"semi": true,
"trailingComma": "es5"
},
"size-limit": [
{
"path": "dist/verify-hcaptcha.cjs.production.min.js",
"limit": "10 KB"
},
{
"path": "dist/verify-hcaptcha.esm.js",
"limit": "10 KB"
}
],
"keywords": [
"hcaptcha",
"captcha",
"verify",
"response",
"token",
"user",
"typescript",
"types",
"typed",
"node",
"validate",
"check",
"siteverify"
],
"dependencies": {},
"devDependencies": {
"@pollyjs/adapter-node-http": "5.1.1",
"@pollyjs/core": "5.1.1",
"@pollyjs/persister-fs": "5.1.1",
"@size-limit/preset-small-lib": "6.0.3",
"@types/pollyjs__adapter-node-http": "2.0.1",
"@types/pollyjs__persister-fs": "2.0.1",
"@types/setup-polly-jest": "0.5.1",
"dts-cli": "0.19.4",
"eslint-plugin-prettier": "4.0.0",
"husky": "7.0.4",
"nock": "13.1.4",
"np": "7.5.0",
"prettier": "2.4.1",
"setup-polly-jest": "0.10.0",
"size-limit": "6.0.3",
"tslib": "2.3.1",
"typescript": "4.4.4"
}
"name": "verify-hcaptcha",
"version": "2.0.0",
"description": "A fully typed library to verify hCaptcha.com tokens submitted by users when solving captcha challenges",
"license": "MIT",
"author": {
"name": "Edoardo Scibona",
"url": "https://github.com/velut"
},
"repository": {
"type": "git",
"url": "https://github.com/velut/verify-hcaptcha.git"
},
"bugs": {
"url": "https://github.com/velut/verify-hcaptcha/issues"
},
"keywords": [
"hcaptcha",
"captcha",
"verify",
"response",
"token",
"user",
"typescript",
"types",
"typed",
"node",
"validate",
"check",
"siteverify"
],
"sideEffects": false,
"type": "module",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./package.json": "./package.json"
},
"files": [
"dist"
],
"engines": {
"node": ">=20"
},
"scripts": {
"check": "tsc --noEmit",
"build": "tsc --noEmit && tsup",
"attw": "attw --pack . --ignore-rules cjs-resolves-to-esm",
"test": "vitest",
"test:ci": "vitest run --coverage --bail 1",
"lint": "prettier --check .",
"format": "prettier --write .",
"pre-push": "bun install && bun run lint && bun run build && bun run test:ci && bun run attw",
"release": "np --no-cleanup"
},
"dependencies": {
"zod": "^3.23.8"
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.15.3",
"@types/bun": "^1.1.3",
"@vitest/coverage-v8": "^1.6.0",
"np": "^10.0.5",
"prettier": "^3.3.2",
"tsup": "^8.1.0",
"typescript": "^5.5.3",
"vitest": "^1.6.0"
}
}

@@ -1,30 +0,23 @@

# verify-hcaptcha
# ✅ verify-hcaptcha
[![Build status](https://img.shields.io/github/workflow/status/velut/verify-hcaptcha/CI)](https://github.com/velut/verify-hcaptcha/actions?query=workflow%3ACI)
[![Build status](https://img.shields.io/github/actions/workflow/status/velut/verify-hcaptcha/main.yml?branch=main)](https://github.com/velut/verify-hcaptcha/actions?query=workflow%3ACI)
[![Coverage](https://img.shields.io/codecov/c/gh/velut/verify-hcaptcha)](https://codecov.io/gh/velut/verify-hcaptcha)
[![jsDocs.io](https://img.shields.io/badge/jsDocs.io-reference-blue)](https://www.jsdocs.io/package/verify-hcaptcha)
![Language](https://img.shields.io/github/languages/top/velut/verify-hcaptcha)
[![npm bundle size](https://img.shields.io/bundlephobia/min/verify-hcaptcha)](https://bundlephobia.com/result?p=verify-hcaptcha)
[![npm](https://img.shields.io/npm/v/verify-hcaptcha)](https://www.npmjs.com/package/verify-hcaptcha)
[![License](https://img.shields.io/github/license/velut/verify-hcaptcha)](https://github.com/velut/verify-hcaptcha/blob/main/LICENSE)
A fully typed library to verify hCaptcha.com tokens submitted by users when solving captcha challenges.
A no dependencies, fully typed library to verify hCaptcha tokens
submitted by users when solving CAPTCHA challenges.
> [!WARNING]
> This is an **unofficial** library; we are not affiliated with hCaptcha.com.
> Note: this is an **unofficial** library; we are not affiliated with hCaptcha.com
## Useful resources
## Features
- [**Explore the API on jsDocs.io**](https://www.jsdocs.io/package/verify-hcaptcha)
- View package contents on [**unpkg**](https://unpkg.com/verify-hcaptcha/)
- View repository on [**GitHub**](https://github.com/velut/verify-hcaptcha)
- Read the changelog on [**GitHub**](https://github.com/velut/verify-hcaptcha/blob/main/CHANGELOG.md)
- Read the official documentation on [**hCaptcha**](https://docs.hcaptcha.com/)
- No dependencies
- Fully typed API and response data
- Well documented and tested
## API & Package Info
- [Explore the API on **jsDocs.io**](https://www.jsdocs.io/package/verify-hcaptcha)
- [View package contents on **unpkg**](https://unpkg.com/verify-hcaptcha/)
- [View repository on **GitHub**](https://github.com/velut/verify-hcaptcha)
- [Read official documentation on **hCaptcha**](https://docs.hcaptcha.com/)
## Install

@@ -35,3 +28,3 @@

```
npm i verify-hcaptcha
npm add verify-hcaptcha
```

@@ -45,42 +38,32 @@

## Usage Examples
Using `pnpm`:
Verify a token submitted by a user:
```
pnpm add verify-hcaptcha
```
```typescript
import { verifyHcaptchaToken } from 'verify-hcaptcha';
Using `bun`:
(async () => {
const result = await verifyHcaptchaToken({
token: "USER-SUBMITTED-RESPONSE-TOKEN",
secretKey: "YOUR-SECRET-KEY",
siteKey: "YOUR-SITE-KEY",
});
if (result.success) {
console.log("User is human");
} else {
console.log("User is robot");
}
})();
```
bun add verify-hcaptcha
```
Verify a token submitted by a user and get the raw response from hCaptcha:
## Usage Examples
Verify a token submitted by a user:
```typescript
import { rawVerifyHcaptchaToken } from 'verify-hcaptcha';
import { verifyHcaptchaToken } from "verify-hcaptcha";
(async () => {
const result = await rawVerifyHcaptchaToken({
token: "USER-SUBMITTED-RESPONSE-TOKEN",
secretKey: "YOUR-SECRET-KEY",
siteKey: "YOUR-SITE-KEY",
});
const result = await verifyHcaptchaToken({
token: "USER-SUBMITTED-RESPONSE-TOKEN",
secretKey: "YOUR-SECRET-KEY",
siteKey: "YOUR-SITE-KEY",
});
if (result.success) {
console.log("User is human");
} else {
console.log("User is robot");
}
})();
if (result.success) {
console.log("User is human");
} else {
console.log("User is robot");
}
```

@@ -90,6 +73,8 @@

MIT License
```
MIT
```
Copyright (c) 2021 Edoardo Scibona
Copyright (c) 2024 Edoardo Scibona
See LICENSE file.
See [LICENSE](./LICENSE) file.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc