The Selfie Scan module captures the user's face with their device's camera and runs configurable liveness, face recognition, and image quality checks. It can enroll new users so their face can be matched against an ID photo or used for later authentication. It can also log in returning users using 1:1 or 1:N face authentication.
For an overview of this module and how it works, see Face Capture.
How you use this module depends on your integration pattern. In Patterns 1 and 2, you add the module to a FlowConfig in code as shown on this page. In Pattern 3, you define your modules and configuration in Dashboard as a Flow or Workflow and reference it by ID with startFlow() or startWorkflow() as shown on Run Flows Configured in Dashboard.
Add Selfie Scan
Add the module with one of the addSelfieScan overloads. Most onboarding flows require Selfie Scan, and some modules depend on ordering: for example, Face Match needs Selfie Scan and an ID or QR Scan added first. FlowConfig.Builder.build() throws ModuleConfigurationException if a required module or ordering rule is broken.
// Default configuration
flowConfigBuilder.addSelfieScan()
// Custom configuration
flowConfigBuilder.addSelfieScan(selfieScan)
// Default configuration
flowConfigBuilder.addSelfieScan();
// Custom configuration
flowConfigBuilder.addSelfieScan(selfieScan);
Selfie Scan ships both a v1 (legacy View) and a v2 (Jetpack Compose) capture screen; the active one depends on your Incode configuration. Contact your Incode representative to enable v2. In v2, tablets are landscape-locked with an optimized layout and phones are portrait-locked.
Example
The example below builds a SelfieScan module with tutorials shown, adds it to the flow, and listens for the result through onSelfieScanCompleted().
val selfieScan = SelfieScan.Builder()
.setShowTutorials(true)
.build()
val flowConfig = FlowConfig.Builder()
.addSelfieScan(selfieScan)
.build()
val onboardingListener = object : IncodeWelcome.OnboardingListener() {
override fun onSelfieScanCompleted(selfieScanResult: SelfieScanResult) {
// Selfie scan completed
}
override fun onError(error: Throwable) {
// Onboarding flow was aborted due to error
}
}
IncodeWelcome.getInstance().startOnboarding(
activityContext,
sessionConfig,
flowConfig,
onboardingListener
)
SelfieScan selfieScan = new SelfieScan.Builder()
.setShowTutorials(true)
.build();
FlowConfig flowConfig = new FlowConfig.Builder()
.addSelfieScan(selfieScan)
.build();
IncodeWelcome.OnboardingListener onboardingListener = new IncodeWelcome.OnboardingListener() {
@Override
public void onSelfieScanCompleted(@NonNull SelfieScanResult selfieScanResult) {
// Selfie scan completed
}
@Override
public void onError(@NonNull Throwable error) {
// Onboarding flow was aborted due to error
}
};
IncodeWelcome.getInstance().startOnboarding(
activityContext,
sessionConfig,
flowConfig,
onboardingListener
);
Configuration Options
Configure the module with SelfieScan.Builder. The scan mode and where liveness and recognition run also depend on your Incode Flow or Workflow configuration, not just these options.
| Setting | Description |
|---|---|
setMode |
Sets the scan mode: Mode.ENROLL, Mode.LOGIN, or Mode.MASK_CHECK. Default is Mode.ENROLL. |
setFaceAuthMode |
Runs face detection and liveness on LOCAL or the SERVER. Default is FaceAuthMode.SERVER. |
setShowTutorials |
Shows a tutorial before the scan. Default is true. |
setMaskCheckEnabled |
Enables local face-mask detection during capture. |
setCameraFacing |
Selects CameraFacing.FRONT or CameraFacing.BACK. Default is CameraFacing.FRONT. Has no effect in some SDK versions; check SelfieScan.Builder in API Reference for current behavior. |
setAutoCaptureTimeout |
Sets the selfie auto-capture timeout, in seconds. |
setOnDeviceFaceResultsSubmissionEnabled |
Runs liveness detection and age estimation on-device, submitting only the score to the backend. Requires end-to-end encryption, the liveness-detection and age-estimation model dependencies, and the V2 UI; incompatible with frame streaming, screen recording, and video liveness recording. |
In CAPTURE_ONLY mode, captured media stays on the device. See Capture-Only Mode for the capture-only data flow.
For the complete option set, see SelfieScan.Builder in API Reference.
Result
Selfie Scan delivers a SelfieScanResult to the onSelfieScanCompleted(selfieScanResult) callback on OnboardingListener. Key fields include:
isSpoofAttempt:falseif user is a real person;trueif there was a spoof attempt. Populated only when a server-side face evaluation runs andstatusisSTATUS_OKorSTATUS_SPOOF_DETECTED; otherwise,null, including in Capture-Only, on-device, and offline modes.hasFaceMask:trueif a face mask is detected,falseif not,nullif the check wasn't performed.croppedSelfieImgPath: The file path to the cropped selfie image.fullFrameSelfieImgPath: The file path to the full-frame selfie image.status: The selfie scan status. One of the following:STATUS_OK(0): All preconditions for checking liveness are met.STATUS_LENSES_DETECTED(1): The user is wearing lenses.STATUS_TOO_DARK(2): The photo is too dark for reliable results.STATUS_TOO_BLURRY(3): The photo is too blurry for reliable results.STATUS_FACE_NOT_FOUND(4): No face meeting the constraints was found.STATUS_FACE_TOO_SMALL(5): The face dimensions are insufficient.STATUS_INSUFFICIENT_PHOTO_QUALITY(6): Photo quality too low to check liveness. This is often because of bad lighting.STATUS_GENERIC_ERROR(7): A generic error occurred while producing the result.STATUS_NO_RESULT(9): No status has been produced yet.STATUS_MASK_DETECTED(10): The user is wearing a mask.STATUS_CLOSED_EYES_DETECTED(11): The user has their eyes closed.STATUS_HEAD_COVER_DETECTED(12): A head covering such as a hat is detected.STATUS_SPOOF_DETECTED(13): A spoof attempt is detected.
selfieBase64: The Base64-encoded cropped selfie image. Redacted fromtoString().fullFrameSelfieEncryptedBase64: The encrypted Base64-encoded full-frame selfie image. Redacted fromtoString().fullFrameSelfieBase64: The Base64-encoded full-frame selfie image. Redacted fromtoString().metadata: Proprietary capture metadata required by the SDK. Populated only whenSdkModeisCAPTURE_ONLY; otherwise,null.videoFilePath: The path to the original, unencrypted video-liveness recording. Populated only whensetVideoLivenessRecordingEnabled(true)andSdkModeisCAPTURE_ONLY; otherwise,null. For transmission, usepresignedVideoFilePath.presignedVideoFilePath: The path to the video-liveness file prepared for back-end transmission. It contains base64 text and is not cryptographically encrypted. Populated only whensetVideoLivenessRecordingEnabled(true)andSdkModeisCAPTURE_ONLY; otherwise,null.allAttemptsExhausted:trueif no further capture or upload retries are available for this selfie scan.isBlocklisted:trueif the recognized user is on the blocklist and login was denied (faceLoginResult.successisfalse). Set only during server-side face authentication inLOGINmode; alwaysfalsein LOCAL mode. This result is available for SDK versions 5.50.0 and newer.faceRecognitionConfidence: The similarity score between stored face and captured selfie. This result was deprecated in SDK version 5.2.0.isFaceMatched: If the stored face and selfie match. This result was deprecated in SDK version 5.35.0; usefaceLoginResult.successinstead.spoofConfidence: The likelihood of a spoofing attempt. This result was deprecated in SDK version 5.2.0; useisSpoofAttemptinstead.maskConfidence: The likelihood the person is wearing a mask. This result was deprecated in SDK version 5.18.0; usehasFaceMaskinstead.selfieEncryptedBase64: The encrypted Base64 cropped selfie. This result was deprecated in SDK version 5.12.0; useselfieBase64/fullFrameSelfie*.idealCaptureEnvironmentTestResult: The result of the ideal-capture-environment test. This result was deprecated in SDK version 5.39.0; usemetadatainstead.faceLoginResult: The result of the Face Login operation populated inSelfieScan.Mode.LOGIN. One of the following:success:trueif the face login succeeded; otherwise,false.customerUUID: The customer UUID of the recognized user;nullwhen unavailable.interviewId: The interview ID for the login session;nullwhen unavailable.interviewToken: The interview token for the login session;nullwhen unavailable.token: The session token associated with the login;nullwhen unavailable.transactionId: The transaction ID for the login operation;nullwhen unavailable.
Fields inherited from
BaseResult:resultCode: TheResultCodefor this result.error: WhenresultCodeisERROR, theThrowablethat caused it; otherwise,null.deviceStats: TheDeviceStatssnapshot of the device state when the result was produced. InCAPTURE_ONLYmode this info is also available inmetadata.motionStatus: Device motion assessment during capture. One of the following:UNCLEAR: Motion could not be determined; the default.PASS: Device motion was within acceptable limits.FAIL: Excessive device motion was detected.
If the scan cannot complete, the flow is aborted and the error surfaces via OnboardingListener.onError(Throwable).
For all fields, see SelfieScanResult in API Reference.