Verification modes

VerifyHuman is one assurance ladder: a zero-JS server floor, an on-page silent check, and a camera step-up — you enter at the rung your assurance need and page access allow. Invisible by default; friction only when it's earned.

There are two axes. Where verification runs (server-to-server, or a widget on the respondent's page) and, for the widget, how hard it verifies (invisible / captcha / standard). This page lists every mode, what it sees, and the exact way to integrate it.

Pick a mode

If you…ModeHow you integrate it
can't add code to the respondent's page (panel / supply, server-to-server only)Server-Sideone HTTP call — POST /api/v1/lite/score
want a silent, no-friction check on the page, no cameraInvisibleSDK mount with widgetMode: 'invisible'
want a quick biometric proof (~2–3 s hidden camera)CaptchaSDK mount with widgetMode: 'captcha'
want the strongest proof — full camera, liveness, challenges, uniquenessStandardSDK mount with widgetMode: 'standard' (the default)
a camera mode couldn't open the cameradevice-onlyautomatic fallback — nothing to wire

The ladder

  L3  Active challenges (blink / smile / turn)   ← STANDARD (when passive isn't enough)
  L2  Passive camera: liveness + uniqueness      ← CAPTCHA (quick) · STANDARD · step-up   [BIOMETRIC]
  ─────────────────────────────────────────────  step up only when the floor is uncertain
  L1  <15KB probe: device signals, behavioral,   ← INVISIBLE = L0 + L1
      CDP/stealth, pointer entropy (no camera)
  L0  Server floor: network / ASN / IP reputation ← EVERY mode, always. Zero-JS, calibrated.
      · device reputation · velocity · dedup ·
      · history · server behavior

Every verification — including a full camera one — is scored by the server floor (L0) first. The camera provides the one thing nothing else can: proof a live, present, unique human is operating the session. Everything else is the shared floor beneath it.

Server-Side (no page code)

A stateless server-to-server scoring API you call once per respondent, where a legacy quality vendor (GRL / Research Defender) used to run. No camera, no client JavaScript, no PII stored. It returns a 0–100 risk score and an allow / review / block recommendation from network / device / velocity / duplicate / behavior / history signals.

POST https://vhuman.riwi.com/api/v1/lite/score
Authorization: Bearer <project API key>
Content-Type: application/json

{ "sessionId": "<your-id>", "clientIp": "<respondent-ip>",
  "userAgent": "<respondent-ua>", "sourceId": "<your-supply-source>",
  "studyId": "<your-questionnaire-id>" }   // optional; per-study duplicate scope

// → read  response.recommendation  (allow | review | block | step_up)

Pick it when you can't put code on the respondent's page, want zero friction, and a reputation-grade verdict (not biometric proof) is enough. The full field list, enum reference, identity-hashing spec, per-source calibration, and the evidence feedback loop are in the Server-Side scoring API reference — or manage the project over MCP.

How it's configured: a project's deploymentType selects the surface — fraud_gate for Server-Side (this mode, no page code) vs widget (the default, the SDK on the page). Set it in the dashboard, over MCP, or via PATCH /projects/{id}. Within widget, widgetMode picks how hard the on-page widget verifies (below).

Invisible / Captcha / Standard (the widget)

All three run the SDK on the respondent's page and differ only by widgetMode. Wiring for every path (React, Next.js, HTML drop-in, vanilla TS) is in the SDK guide; this is the summary.

widgetModeRespondent seesSignals
invisibleNothing. Runs silently. Camera never opens (unless escalateOnSuspicion).Server floor + on-page probe: device, behavioral, CDP/stealth, pointer entropy. No camera.
captchaOne-click / brief “verifying…” badge (~2–3 s). Camera runs hidden.Above + quick passive liveness + face presence.
standardFull camera with face guide; passive liveness + active challenges when needed.Above + full liveness, anti-spoof, biometric face-uniqueness.

Minimal wiring

// Managed (npm: import { VH } from '@verifyhuman/sdk';  CDN: window.VH)
const result = await VH.mount("#vh", {
  siteKey: "YOUR_SITE_KEY",
  widgetMode: "invisible",   // 'invisible' | 'captcha' | 'standard'
});

// React
import { VerifyHuman } from "@verifyhuman/sdk/react";
<VerifyHuman siteKey={SITE_KEY} widgetMode="captcha" onVerify={(t) => ...} />

The widgetMode option / prop overrides the per-project default set in the dashboard. A pure HTML data-sitekey drop-in has no data-widget-mode attribute, so it takes the mode from the project config — use VH.mount or <VerifyHuman> to choose it from code. See the three layers of “mode” for the full precedence rules.

device-only (automatic fallback)

Not a mode you choose. When a camera mode can't open the camera (blocked WebView, denied permission, model load failure), the flow completes without the camera instead of dead-ending — scored by the server floor, plus behavioral evidence if the widget collected any. You can tell it apart on the result (unifiedVerdict.assuranceLevel reports device_only or behavioral instead of biometric) and set a minimum-assurance policy to reject it. See In-app browsers & camera for the recovery ladder and the assurance taxonomy.

Reading the verdict — one vocabulary

Whatever mode you run, the normalized answer is allow / review / block plus an assurance tier.

  • Server-Side → read recommendation (allow · review · block · step_up). verdictClass (human / fraud / verified_agent / unknown) classifies who the actor is, separately from the action.
  • Widget → read unifiedVerdict.verdict (allow / review / block) for the same cross-mode band, or status (pass / fail) for the local widget outcome. unifiedVerdict.assuranceLevel (none / device_only / behavioral / biometric) tells you which ladder rung the verdict was reached at.

The widget maps its PASS / FAIL / CHALLENGE_REQUIRED decision onto the same allow/review/block words the Server-Side API uses (PASS → allow, CHALLENGE_REQUIRED → review, FAIL → block), so you only ever need one vocabulary for the answer. step_up (Server-Side only) is a review that specifically recommends escalating to a biometric check.