In-app browsers & the camera
A large share of survey traffic opens inside an in-app browser — the WebView embedded in Instagram, Facebook, TikTok, Telegram, LinkedIn, Gmail, and similar apps. On Android especially, these WebViews silently block the camera (they never forward the OS camera permission), so a biometric check can't run. VerifyHuman handles this for you automatically — this page explains what happens and the two knobs you can turn.
What the SDK does automatically
When the widget detects that the camera was blocked by the environment (not denied by the user), it does not fail the respondent as “not human.” Instead it runs a recovery ladder:
- In-widget QR handoff. The widget shows a “Verify on your phone” panel: a QR code, a Copy link, and (on Android) an Open in browser break-out. The respondent verifies in their phone's real browser, and the original tab resumes automatically with a full biometric verdict.
- Continue without camera. If they opt out (or the handoff can't complete), the widget completes a device-only check — a real verdict from behavioral + device signals, weaker than biometric but never a dead end. The respondent is never trapped.
This is on by default for any managed embed (the VH.mount() / HTML drop-in / React paths). You don't need to wire anything.
Read the result: the assurance taxonomy
Because a verification can now complete at different strengths, every verdict carries two fields so you always know what actually ran — on the mount result, the signed vh_token, the /token/verify response, and the webhook payload:
{
"status": "pass",
"assuranceLevel": "biometric", // biometric | device_only | none
"verificationOutcome": "completed", // completed | unverified_technical | declined_by_user
"token": "eyJ…"
}assuranceLevel— how strong the check was.biometric= a real camera liveness + uniqueness check ran (in-context or via the QR handoff).device_only= no camera; behavioral + device signals only.none= no evidence at all.verificationOutcome— why you landed there, so you can tell “wouldn't” from “couldn't.”completed= ran to a verdict.unverified_technical= the camera was blocked by the environment.declined_by_user= the respondent chose to continue without verifying.
Use these to route respondents however your study needs — e.g. accept everyone but flag device_only for review, or gate on biometric only.
Require a minimum assurance (optional)
By default VerifyHuman is do-no-harm: a device-only pass is accepted and clearly labeled, never blocked. A fraud-sensitive study can opt into a stricter floor with the project's minimum-assurance policy:
none(default) — accept any assurance; label, don't block.device_only— reject bare capture-failures / declines that reached a pass-like state.biometric— require a real camera check. Respondents in a blocked WebView still have the QR-handoff path to reach biometric before this rejects them.
Set it per project (minAssuranceLevel on the project config, via the dashboard or the API). Leave it at none unless you specifically need to enforce a camera check — it screens out real device-only respondents.
Handle the block yourself (advanced)
If you host your own recovery flow, pass an onCameraBlocked handler to VH.mount(). When the environment blocks the camera, the SDK calls your handler instead of showing its own QR panel, and hands control back to you. Omit it (the common case) and the SDK's built-in recovery runs.
VH.mount('#vh', {
siteKey: 'YOUR_SITE_KEY',
// optional — omit to use the SDK's built-in QR recovery:
onCameraBlocked: () => showMyOwnHandoff(),
})Best practice: start in the system browser
The most reliable fix is to avoid the in-app WebView entirely. When you control the entry point (a panel invite, an email, a survey redirect), prefer opening your survey in the phone's real browser, where the camera works in-context and no handoff is needed. On iOS there is no web-triggerable break-out, so the QR handoff is the reliable cross-platform path once you're already inside a WebView. See Survey integrations for the redirect-first setup on each platform.
Testing it
In-app camera blocks reproduce on a real Android device (iOS in-app browsers usually grant the camera). The quickest repro: paste your embed URL into Telegram → Saved Messages on Android and tap it — the camera is blocked and the QR panel appears. Scan it (or use Open in browser) to complete the handoff and watch the original tab resume.