> For the complete documentation index, see [llms.txt](https://docs.vida.id/identity-stack/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.vida.id/identity-stack/verify/liveness/integration/liveness-web-sdk/customization/configuration-options.md).

# Configuration Options

### Full Configuration Example - With Default Values <a href="#full-configuration-example-with-default-values" id="full-configuration-example-with-default-values"></a>

{% code expandable="true" %}

````js
# Liveness Workflow — Init Configuration

```js
VidaSDK.init({
  /* ═══════════════════════════════════════════════════
   * REQUIRED
   * ═══════════════════════════════════════════════════ */

  // Your JWT Token
  token: '<your-token>',

  // Your Signing Key
  signingKey: '<your-signing-key>',

  /* ═══════════════════════════════════════════════════
   * GENERAL
   * ═══════════════════════════════════════════════════ */

  // DOM element ID where SDK renders. Element must exist in the DOM. Optional
  elementId: 'root',

  // Workflow type. Defaults to 'liveness'
  workflow: 'liveness',

  // UI language. Options: 'EN' | 'ID'
  locale: 'EN',

  // User context for fraud detection. userInfo.id is required if device fraud shield is enabled.
  userInfo: { id: 'user-123' },

  // Partner's transaction ID for tracking.
  partnerTransactionId: '',

  // Client ID to enable device fraud detection. If set, userInfo.id becomes required.
  fraudShieldClientId: '',

  /* ═══════════════════════════════════════════════════
   * UI VISIBILITY
   * ═══════════════════════════════════════════════════ */

  // Hide the session ID display.
  hideSessionId: false,

  // Hide the network status offline alert.
  hideNetworkStatusAlert: false,

  /* ═══════════════════════════════════════════════════
   * CALLBACKS
   * ═══════════════════════════════════════════════════ */

  // Called when liveness verification completes successfully.
  onComplete: (data) => console.log('onComplete', data),

  // Called when liveness verification fails.
  onError: (data) => console.log('onError', data),

  // Called when a selfie is captured. Receives base64 image string.
  onSelfieCapture: (image) => console.log('onSelfieCapture', image),

  /* ═══════════════════════════════════════════════════
   * WORKFLOW CONFIGS
   * ═══════════════════════════════════════════════════ */
  workflowConfigs: {
    liveness: {
      // Skip the tutorial/onboarding screen.
      skipTutorialScreen: false,

      // Skip the selfie review confirmation screen. Directly submits the captured selfie.
      skipSelfieReviewScreen: false,

      // Camera frame shape overlay. Options: 'circle' | 'oval' | 'square' | 'rectangle'
      cameraFrameShape: 'oval',

      // Face detection timeout in milliseconds. Must be a positive integer.
      detectionTimeOut: 90000,

      // Duration (ms) to show countdown alert before timeout. Must be less than detectionTimeOut.
      detectionTimeOutCountdownDuration: 20000,

      // Hide the countdown alert that appears before detection timeout.
      hideDetectionTimeOutCountdownAlert: false,

      // Maximum retry attempts allowed. Must be a positive integer.
      maxRetryAttempts: 3,

      // Hide the error message when max retries are exhausted.
      hideMaxRetryError: false,

      // Hide the static head shape overlay on the camera screen.
      hideStaticHeadShape: false,

      // Skip the white screen flash effect in low-light conditions.
      skipDarkLightingScreenFlash: false,

      // Hide the help button on the camera capture screen.
      hideHelpOnCaptureScreen: false,

      // Hide error codes displayed on the selfie review screen.
      hideErrorCodeOnSelfieReview: false,

      // Granular control to hide description text on individual screens.
      hideDescriptions: {
        tutorial: false, // Hide tutorial screen description
        cameraAccess: false, // Hide camera access prompt description
        camera: false, // Hide camera screen description
        selfieReview: false, // Hide selfie review screen description
      },
    },
  },

  /* ═══════════════════════════════════════════════════
   * THEME CONFIGS
   * All fields are optional. Shown values are defaults.
   * ═══════════════════════════════════════════════════ */
  themeConfigs: {
    // Typography
    fontFamily: 'Plus Jakarta Sans, sans-serif', // Font family for all SDK text
    fontFamilyUrl: 'https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap', // Fonts URL to load a custom font
    titleTextColor: '#333334', // Title text color
    titleTextFontSize: '20px', // Title text font size
    descriptionTextColor: '#4C4D4F', // Description text color
    descriptionFontSize: '14px', // Description text font size
    bodyTextColor: '#4C4D4F', // Body text color
    bodyTextFontSize: '14px', // Body text font size

    // Primary button
    primaryButtonBgColor: '#00EB76', // Background color
    primaryButtonBorderColor: 'none', // Border color
    primaryButtonHoverBgColor: '#00EB76', // Hover background color
    primaryButtonDisabledBgColor: '#BBBBBB', // Disabled background color
    primaryButtonTextColor: '#142C42', // Text color
    primaryButtonHoverTextColor: '#FFFFFF', // Hover text color
    primaryButtonBorderRadius: '6px', // Border radius

    // Secondary button
    secondaryButtonBgColor: '#FFFFFF', // Background color
    secondaryButtonBorderColor: '#DCE1E7', // Border color
    secondaryButtonHoverBgColor: '#F4F4F5', // Hover background color
    secondaryButtonDisabledBgColor: '#BBBBBB', // Disabled background color
    secondaryButtonTextColor: '#142C42', // Text color
    secondaryButtonHoverTextColor: '#142C42', // Hover text color
    secondaryButtonBorderRadius: '6px', // Border radius

    // Camera & frame
    cameraFrameBorderInitialColor: '#FFFFFF', // Initial frame border color
    cameraFrameBorderAnimationColor: '#00EB76', // Animated frame border color (progress)
    cameraFrameOverlayColor: '#000000', // Overlay color outside the frame
    instructionIconColor: '#000000', // Tutorial instruction icon color
    cameraInstructionTextColor: '#FFFFFF', // Camera feedback text color
    cameraInstructionBgColor: '#00172F', // Camera feedback background color
    cameraInstructionFontSize: '12px', // Camera feedback font size
    cameraCaptureButtonColor: '#FFFFFF', // Capture button color

    // Alerts & errors
    errorAlertBgColor: '#FEE2E2', // Error alert background color
    errorAlertTextColor: '#991919', // Error alert text color
    errorAlertTextFontSize: '14px', // Error alert font size
    errorTextColor: '#DC2626', // Error text color

    // UI controls
    loadingSpinnerColor: '#00EB76', // Loading spinner color
    backButtonColor: '#000000', // Back button color
    modalCloseButtonColor: '#000000', // Close button color
    sessionIdFontSize: '12px', // Session ID font size
    backgroundColor: '#FFFFFF', // SDK background color
  },

  /* ═══════════════════════════════════════════════════
   * LOCALE CONFIGS
   * Custom text overrides for EN and ID locales.
   * All fields are optional — SDK uses defaults if not provided.
   * Only 'EN' and 'ID' locale keys are supported.
   * ═══════════════════════════════════════════════════ */
  localeConfigs: {
    liveness: {
      EN: {
        sessionId: 'Session ID', // Session ID label
        networkStatus: 'You seem to be offline. Please check your internet connection', // Offline status message

        // Tutorial screen
        livenessTutorial: {
          title: 'Capture Your Selfie', // Screen title
          description: 'Position your face within the frame.', // Screen description
          instructions: {
            holdPhoneSteady: 'Hold the phone steady using both hands', // (Visible for mobile/tanlet devices) Instruction: steady phone
            avoidGlasses: "Don't wear glasses", // Instruction: no glasses
            avoidBrightPlace: 'Avoid being in a very bright place', // (Visible for color flash) Instruction: avoid bright light
            faceFullyVisible: 'Ensure your face is fully visible within the frame', // (Visible for desktop devices) Instruction: face visibility
          },
          actionButton: 'Start Selfie Capture', // Start button text
        },

        // Selfie capture screen (camera screen)
        selfieCapture: {
          title: 'Capture Your Selfie', // Screen title (when camera allowed)
          description: 'Follow the instructions provided and ensure your face is clearly visible', // Screen description
          helpText: 'Need Help?', // Help button text
          helpBackButton: 'Back', // Help overlay back button
          selfieCaptureTipsTitle: 'Capture Your Selfie', // Selfie tips overlay title
          docCaptureTipsTitle: 'Document Capture Tips', // Doc tips overlay title
          noFaceDetected: 'Put your face in the frame', // Feedback: no face found
          faceDetected: 'Stay still', // Feedback: face detected, capturing
          placeFaceinFrame: 'Put your face in the frame', // Feedback: face outside frame
          multipleFaceDetected: 'Ensure no additional faces are visible in the frame', // Feedback: multiple faces
          faceTooFar: 'Move closer', // Feedback: face too far
          faceNotStraight: 'Keep your face straight', // Feedback: face angle off
          faceToodark: 'Move to well-lit area', // Feedback: too dark
          faceTooBright: 'Too bright', // Feedback: too bright
          eyesClosed: 'Open your eyes', // Feedback: eyes closed
          detectionTimeOut: '${time} seconds left to complete your verification', // Countdown alert. ${time} is replaced with seconds remaining.

          // Camera permission prompt
          permission: {
            title: 'Allow Camera Access', // Permission screen title
            description: 'To continue, please enable camera access. We cannot verify your identity without using your camera.', // Permission description
            actionButton: 'Allow', // Permission action button
          },

          // Camera error screen
          error: {
            title: 'The camera is either not supported or the access is denied.', // Error title
            description: 'If you denied camera access by mistake, follow these steps:', // Error description
            actionButton: 'Retry', // Retry button
            unsupportedDeviceTitle: 'Unable to proceed', // Unsupported device error title
            unsupportedDeviceDescription: 'Unsupported device. Switch to a compatible device or use a desktop/mobile browser.', // Unsupported device description
            moduleDownloadErrorTitle: 'Unable to proceed', // Face detection module download error title
            moduleDownloadErrorDescription: 'Module download failed. Check your connection and try again', // Module download error description
            browserPrivacyModeErrorTitle: 'Unable to proceed', // Private/incognito mode error title
            browserPrivacyModeErrorDescription:
              'Face detection failed. Do not use a private window, and disable browser tracking protection for this site before trying again.', // Privacy mode error description
          },
        },

        // Selfie review screen
        selfieReview: {
          title: 'Review Photo', // Screen title
          description: 'Ensure the image is well-lit, clear, and that all features are visible', // Screen description
          primaryActionButton: 'Submit Photo', // Submit button
          secondaryActionButton: 'Retake Selfie', // Retake button
          tryLaterButton: 'Try Again Later', // Try later button (shown on max retry)

          // Backend error messages (error code → display text)
          backendError_1041: 'Liveness verification failed', // Liveness failed
          backendError_1051: 'Remove any obstructions from your face', // Face obstruction
          backendError_1052: 'Move closer', // Face too far
          backendError_1053: 'Please ensure the lighting is sufficient and the photo is clear', // Bad image quality
          backendError_1054: 'Ensure no additional faces are visible in the frame', // Multiple faces
          backendError_1055: 'Put your face in the frame', // No face detected
          backendError_1058: 'Please ensure the lighting is sufficient and the photo is clear', // Face too dark
          backendError_1059: 'The selfie is blurry, hold your phone steady', // Blurry image
          backendError_1060: 'Keep your face straight', // Face not straight
          backendError_1062: 'Open your eyes', // Eyes closed
          backendError_1063: 'Please ensure the lighting is sufficient and the photo is clear', // Unnatural color
          backendError_1064: "The selfie is too dark, ensure there's enough lighting for a clear photo", // Under exposure
          backendError_1074: "The selfie is too dark, ensure there's enough lighting for a clear photo", // Under exposure (alt)
          backendError_1065: 'The selfie is too bright, please adjust the lighting for a clear photo', // Over exposure
          backendError_1075: 'The selfie is too bright, please adjust the lighting for a clear photo', // Over exposure (alt)
          backendError_1066: 'The selfie is blurry, hold your phone steady', // Blurry (alt)
          backendError_1076: 'The selfie is blurry, hold your phone steady', // Blurry (alt)

          sessionExpired: 'Session expired. Please restart the selfie process to continue', // Session timeout
          unknownError: 'Oops! Something went wrong, please try again later', // Generic error
          maxRetryExhausted: "You've reached the maximum number of attempts. Please try again later", // Max retry reached
        },
      },
      ID: {
        sessionId: 'ID Sesi',
        networkStatus: 'Sepertinya Anda offline. Silakan periksa koneksi internet Anda',

        livenessTutorial: {
          title: 'Ambil Swafoto',
          description: 'Posisikan wajah Anda dalam bingkai.',
          instructions: {
            holdPhoneSteady: 'Pegang telepon dengan stabil menggunakan kedua tangan',
            avoidGlasses: 'Jangan memakai kacamata',
            avoidBrightPlace: 'Hindari berada di tempat yang terlalu terang',
            faceFullyVisible: 'Pastikan wajah Anda terlihat sepenuhnya dalam bingkai',
          },
          actionButton: 'Mulai Pengambilan Selfie',
        },

        selfieCapture: {
          title: 'Ambil Swafoto',
          description: 'Ikuti petunjuk yang diberikan dan pastikan wajah Anda terlihat jelas',
          helpText: 'Butuh Bantuan?',
          helpBackButton: 'Kembali',
          selfieCaptureTipsTitle: 'Ambil Swafoto',
          docCaptureTipsTitle: 'Tip Pengambilan Dokumen',
          noFaceDetected: 'Tempatkan wajah Anda dalam bingkai',
          faceDetected: 'Tetap diam',
          placeFaceinFrame: 'Tempatkan wajah Anda dalam bingkai',
          multipleFaceDetected: 'Pastikan hanya satu wajah di layar',
          faceTooFar: 'Mendekat',
          faceNotStraight: 'Hadapkan wajah ke layar',
          faceToodark: 'Pindah ke tempat cerah',
          faceTooBright: 'Terlalu silau',
          eyesClosed: 'Buka mata Anda',
          detectionTimeOut: 'Waktu hampir habis, ${time} detik tersisa untuk verifikasi',
          permission: {
            title: 'Izinkan akses kamera',
            description:
              'Untuk melanjutkan, Anda perlu mengizinkan akses kamera. Kami tidak dapat memverifikasi Anda tanpa menggunakan kamera.',
            actionButton: 'Izinkan',
          },
          error: {
            title: 'Kamera tidak didukung atau akses ditolak.',
            description: 'Jika Anda tidak sengaja menolak akses kamera, ikuti langkah-langkah berikut:',
            actionButton: 'Coba kembali',
            unsupportedDeviceTitle: 'Tidak dapat melanjutkan',
            unsupportedDeviceDescription: 'Perangkat tidak didukung. Gunakan perangkat lain atau beralih ke desktop/mobile.',
            moduleDownloadErrorTitle: 'Tidak dapat melanjutkan',
            moduleDownloadErrorDescription: 'Pengunduhan modul gagal. Pastikan koneksi internet stabil dan coba lagi',
            browserPrivacyModeErrorTitle: 'Tidak dapat melanjutkan',
            browserPrivacyModeErrorDescription:
              'Deteksi wajah gagal. Jangan gunakan jendela private, dan nonaktifkan perlindungan pelacakan browser untuk situs ini sebelum mencoba lagi.',
          },
        },

        selfieReview: {
          title: 'Tinjau Foto',
          description: 'Pastikan pencahayaan foto baik dan tampak jelas',
          primaryActionButton: 'Kirim Foto',
          secondaryActionButton: 'Ulangi Selfie',
          tryLaterButton: 'Coba Lagi',
          backendError_1041: 'Verifikasi Liveness gagal',
          backendError_1051: 'Jangan ada penghalang di wajah',
          backendError_1052: 'Mendekat',
          backendError_1053: 'Pastikan pencahayaan cukup agar foto terlihat jelas',
          backendError_1054: 'Pastikan hanya satu wajah di layar',
          backendError_1055: 'Tempatkan wajah Anda dalam bingkai',
          backendError_1058: 'Pastikan pencahayaan cukup agar foto terlihat jelas',
          backendError_1059: 'Swafoto buram, pastikan perangkat stabil',
          backendError_1060: 'Hadapkan wajah ke layar',
          backendError_1062: 'Buka mata Anda',
          backendError_1063: 'Pastikan pencahayaan cukup agar foto terlihat jelas',
          backendError_1064: 'Swafoto terlalu gelap, pastikan pencahayaannya cukup agar foto terlihat jelas',
          backendError_1074: 'Swafoto terlalu gelap, pastikan pencahayaannya cukup agar foto terlihat jelas',
          backendError_1065: 'Swafoto terlalu terang, atur pencahayaan agar foto terlihat jelas',
          backendError_1075: 'Swafoto terlalu terang, atur pencahayaan agar foto terlihat jelas',
          backendError_1066: 'Swafoto buram, pastikan perangkat stabil',
          backendError_1076: 'Swafoto buram, pastikan perangkat stabil',
          sessionExpired: 'Sesi telah habis. Mohon ulangi proses swafoto untuk melanjutkan',
          unknownError: 'Ups! Terjadi kesalahan, silakan coba lagi nanti',
          maxRetryExhausted: 'Anda telah mencapai batas maksimum percobaan. Silakan coba lagi nanti',
        },
      },
    },
  },
});
```
````

{% endcode %}
