API Documentation / Biometrics / Face Liveness
v1.4.0 Go to Console
Biometric Checks Deepfake Detection Check out New Version (unstable)

Liveness Check: Verify Real Person from a Selfie Image

Send a selfie as Base64 and receive an instant liveness verdict — LIVE, SPOOF, or INCONCLUSIVE — alongside a confidence score and a plain-language breakdown of every signal that contributed to the decision.

The engine analyses each image through 8 independent signals: sharpness, eye geometry, head orientation, face framing, facial symmetry, skin micro-texture (LBP), EXIF camera metadata, and a frequency-domain GAN fingerprint detector. A spoof must defeat multiple signals simultaneously to cross the liveness threshold.

Designed for KYC onboarding, account recovery, and re-authentication flows. Works with standard mobile selfies — no specialised hardware required.

🖨️

Printed photos

📱

Screen displays

🤖

Deepfakes & GANs

📷

Photo-of-a-photo

Endpoints

POST /v1/liveness/check/ Run liveness analysis
GET /v1/health/ Health probe

Request Payload

Send as Content-Type: application/json.

Field Description
image Base64 string · Required The selfie to analyse. Accepts a raw Base64 string or a data-URL prefix (data:image/jpeg;base64,...). Supported formats: JPEG, PNG, WebP, BMP. Maximum size: 10 MB.

Response Fields

Top-level envelope

Field Type Description
status string "success" or "error". Always check this first.
request_id string Unique identifier for this request. Format: lv_<16 hex chars>. Store this for audit trails and support queries.
timestamp string UTC response time in ISO 8601 format.
result object Detection result. Present on success; null on error.
error object Error detail. Present on failure; null on success.

result object

Field Type Description
verdict string "LIVE", "SPOOF", or "INCONCLUSIVE". See Verdicts below.
confidence float Aggregate liveness score ∈ [0, 1]. Higher = more confident the subject is live.
threshold float The decision threshold applied to produce the verdict. Default: 0.58.
face_detected boolean Whether a face was located in the submitted image.
signals array Array of 8 signal objects. Each describes one detection check. See Signals Reference below.

signals array items

Field Type Description
name string Machine-readable signal identifier (e.g. lbp_texture, fft_deepfake).
label string Human-readable name, safe for display in UIs and dashboards.
score float Signal score ∈ [0, 1]. Higher = more live-like for that check.
weight float This signal's contribution to the final confidence score. All 8 weights sum to 1.0.
passed boolean true if score ≥ 0.5. Convenience field — does not independently determine the verdict.
detail string Plain-language explanation of what was found. Safe to surface in logs, dashboards, and support tools.

Verdicts

LIVE

Confidence is at or above the threshold. The image is consistent with a real, live person.

→ Allow the user to proceed.

SPOOF

Confidence is more than 4 percentage points below the threshold. One or more signals indicate a spoof attempt.

→ Reject the attempt. Log request_id and confidence for your records.

INCONCLUSIVE

Confidence is within ±4 percentage points of the threshold, or no face was detected. The engine cannot make a confident determination.

→ Prompt the user to retake the photo under better lighting or closer to the camera.

Confidence score ranges

Range Interpretation
0.80 – 1.00Strong LIVE — multiple signals confirm a real face.
0.62 – 0.79Moderate LIVE — most signals passed, minor issues present (e.g. compressed image).
0.54 – 0.61Borderline — verdict is INCONCLUSIVE. Request a retake.
0.35 – 0.53Weak — likely SPOOF but signals are mixed.
0.00 – 0.34Strong SPOOF — multiple signals failed decisively.

Signals Reference

Eight independent signals are computed per image. Each contributes a weighted sub-score to the final confidence value. No single signal determines the verdict — a spoof must defeat several simultaneously.

01 Image Sharpness sharpness
Weight 12%

Measures image sharpness using the Laplacian variance of the greyscale image. Printed photos and screen recaptures are often blurry or have lower-frequency detail than a live camera selfie.

⚠ Mobile JPEG compression frequently reduces sharpness scores on genuine selfies. Weight is 12% to avoid penalising legitimate compressed uploads — the LBP texture signal covers micro-texture more precisely.
ScoreInterpretation
0.80 – 1.00Sharp, well-focused image
0.50 – 0.79Moderate sharpness — typical for compressed mobile selfies
0.00 – 0.49Soft or blurry — may indicate a recaptured image
02 Eye Aspect Ratio eye_aspect_ratio
Weight 13%

Computes the Eye Aspect Ratio (EAR) for both eyes using 6 MediaPipe landmarks per eye — the ratio of eye height to eye width. Naturally open eyes have an EAR of approximately 0.25–0.35. Flat printed or screen-displayed images tend to produce slightly lower or less consistent EAR values due to 2D distortion.

EAR = (‖p2 − p6‖ + ‖p3 − p5‖) / (2 × ‖p1 − p4‖)
ScoreInterpretation
0.80 – 1.00Eyes naturally open
0.50 – 0.79Partially open or slight occlusion
0.00 – 0.49Eyes closed or EAR below minimum threshold
03 Head Pose head_pose
Weight 13%

Extracts yaw, pitch, and roll from the 4×4 facial transformation matrix returned by MediaPipe. Extreme angles are more common when a phone or printout is held at an angle rather than a person facing the camera naturally.

Max yaw (left / right) ± 35°
Max pitch (up / down) ± 30°
ScoreInterpretation
0.85 – 1.00Near-frontal, well-aligned
0.50 – 0.84Slight rotation — within acceptable range
0.00 – 0.49Significant rotation detected
04 Face Area Ratio face_area_ratio
Weight 8%

Measures what fraction of the image is occupied by the face bounding box. The optimal range for a selfie is 10–40%. Very small faces can indicate a photo-of-a-photo attack; faces filling the entire frame can indicate a tightly cropped spoof image.

ConditionScore
Face < 4% of image areaPenalised
Face 4% – 80% of image areaScored (optimal at 20%)
Face > 80% of image areaFixed 0.50
05 Facial Symmetry facial_symmetry
Weight 12%

Compares the positions of symmetric landmark pairs — eye corners, mouth corners, jawline edges — relative to the vertical midline of the face. Real faces are approximately symmetric. Warped, crumpled, or perspectively distorted spoof images show elevated asymmetry.

ScoreInterpretation
0.80 – 1.00Highly symmetric — consistent with a genuine face
0.50 – 0.79Mild asymmetry — within normal limits
0.00 – 0.49Notable asymmetry detected
06 LBP Skin Texture lbp_texture Highest weight
Weight 20%

Extracts a 96×96 crop of the face region and computes a uniform Local Binary Pattern (LBP) histogram, which encodes the micro-texture of skin. Real skin has varied, non-uniform texture at the pixel level. Printed photos — even high-quality ones — and phone screen displays produce either flattened texture from halftone dot patterns or periodic pixel-grid structures.

Two sub-metrics are combined: Shannon entropy (real skin scores higher — more varied patterns) and dominant bin ratio (real skin stays below 0.60; spoofs typically exceed 0.65).

Unlike sharpness, LBP texture is not degraded by JPEG compression — making it robust for real-world mobile uploads where selfies are frequently compressed in transit.
ScoreInterpretation
0.80 – 1.00Skin texture matches a real face captured by a camera
0.55 – 0.79Broadly consistent — some compression artefacts reduce texture variance
0.35 – 0.54Partial texture uniformity — possible flat medium
0.00 – 0.34Highly uniform or periodic texture — strong spoof indicator
07 EXIF Metadata exif_metadata
Weight 10%

Analyses EXIF metadata embedded in the raw image bytes before any re-encoding. Genuine camera photos carry hardware metadata — camera make/model, f-stop, ISO, shutter speed, focal length, GPS. Screenshots and images captured with screen-recording tools typically have no such metadata, or reveal their software origin in the EXIF Software tag.

Missing EXIF is treated as neutral (0.50), not suspicious. EXIF is routinely stripped by WhatsApp, Telegram, browser uploads, CDNs, and base64 re-encoding pipelines. Only confirmed camera hardware rewards the score; only a confirmed spoof-tool Software tag penalises it.
ConditionScore
No EXIF found0.50 (neutral)
EXIF present, no camera hardware tags0.55
Camera make / model confirmed0.75
Camera + optical parameters presentup to 1.00
Screen-capture or editing software detected0.10

Detected spoof keywords: screenshot · screen capture · snipping · obs · bandicam · photoshop · gimp · preview · snagit

08 FFT Deepfake Fingerprint fft_deepfake New
Weight 12%

Analyses the frequency domain of the face region to detect artefacts left by GAN-based image generators and face-swap models — StyleGAN, ProGAN, FaceSwap, DeepFaceLab, and similar tools. These artefacts are largely invisible to the human eye but are statistically distinct from natural camera images.

Three sub-metrics are combined into the final score:

Ring kurtosis (50% of signal) — GAN decoders leave discrete energy spikes in the mid-frequency band of the 2-D FFT. These inflate the statistical kurtosis well above the natural image baseline of ~3. Real images score near 1.0; GAN images often score below 0.5.
High-frequency energy ratio (30% of signal) — Natural images follow a 1/f² power spectral density. GAN outputs deviate from this rolloff. The score decays as the measured ratio drifts from the natural-image baseline.
Azimuthal variance (20% of signal) — Real images have roughly isotropic frequency spectra. Square convolution kernels in GANs produce directional energy bias at 45° and 90° multiples, causing elevated angular variance.
ScoreInterpretation
0.80 – 1.00Frequency spectrum consistent with a natural camera image — no GAN fingerprints
0.60 – 0.79Broadly natural — minor anomalies may result from heavy compression
0.40 – 0.59Moderate frequency anomalies — possible GAN-generated content or face-swap processing
0.00 – 0.39Strong periodic artefacts and directional bias — consistent with GAN generation

No additional dependencies — computed using NumPy FFT, which is included in the base installation.

Error Codes

HTTP Code Cause & Resolution
422 INVALID_REQUEST The image field is missing, blank, not valid base64, or exceeds 10 MB.
200 NO_FACE_DETECTED No face found in the image. The subject may be too far away, heavily occluded, or the image may be too dark or low-resolution.
200 INFERENCE_ERROR An unexpected failure occurred during analysis. Retry the request. If the issue persists, contact support with the request_id.
500 SERVER_ERROR Unhandled server exception. Contact support and include the request_id if present in the response.

Image Requirements

Accepted formats
JPEGRecommended
PNGAccepted
WebPAccepted
BMPAccepted
Constraints
Max file size10 MB
Min resolution224 × 224 px
EncodingBase64 or data-URL
Faces per image1 (primary only)
Best practices for highest accuracy
  • Face should occupy 10–40% of the image area — standard selfie distance from a phone.
  • Subject should face the camera roughly forward — head rotation under ±30° in any axis.
  • Adequate, even lighting — avoid strong backlighting, shadows across the face, or heavy glare.
  • Exactly one face per image — do not submit group photos or cropped identity documents.
  • Do not apply filters, beauty effects, or heavy post-processing before submission.

Configuration

All thresholds are set in liveness_api/settings.py under LIVENESS_CONFIG. Changes take effect on server restart. Contact your account manager if you need threshold adjustments for your specific use case.

Parameter Default Description
live_threshold0.58Confidence ≥ this → LIVE. Within ±0.04 → INCONCLUSIVE.
min_face_confidence0.60Minimum MediaPipe face detection confidence to proceed with analysis.
min_blur_variance40.0Laplacian variance floor. Reduce for environments where images are heavily compressed.
min_ear0.15Eye Aspect Ratio below this value is treated as closed eyes.
max_yaw_deg35.0Maximum tolerated head yaw before the pose score begins to decay.
max_pitch_deg30.0Maximum tolerated head pitch before the pose score begins to decay.
min_face_area_ratio0.04Face bounding-box area as a fraction of image area below this value is penalised.
max_asymmetry0.20Symmetry index above this value yields a facial symmetry score of 0.
lbp_dominant_bin_spoof_threshold0.60LBP dominant bin fraction above which skin texture is considered suspiciously uniform.
fft_kurtosis_max12.0Ring kurtosis ceiling. Real images ≈ 3; GAN images often exceed 6.
fft_hf_ratio_baseline0.65Expected high-frequency energy ratio for a natural compressed selfie.
fft_az_variance_max0.35Azimuthal variance above this indicates directional GAN convolution bias.

Features & Benefits

🛡️

8-Signal Ensemble

No single check decides the outcome. A spoof must simultaneously defeat sharpness, LBP texture, head pose, eye geometry, facial symmetry, face area, EXIF metadata, and the FFT deepfake detector to cross the liveness threshold.

🤖

Deepfake Detection

The FFT fingerprint signal specifically targets GAN-generated and face-swapped images — attack vectors that bypass traditional liveness checks based on sharpness or geometry alone.

📱

Mobile-Optimised

Thresholds and signal weights are calibrated for compressed JPEG selfies from modern smartphones — designed to minimise false rejections of legitimate users while maintaining strong fraud resistance.

Fast & Lightweight

All 8 signals run synchronously in a single request. Typical response under 200 ms on a 2-vCPU instance. The FFT signal uses NumPy only — no additional model downloads or infrastructure required.

For high-security use cases such as financial onboarding or regulated KYC flows, we recommend combining this API with an active liveness challenge (blink or head-turn prompt) and a certified ISO/IEC 30107-3 anti-spoofing SDK. Contact your account manager to discuss enterprise options.