reCAPTCHA

@crvouga/mockingbird-service-recaptcha

Deterministic reCAPTCHA v3 browser shim and single-use Siteverify emulator.

Parity: v3 browser API and token verificationIdentity2 of 2 operationsIn-process fetchNode servermockingbird-recaptcha
$
npm install -D @crvouga/mockingbird-service-recaptcha

Playground

Requests go to the real emulator running in this tab. State persists across requests, and the journal shows what it received. A green dot marks operations whose sample succeeds as-is; others need ids from earlier responses.

Loads the real @crvouga/mockingbird-service-recaptcha into this tab on first send
https://www.google.com

Send a request to see the emulator's response.

Operations

2 of 2 operations in the vendored contract are emulated.

MethodPathOperationStatus
GET/recaptcha/api.jsBrowserScript
POST/recaptcha/api/siteverifySiteverify

Documentation

The package README, the same file that ships in the npm tarball.Edit on GitHub

Local emulators. Real API contracts. Part of Mockingbird.

A WIP reCAPTCHA v3 emulator: browser grecaptcha.ready/execute, deterministic single-use tokens, and form-encoded Siteverify. The contract follows Google's verification and v3 references. It does not contact Google.

Install

Shell
bun add @crvouga/mockingbird-service-recaptcha

Usage

TypeScript
import { createServer } from "@crvouga/mockingbird-service-recaptcha/server"

// Test setup: a local reCAPTCHA, and a token like the one grecaptcha.execute hands the browser.
const server = await createServer()
const issued = await fetch(`${server.url}/__admin/issue`, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ siteKey: "mock_site", action: "login", hostname: "app.example" }),
})
const { token } = await issued.json()

// Application code: the Siteverify call it makes to Google, sent to the emulator's URL.
const siteverifyUrl = `${server.url}/recaptcha/api/siteverify`
const verified = await fetch(siteverifyUrl, {
  method: "POST",
  body: new URLSearchParams({ secret: "mock_secret", response: token }),
})
const { success, score, action } = await verified.json()

await server.close()

mockingbird-recaptcha serve runs the same server standalone; createRuntime from the main entry is the in-process form. Override the browser script URL to /recaptcha/api.js?render=mock_site and the server verification URL to /recaptcha/api/siteverify on the local origin. The browser shim uses a local /__admin/issue request to obtain tokens; an admin-key-protected runtime requires tokens to be provisioned by the test harness. No admin key is embedded in script.

Tokens bind a site key, hostname, action, score, and issue time. Verification consumes them once and expires them after two minutes. A low score is still a successful vendor verification: the application checks its score threshold, expected action, and hostname.

PUT /__admin/settings accepts sites, score, per-action scores, response action/ hostname overrides, executeError, expired, replayed, and errorCodes. GET /__admin/attempts returns only time/result/error metadata, without tokens or secrets. Shared admin routes provide clock control, reset, Timeline history, namespaces, and faults. Namespace selection uses x-mockingbird-namespace or /__admin/ns/<name>/…. Custom adminPrefix relocates issuance and the shim's local target together.

Presets: human, bot, threshold_boundary, expired, replayed, script_failure, rate_limited, and server_error. Pass count: 1 for a one-shot failure. Generic faults also support deterministic latency and connection drops. No webhook or pagination exists in this vendor surface.

API

The main entry exports RecaptchaAPI, RecaptchaState, createRuntime, RECAPTCHA_NAMESPACE, RECAPTCHA_PRESETS, DEFAULT_SETTINGS, document, operationIds, and supportedOperationIds, plus public types. The /server entry exports createServer, serveTarget, and DEFAULT_PORT.

Deliberately not modelled

  • Google's risk model, device fingerprinting, interactive v2 challenges, or Enterprise API.
  • The private Geviti client's implementation: acceptance uses the documented Google flow.
  • Live successful challenges. The cold parity command probes only missing-response rejection and exits 2 without RECAPTCHA_SECRET_KEY; never use production credentials in fixtures.
↑↓ to navigate↵ to open