UNPKG

verify-hcaptcha

Version:

A fully typed library to verify hCaptcha.com tokens submitted by users when solving captcha challenges

83 lines (74 loc) 3.28 kB
/** 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", // Required secretKey: "YOUR-SECRET-KEY", // Required siteKey: "YOUR-SITE-KEY", // Optional remoteIp: "USER-IP-ADDRESS", // Optional }); if (result.success) { console.log("User is human"); } else { console.log("User is robot"); } ``` @packageDocumentation */ import * as z from "zod/mini"; const rawHcaptchaResponseSchema = z.object({ success: z.boolean(), challenge_ts: z.optional(z.string()), hostname: z.optional(z.string()), credit: z.optional(z.boolean()), // See https://github.com/colinhacks/zod/discussions/4934 and https://github.com/colinhacks/zod/discussions/4939. "error-codes": z.optional(z.array(z.string())), score: z.optional(z.number()), "score-reason": z.optional(z.array(z.string())), }); const hCaptchaResponseSchema = z.pipe(rawHcaptchaResponseSchema, z.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"], }))); /** `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 */ export 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); }