Self-hosted · nothing stored

Identity verification with real liveness detection, embedded in minutes.

liveCheck compares a live selfie against an ID photo and confirms a real person is present — blink or head-turn challenges, not just a static photo — then hands you the result. No customer data ever touches a disk or database.

How it works

One iframe or WebView, five steps, no server-side session store.

Embed the widget

GET /widget?origin=<your origin> in an iframe or WebView.

Capture the ID

The widget captures a photo of the user's ID document.

Issue a challenge

A signed, short-lived JWT assigns a random liveness action: blink, turn left, or turn right.

Record & submit

~5 seconds of webcam frames are captured while the user follows the instruction.

Verify & return

Liveness and face match run in memory; the result is posted back to the host page.

Built for privacy and drop-in integration

🔒

Nothing persisted

ID photos and selfie frames are decoded into memory, processed, and discarded when the request ends.

👀

Active liveness challenges

Random blink / head-turn prompts via MediaPipe FaceMesh, not a passive photo check.

👤

Face matching

Compares a face encoding from the ID photo against the best captured selfie frame (face_recognition / dlib).

🌐

Web & mobile, same widget

Embed via <iframe> on the web, or load the same URL in a React Native / native WebView.

Stateless by design

The only "session" is a signed, expiring JWT — there is no server-side session store to manage.

⚙️

Origin-locked embedding

ALLOWED_ORIGINS and a frame-ancestors CSP control exactly who can embed the widget.

Embed it

Get your origin allowlisted by the operator, then drop this in.

<!-- website (iframe) --> <iframe src="https://verify.yourapp.com/widget?origin=https://your-site.com" allow="camera" width="420" height="640"> </iframe> <script> window.addEventListener("message", (event) => { if (event.origin !== "https://verify.yourapp.com") return; if (event.data?.type !== "liveCheck:result") return; const { passed, confidence } = event.data; // handle result }); </script>

The same URL works in a React Native WebView or a native iOS/Android WebView — the widget detects the runtime and posts the result via both window.parent.postMessage and window.ReactNativeWebView.postMessage automatically.

The response shape is the same everywhere:

{ "passed": true, "confidence": 0.87, "liveness": { "passed": true, "score": 0.91, "reason": "Blink detected" }, "face_match": { "matched": true, "confidence": 0.83, "reason": "Face matches ID document" } }

Or use an SDK

Typed wrappers around the iframe/WebView + message-bridge boilerplate above — same result shape everywhere.

💻

Web

npm install livecheck-sdk

sdk/web — promise-based LiveCheckWidget, mounts the iframe and checks the sender origin for you.

🍑

iOS

.package(path: "sdk/ios")

sdk/ios — a LiveCheckView (Swift Package) wrapping the WKWebView + JS bridge.

🤖

Android

include(":livecheck-sdk")

sdk/android — a LiveCheckView (Kotlin module) wrapping WebView + JS interface.

All three carry the same limitation as the raw integration: results arrive over a channel the client controls, so they're fine for UX gating but aren't a backend-verifiable receipt.

Pricing

Start free, pay as you scale, or bring it fully in-house.

Free

$0

up to 100 verifications

  • Full widget & SDK access
  • Blink / head-turn liveness
  • Face match verification
  • Community support
Start free
Popular

Pro

$35/month

1,000 verifications / month

  • Everything in Free
  • Higher rate limits
  • Web, iOS & Android SDKs
  • Email support
Get started

Enterprise

  • Everything in Pro
  • Custom rate limits & SLA
  • Priority support
  • Dedicated onboarding
Talk to sales

Pay-per-verification

$0.04 / face match

No monthly commitment. ~$0.33 per check when bundled into a full KYC identity workflow.

Custom integration

$5,000 – $10,000+

Dedicated mobile or web integration built around a custom neural network for your product.

On-premise / self-hosted

Talk to sales

Fully self-hosted deployment on your own infrastructure for high-security requirements — no customer data ever leaves your servers.

Security notes

Know the limits before you rely on this in production.

Not a fraud-proof passive anti-spoofing system. Active-challenge liveness (blink / head-turn) has no passive replay detection — a convincing video replay of the requested action could pass. The client-side postMessage result is fine for UX gating (unlocking a "Continue" button) but is not, on its own, a safe basis for backend decisions like releasing funds — there is currently no signed, backend-verifiable receipt. See INTEGRATE.md for the full guidance.