# Capacitor Native Biometric
Add Face ID, Touch ID and fingerprint login to your Capacitor app, and keep credentials safe in the iOS Keychain and Android Keystore.
Capgo: push fixes to your Capacitor users in minutes, build signed iOS and Android apps without a Mac, and roll back in one click.
14-day unlimited free trial. No credit card required
IsAvailableOptions |
**Returns:** Promise<AvailableResult>
**Since:** 1.0.0
--------------------
### addListener('biometryChange', ...)
```typescript
addListener(eventName: 'biometryChange', listener: BiometryChangeListener) => Promise'biometryChange' | - Must be 'biometryChange' |
| **`listener`** | BiometryChangeListener | - Callback function that receives the updated AvailableResult |
**Returns:** Promise<PluginListenerHandle>
**Since:** 7.6.0
--------------------
### verifyIdentity(...)
```typescript
verifyIdentity(options?: BiometricOptions | undefined) => PromiseBiometricOptions |
**Since:** 1.0.0
--------------------
### getCredentials(...)
```typescript
getCredentials(options: GetCredentialOptions) => PromiseGetCredentialOptions |
**Returns:** Promise<Credentials>
**Since:** 1.0.0
--------------------
### setCredentials(...)
```typescript
setCredentials(options: SetCredentialOptions) => PromiseSetCredentialOptions |
**Since:** 1.0.0
--------------------
### deleteCredentials(...)
```typescript
deleteCredentials(options: DeleteCredentialOptions) => PromiseDeleteCredentialOptions |
**Since:** 1.0.0
--------------------
### getSecureCredentials(...)
```typescript
getSecureCredentials(options: GetSecureCredentialsOptions) => PromiseGetSecureCredentialsOptions |
**Returns:** Promise<Credentials>
**Since:** 8.4.0
--------------------
### isCredentialsSaved(...)
```typescript
isCredentialsSaved(options: IsCredentialsSavedOptions) => PromiseIsCredentialsSavedOptions |
**Returns:** Promise<IsCredentialsSavedResult>
**Since:** 7.3.0
--------------------
### setData(...)
```typescript
setData(options: SetDataOptions) => PromiseSetDataOptions |
**Since:** 8.6.0
--------------------
### getData(...)
```typescript
getData(options: GetDataOptions) => PromiseGetDataOptions |
**Returns:** Promise<StoredData>
**Since:** 8.6.0
--------------------
### getSecureData(...)
```typescript
getSecureData(options: GetSecureDataOptions) => PromiseGetSecureDataOptions |
**Returns:** Promise<StoredData>
**Since:** 8.6.0
--------------------
### deleteData(...)
```typescript
deleteData(options: DeleteDataOptions) => PromiseDeleteDataOptions |
**Since:** 8.6.0
--------------------
### isDataSaved(...)
```typescript
isDataSaved(options: IsDataSavedOptions) => PromiseIsDataSavedOptions |
**Returns:** Promise<IsDataSavedResult>
**Since:** 8.6.0
--------------------
### getPluginVersion()
```typescript
getPluginVersion() => Promise<{ version: string; }>
```
Get the native Capacitor plugin version.
**Returns:** Promise<{ version: string; }>
**Since:** 1.0.0
--------------------
### Interfaces
#### AvailableResult
Result from isAvailable() method indicating biometric authentication availability.
| Prop | Type | Description |
| ------------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`isAvailable`** | boolean | Whether authentication is available. On Android, weak-only biometrics (such as some face unlock implementations) are available for `verifyIdentity()` when no `allowedBiometryTypes` filter excludes them. If `useFallback` is true, PIN/pattern/password can also make this value true. |
| **`authenticationStrength`** | AuthenticationStrength | The strength of available authentication method (STRONG, WEAK, or NONE) |
| **`biometryType`** | BiometryType | The primary biometry type available on the device. On Android devices with multiple biometry types, this returns MULTIPLE. Use this for display purposes only - always use isAvailable for logic decisions. |
| **`deviceIsSecure`** | boolean | Whether the device has a secure lock screen (PIN, pattern, or password). This is independent of biometric enrollment. |
| **`strongBiometryIsAvailable`** | boolean | Whether strong biometry (Face ID, Touch ID, or fingerprint on devices that consider it strong) is specifically available, separate from weak biometry or device credentials. |
| **`errorCode`** | BiometricAuthError | Error code from BiometricAuthError enum. Only present when isAvailable is false. Indicates why biometric authentication is not available. |
#### IsAvailableOptions
| Prop | Type | Description | Default | Since |
| -------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- |
| **`useFallback`** | boolean | Whether passcode or device credentials should count toward biometric availability when no biometric is enrolled or available. - On iOS, this affects both `isAvailable()` and `verifyIdentity()`. - On Android, this is honored by `isAvailable()` only — the native check computes `fallbackAvailable = useFallback && deviceIsSecure` and reports availability accordingly. The `verifyIdentity()` flow ignores this option on Android due to BiometricPrompt API constraints (DEVICE_CREDENTIAL authenticator and negative button are mutually exclusive); use `BiometricOptions.useFallback` (iOS-only) to control the auth-dialog fallback there. | | |
| **`preferMultipleBiometryType`** | boolean | Android only. Report `BiometryType.MULTIPLE` whenever a fingerprint is enrolled and the device also advertises a face or iris sensor, even when that second modality cannot be confirmed as enrolled. You normally do not need this. On Android 12 and newer a face enrolled next to a fingerprint is usually detected and reported as `BiometryType.MULTIPLE` on its own. Detection is best-effort, and is not possible on Android 11 and older, for the rare Class 3 (Strong) face sensor, or on a vendor build whose biometric labels name only the preferred modality. Undetected devices report `BiometryType.FINGERPRINT`, because most devices advertise a face sensor the user never enrolled. Set this to `true` if your UI would rather over-report `MULTIPLE` there. `verifyIdentity()` is unaffected and still offers every enrolled biometric the device supports; this only changes the reported type. The most recent value is reused for `biometryChange` events. | false | 8.6.5 |
#### PluginListenerHandle
| Prop | Type |
| ------------ | ----------------------------------------- |
| **`remove`** | () => Promise<void> |
#### BiometricOptions
| Prop | Type | Description | Default |
| -------------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
| **`reason`** | string | | |
| **`title`** | string | | |
| **`subtitle`** | string | | |
| **`description`** | string | | |
| **`negativeButtonText`** | string | | |
| **`useFallback`** | boolean | Only for iOS. Specifies if should fallback to passcode authentication if biometric authentication fails. On Android, this parameter is ignored due to BiometricPrompt API constraints: DEVICE_CREDENTIAL authenticator and negative button (cancel) are mutually exclusive. | |
| **`fallbackTitle`** | string | Only for iOS. Set the text for the fallback button in the authentication dialog. If this property is not specified, the default text is set by the system. | |
| **`maxAttempts`** | number | Only for Android. Set a maximum number of attempts for biometric authentication. The maximum allowed by android is 5. | 1 |
| **`allowedBiometryTypes`** | BiometryType[] | Only for Android. Specify which biometry types are allowed for authentication. If not specified, all enrolled biometric classes (strong and weak) are allowed. On Android, face unlock is often classified as weak biometrics — include `BiometryType.FACE_AUTHENTICATION` or omit this option to allow it. Use `BiometryType.DEVICE_CREDENTIAL` for PIN/pattern/password (disables the cancel button). | |
#### Credentials
| Prop | Type |
| -------------- | ------------------- |
| **`username`** | string |
| **`password`** | string |
#### GetCredentialOptions
| Prop | Type |
| ------------ | ------------------- |
| **`server`** | string |
#### SetCredentialOptions
| Prop | Type | Description | Default | Since |
| -------------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ------ |
| **`username`** | string | | | |
| **`password`** | string | | | |
| **`server`** | string | | | |
| **`accessControl`** | AccessControl | Access control level for the stored credentials. When set to BIOMETRY_CURRENT_SET or BIOMETRY_ANY, the credentials are hardware-protected and require biometric authentication to access. On iOS, this adds SecAccessControl to the Keychain item. On Android, this creates a biometric-protected Keystore key and requires BiometricPrompt authentication for both storing and retrieving credentials. | AccessControl.NONE | 8.4.0 |
| **`authValidityDuration`** | number | Only for Android. Ignored on iOS and web. Only meaningful together with `accessControl` set to BIOMETRY_CURRENT_SET or BIOMETRY_ANY. Number of seconds a successful biometric authentication remains valid for Keystore key use. When `0` or omitted (the default), the Keystore key requires a fresh authentication for every operation — each `getSecureCredentials()` call shows a `BiometricPrompt` cryptographically bound to that specific read via a `CryptoObject`. This is the strongest mode: it guarantees no code path can use the key without a live biometric check. When set to a value greater than `0`, one successful biometric authentication authorizes Keystore key use for that many seconds. Subsequent `getSecureCredentials()` calls within the window succeed without showing a prompt. This trades security for convenience: any in-app code that can reach the decryption call — not just the code path that triggered the prompt — can silently read the credentials for the remainder of the window. | 0 | 8.5.0 |
| **`title`** | string | Title for the biometric prompt shown while protecting credentials. Only for Android. | "Protect Credentials" | 8.4.14 |
| **`negativeButtonText`** | string | Text for the negative/cancel button in the biometric prompt. Only for Android. | "Cancel" | 8.4.14 |
| **`maxAttempts`** | number | Set a maximum number of attempts for biometric authentication. The maximum allowed by Android is 5. Only for Android. | 1 | |
#### DeleteCredentialOptions
| Prop | Type |
| ------------ | ------------------- |
| **`server`** | string |
#### GetSecureCredentialsOptions
| Prop | Type | Description | Default |
| ------------------------ | ------------------- | --------------------------------------------------------------------------------------------------------------------- | -------------- |
| **`server`** | string | | |
| **`reason`** | string | Explanation text shown as the subtitle of the Touch ID prompt. Face ID does not display it. Only for iOS. | |
| **`title`** | string | Title for the biometric prompt. Only for Android. | |
| **`subtitle`** | string | Subtitle for the biometric prompt. Only for Android. | |
| **`description`** | string | Description for the biometric prompt. Only for Android. | |
| **`negativeButtonText`** | string | Text for the negative/cancel button. Only for Android. | |
| **`maxAttempts`** | number | Set a maximum number of attempts for biometric authentication. The maximum allowed by Android is 5. Only for Android. | 1 |
#### IsCredentialsSavedResult
| Prop | Type |
| ------------- | -------------------- |
| **`isSaved`** | boolean |
#### IsCredentialsSavedOptions
| Prop | Type |
| ------------ | ------------------- |
| **`server`** | string |
#### SetDataOptions
| Prop | Type | Description | Default | Since |
| -------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | ----- |
| **`key`** | string | Unique identifier for the stored value. Use a stable app-specific namespace (e.g. `pin`, `session.token`). | | |
| **`value`** | string | Arbitrary string payload. Serialize objects with `JSON.stringify()` before storing. Platform limits apply: Android Keystore-backed encryption works best with payloads under ~8 KB; iOS Keychain practical limits are higher but very large values are discouraged. | | |
| **`accessControl`** | AccessControl | Access control level for the stored value. When set to BIOMETRY_CURRENT_SET or BIOMETRY_ANY, the value is hardware-protected and requires biometric authentication to access via `getSecureData()`. | AccessControl.NONE | 8.6.0 |
| **`authValidityDuration`** | number | Only for Android. Ignored on iOS and web. Only meaningful together with `accessControl` set to BIOMETRY_CURRENT_SET or BIOMETRY_ANY. | 0 | 8.6.0 |
| **`title`** | string | Title for the biometric prompt shown while protecting data. Only for Android. | "Protect Data" | 8.6.0 |
| **`negativeButtonText`** | string | Text for the negative/cancel button in the biometric prompt. Only for Android. | "Cancel" | 8.6.0 |
| **`maxAttempts`** | number | Set a maximum number of attempts for biometric authentication. The maximum allowed by Android is 5. Only for Android. | 1 | |
#### StoredData
| Prop | Type |
| ----------- | ------------------- |
| **`value`** | string |
#### GetDataOptions
| Prop | Type |
| --------- | ------------------- |
| **`key`** | string |
#### GetSecureDataOptions
| Prop | Type | Description | Default |
| ------------------------ | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
| **`key`** | string | | |
| **`reason`** | string | Explanation text shown as the subtitle of the Touch ID prompt. Face ID does not display it. Only for iOS. | |
| **`title`** | string | Title for the biometric prompt. Only for Android. | |
| **`subtitle`** | string | Subtitle for the biometric prompt. Only for Android. | |
| **`description`** | string | Description for the biometric prompt. Only for Android. | |
| **`negativeButtonText`** | string | Text for the negative/cancel button. Only for Android. | |
| **`fallbackTitle`** | string | Set the text for the fallback button in the authentication dialog. If this property is not specified, the default text is set by the system. Set it to an empty string to hide the button. Only for iOS. | |
| **`maxAttempts`** | number | Set a maximum number of attempts for biometric authentication. The maximum allowed by Android is 5. Only for Android. | 1 |
#### DeleteDataOptions
| Prop | Type |
| --------- | ------------------- |
| **`key`** | string |
#### IsDataSavedResult
| Prop | Type |
| ------------- | -------------------- |
| **`isSaved`** | boolean |
#### IsDataSavedOptions
| Prop | Type |
| --------- | ------------------- |
| **`key`** | string |
### Type Aliases
#### BiometryChangeListener
Callback type for biometry change listener
(result: AvailableResult): void
### Enums
#### AuthenticationStrength
| Members | Value | Description |
| ------------ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **`NONE`** | 0 | No authentication available, even if PIN is available but useFallback = false |
| **`STRONG`** | 1 | Strong authentication: Face ID on iOS, fingerprints on devices that consider fingerprints strong (Android). Note: PIN/pattern/password is NEVER considered STRONG, even when useFallback = true. |
| **`WEAK`** | 2 | Weak authentication: Face authentication on Android devices that consider face weak, or PIN/pattern/password if useFallback = true (PIN is always WEAK, never STRONG). |
#### BiometryType
| Members | Value |
| ------------------------- | -------------- |
| **`NONE`** | 0 |
| **`TOUCH_ID`** | 1 |
| **`FACE_ID`** | 2 |
| **`FINGERPRINT`** | 3 |
| **`FACE_AUTHENTICATION`** | 4 |
| **`IRIS_AUTHENTICATION`** | 5 |
| **`MULTIPLE`** | 6 |
| **`DEVICE_CREDENTIAL`** | 7 |
#### BiometricAuthError
| Members | Value | Description | Since |
| ------------------------------------ | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
| **`UNKNOWN_ERROR`** | 0 | Unknown error occurred | |
| **`BIOMETRICS_UNAVAILABLE`** | 1 | Biometrics are unavailable (no hardware or hardware error) Platform: Android, iOS | |
| **`USER_LOCKOUT`** | 2 | User has been locked out due to too many failed attempts Platform: Android, iOS | |
| **`BIOMETRICS_NOT_ENROLLED`** | 3 | No biometrics are enrolled on the device Platform: Android, iOS | |
| **`USER_TEMPORARY_LOCKOUT`** | 4 | User is temporarily locked out (Android: 30 second lockout) Platform: Android | |
| **`AUTHENTICATION_FAILED`** | 10 | Authentication failed (user did not authenticate successfully) Platform: Android, iOS | |
| **`APP_CANCEL`** | 11 | App canceled the authentication (iOS only) Platform: iOS | |
| **`INVALID_CONTEXT`** | 12 | Invalid context (iOS only) Platform: iOS | |
| **`NOT_INTERACTIVE`** | 13 | Authentication was not interactive (iOS only) Platform: iOS | |
| **`PASSCODE_NOT_SET`** | 14 | Passcode/PIN is not set on the device Platform: Android, iOS | |
| **`SYSTEM_CANCEL`** | 15 | System canceled the authentication (e.g., due to screen lock) Platform: Android, iOS | |
| **`USER_CANCEL`** | 16 | User canceled the authentication Platform: Android, iOS | |
| **`USER_FALLBACK`** | 17 | User chose to use fallback authentication method Platform: Android, iOS | |
| **`NO_PROTECTED_CREDENTIALS_FOUND`** | 21 | No biometric-protected credentials or data exist for the requested server or key. Platform: Android, iOS (`getSecureCredentials()`, `getSecureData()`). Thrown when `getSecureCredentials()` or `getSecureData()` is called but nothing was stored with `accessControl` BIOMETRY_CURRENT_SET or BIOMETRY_ANY — for example after deletion, a fresh install, or items removed from the secure enclave after biometric enrollment changes. Rejection message differs by platform and method: - `getSecureCredentials()`: Android `No protected credentials found`, iOS `No protected credentials found for server` - `getSecureData()`: Android `No protected data found`, iOS `No protected data found for key` | 8.4.0 |
#### AccessControl
| Members | Value | Description |
| -------------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`NONE`** | 0 | No biometric protection. Credentials are accessible without authentication. This is the default behavior for backward compatibility. |
| **`BIOMETRY_CURRENT_SET`** | 1 | Biometric authentication required for credential access. Credentials are invalidated if biometrics change (e.g., new fingerprint enrolled). More secure but credentials are lost if user modifies their biometric enrollment. |
| **`BIOMETRY_ANY`** | 2 | Biometric authentication required for credential access. Credentials survive new biometric enrollment (e.g., adding a new fingerprint). More lenient — recommended for most apps. |