npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

cordova-plugin-mlkit-suite

v0.4.1

Published

Google ML Kit vision suite for Apache Cordova on Android and iOS with barcode scanning, face capture, OCR, document scanning, image labeling, and segmentation.

Readme

npm downloads npm version GitHub package.json version Android and iOS demo GitHub license

cordova-plugin-mlkit-suite

cordova-plugin-mlkit-suite is a Google ML Kit computer-vision plugin for Apache Cordova on Android and iOS. Its JavaScript API provides guided face capture, live and still-image barcode scanning, OCR with Text Recognition v2, document scanning, image labeling, subject segmentation, and background removal through native ML Kit SDKs.

[!WARNING] This plugin is in active development. Its API, defaults, quality thresholds, and native behavior may change before a stable release. Validate every required workflow on representative physical devices before using it in production.

Table of contents

Overview

  • Guided face capture on Android and iOS, with a front-camera overlay, configurable quality checks, automatic capture, and a local JPEG result.
  • Barcode scanning from the live camera or an existing image on Android and iOS, supporting all available barcode formats, configurable format filters, scan-region enforcement, consecutive-frame confirmation, animated success feedback, and an optional confirmation beep.
  • Text recognition v2 for extracting Latin-script text from local images on Android and iOS.
  • Document scanning on Android, with page limits, scanner modes, gallery import, JPEG pages, and optional PDF output.
  • Image labeling for classifying local images with ML Kit's general-purpose default model on Android and iOS.
  • Subject segmentation for separating foreground people, pets, and objects from the background on Android.

| Module | Android | iOS | | --- | --- | --- | | Barcode scanning | ✅ Live camera and still images | ✅ Live camera and still images | | Document scanner | ✅ Available | ❌ Not available | | Face detection | ✅ Guided face capture | ✅ Guided face capture | | Image labeling | ✅ Default model | ✅ Default model | | ~~Selfie segmentation~~ | ❌ Removed | ❌ Removed | | Subject segmentation | ✅ Transparent PNG | ❌ Not available | | Text recognition v2 | ✅ Latin script | ✅ Latin script |

Android model delivery is configurable per module. Native plugin UI and errors support automatic, English, and Spanish localization.

Compatibility

The plugin requires Cordova 11 or newer.

| Platform | Supported Cordova platform | Minimum OS | | --- | --- | --- | | Android | cordova-android 12.x–15.x | Android 7.0 / API 24 | | iOS | cordova-ios 8.x | iOS 15.5 |

Android compatibility notes

Document Scanner on Android additionally requires Google Play services and at least 1.7 GB of total RAM.

The Android implementation selects a tested CameraX version for each supported cordova-android major:

| cordova-android | CameraX | Reference toolchain | | --- | --- | --- | | 12.x | 1.2.3 | compileSdk 33 / AGP 7.4.2 / JDK 11 | | 13.x | 1.4.2 | compileSdk 34 / AGP 8.3.0 / JDK 17 | | 14.x | 1.5.2 | compileSdk 35 / AGP 8.7.3 / JDK 17 | | 15.x | 1.6.0 | compileSdk 36 / AGP 8.10.1 / JDK 17 |

Unknown cordova-android majors fail at build time instead of silently selecting untested dependencies. On an unsupported Android device, MlKit.scanDocument() rejects with UNSUPPORTED_DEVICE without affecting the other modules.

Model packaging and download behavior are documented separately under Android model delivery.

Quick start

Install the plugin from the Cordova application root:

cordova plugin add cordova-plugin-mlkit-suite

All methods return Promises. For example, open the native barcode scanner and inspect the result:

const result = await MlKit.barcode.scan({
    formats: ["QR_CODE", "PDF_417"]
});

if (result.status === "success") {
    console.log(result.text, result.format);
}

On Android, Face Detection, Barcode Scanning, Image Labeling, OCR, and Subject Segmentation default to the smaller Google Play services install-time strategy. See Android model delivery to bundle configurable models or defer supported downloads.

iOS setup

On iOS, configure the deployment target and a camera-purpose string in the host application's config.xml:

<platform name="ios">
    <preference name="deployment-target" value="15.5" />
    <edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
        <string>Use the camera to capture a photo.</string>
    </edit-config>
</platform>

The plugin requests camera access. Generated images are written to the application's private cache, so no storage or Photo Library permission is required.

Android model delivery

Face Detection, Barcode Scanning, Image Labeling, and Latin Text Recognition can independently use the official ML Kit bundled or unbundled installation paths. Subject Segmentation is always unbundled through Google Play services but can use install-time or first-use. Document Scanner is always delivered dynamically by Google Play services.

| Mode | Implementation | Download timing | Best fit | | --- | --- | --- | --- | | install-time (default) | Unbundled | Requested after installation from Google Play; completion is best effort. | Small app with proactive delivery for normal Play Store installs. | | first-use | Unbundled | Downloaded when the app first calls that module, unless prepared earlier. | Small app where unused modules should never download. | | bundled | Bundled | Included in the APK/AAB; no model download. | Immediate offline availability is more important than package size. |

Apply one mode as the global fallback during installation:

cordova plugin add cordova-plugin-mlkit-suite \
  --variable ANDROID_MLKIT_MODEL_DELIVERY=bundled

Module-specific variables override the global value; inherit uses the global setting:

| Module | Installation variable | Valid values | | --- | --- | --- | | Global fallback | ANDROID_MLKIT_MODEL_DELIVERY | bundled, install-time, first-use, play-services | | Face Detection | ANDROID_MLKIT_FACE_MODE | inherit, bundled, install-time, first-use, play-services | | Barcode Scanning | ANDROID_MLKIT_BARCODE_MODE | inherit, bundled, install-time, first-use, play-services | | Image Labeling | ANDROID_MLKIT_IMAGE_LABELING_MODE | inherit, bundled, install-time, first-use, play-services | | Latin Text Recognition | ANDROID_MLKIT_OCR_MODE | inherit, bundled, install-time, first-use, play-services | | ~~Selfie Segmentation~~ | ~~None~~ | ~~bundled only~~ — removed after measuring a 77.84 MB increase in the universal Android debug APK | | Subject Segmentation | ANDROID_MLKIT_SUBJECT_SEGMENTATION_MODE | inherit, install-time, first-use, play-services | | Document Scanner | None | Google Play services only |

The global fallback defaults to install-time; module variables default to inherit. play-services aliases install-time. Subject Segmentation resolves inherited bundled to install-time.

These are build-time settings, so remove and re-add the plugin to change them. Do not edit generated Gradle, manifest, plugins/, or platforms/android/ files.

When an unbundled module is missing, the plugin shows a native spinner, waits for the download, and then continues the requested operation. Its default text follows the resolved plugin locale; set moduleLoadingMessage to custom text, or to an empty string for a spinner without a label:

await MlKit.recognizeText(imagePath, {
    moduleLoadingMessage: "Downloading text recognition…"
});

Use prepareModels() to download selected modules proactively:

await MlKit.prepareModels(["barcode", "image-labeling", "ocr"], {
    moduleLoadingMessage: "Preparing ML Kit models…"
});

Preparation resolves with { "status": "ready", "alreadyAvailable": true }; alreadyAvailable is false when the call completed a download. getCapabilities() reports configured modes and readiness without starting one.

Localization

Plugin-owned camera instructions, accessibility labels, loading text, and user-facing native errors are available in English and Spanish. Every options object accepts an optional locale:

await MlKit.face.capture({ locale: "es-AR" });
await MlKit.barcode.scan({ locale: "auto" });

auto is the default and uses the application/device language resolved natively at runtime. en, es, and BCP-47 tags such as en-US or es-AR are accepted; unsupported languages safely fall back to English. Explicit barcode instructionText and moduleLoadingMessage values always take precedence, including an empty string.

Android translations live in src/android/res/values*/mlkit_suite_strings.xml; iOS translations live in src/ios/MlKitSuiteResources.bundle/*.lproj/Localizable.strings. Add the same keys in a new platform locale directory to extend the plugin. Stable result values and error codes are never translated.

The Google Document Scanner UI is owned by Google Play services and follows the locale selected by that component. Its public API has no locale override, so locale controls the plugin's loading and error messages around the flow but cannot force the language of Google's scanner screens.

API

| Method | Android | iOS | Purpose | | --- | --- | --- | --- | | MlKit.getCapabilities() | ✅ | ✅ | Describes modules available on the current platform and device. | | MlKit.prepareModels(modules?, options?) | ✅ | ✅ | Ensures all or selected Face, Barcode, Image Labeling, Latin OCR, and Subject Segmentation modules are ready; bundled modules resolve immediately. | | MlKit.prepareDocumentScanner(options?) | ✅ | ❌ | Checks and installs the on-demand Google Play services scanner component. | | MlKit.scanDocument(options?) | ✅ | ❌ | Opens Google's native document capture, crop, filter, and cleanup UI. | | MlKit.labelImage(imagePath, options?) | ✅ | ✅ | Returns labels from ML Kit's default image-labeling model. | | MlKit.segmentSubjects(imagePath, options?) | ✅ | ❌ | Creates a transparent PNG containing foreground subjects from a local image. | | MlKit.recognizeText(imagePath, options?) | ✅ | ✅ | Returns plain Latin-script text from a local image. | | MlKit.scanBarcodes(imagePath, options?) | ✅ | ✅ | Returns every matching barcode detected in a local image. | | MlKit.barcode.scan(options?) | ✅ | ✅ | Opens a high-resolution rear-camera barcode scanner. | | MlKit.face.capture(options?) | ✅ | ✅ | Opens guided front-camera face capture with automatic capture. |

Document Scanner requires at least 1.7 GB of total device RAM.

All methods return Promises. The plugin processes content locally and does not interpret, validate, upload, or transform decoded payloads for a particular country or document type.

Capabilities

Use getCapabilities() to discover platform and device support:

const capabilities = await MlKit.getCapabilities();

if (capabilities.document.scan && capabilities.document.deviceSupported) {
    // The native document flow can be requested on this device.
}

The result contains platform, localization details, and face, barcode, document, imageLabeling, subjectSegmentation, and text capability objects. Each module reports its configured mode, ready state, and modelStatus without starting a download. Android can report mixed when configurable module modes differ. Subject Segmentation is an unbundled Android module. On iOS, Subject Segmentation and Document Scanner report unsupported.

Barcode scanning

Both barcode APIs use ML Kit Barcode Scanning. Use still-image detection for existing local files or the native camera flow for interactive scanning.

Barcode detection in an image

MlKit.scanBarcodes(imagePath, options?) uses ML Kit Barcode Scanning to analyze one existing local image and resolves to an array. It does not require the camera UI or two-frame confirmation.

const barcodes = await MlKit.scanBarcodes(imagePath, {
    formats: ["PDF_417", "QR_CODE"],
    moduleLoadingMessage: "Loading barcode detector…"
});

for (const barcode of barcodes) {
    console.log(barcode.text, barcode.format);
}

Omit formats to enable every supported format. moduleLoadingMessage follows the common native-indicator rules above. Each detected value includes text, format, numeric valueType, boundingBox, and cornerPoints. An image containing no matching barcode resolves to [].

{ "text": "https://example.com", "format": "QR_CODE", "valueType": 8 }

boundingBox can be null; cornerPoints can be empty. Coordinates use the source image's pixel coordinate system. valueType is the platform ML Kit enum value, and format is one of the names below or UNKNOWN if the native SDK reports an unrecognized value.

Camera barcode scanning

MlKit.barcode.scan(options?) combines ML Kit Barcode Scanning with the plugin's own full-screen rear-camera UI on Android and iOS:

const result = await MlKit.barcode.scan({
    formats: ["PDF_417", "QR_CODE"],
    timeoutMs: 45000
});

if (result.status === "success") {
    console.log(result.text, result.format);
}
{ "status": "success", "text": "https://example.com", "format": "QR_CODE" }

Android requests 1920×1080 analysis frames from CameraX; iOS requests the equivalent AVFoundation hd1920x1080 preset. Each platform falls back to the closest suitable high-resolution stream supported by the camera. The four-color corner guide is the active scan region: codes outside it or crossing its edges are ignored. A result is returned only after two consecutive analyzed frames contain exactly the same non-empty text and format while fully inside the guide. A missing, outside, or different value resets confirmation. On success, the scanner freezes the confirmed camera frame and animates the guide onto the detected code before returning the result.

Barcode formats

Both barcode methods support AZTEC, CODABAR, CODE_39, CODE_93, CODE_128, DATA_MATRIX, EAN_8, EAN_13, ITF, PDF_417, QR_CODE, UPC_A, and UPC_E. PDF417 aliases PDF_417; comma-separated strings are accepted in addition to arrays.

Camera barcode options

| Option | Type | Default | Description | | --- | --- | --- | --- | | formats | string[] \| string \| null | all formats | Formats to detect. Restricting formats generally improves speed. | | showCloseButton | boolean | true | Shows the native close button. Android Back still cancels when hidden. | | showTorchButton | boolean | true | Shows a torch toggle when the rear camera has flash hardware. | | beepEnabled | boolean | true | Plays a short synthesized confirmation beep after a successful scan. Device silent mode is respected. | | instructionText | string \| null | "Place a barcode inside the frame" | Text shown above the guide. An empty string hides it. | | guideColor | string \| null | null | Optional #RRGGBB color for all four guide corners. When omitted, the default blue, yellow, green, and red corners are used. A detected in-guide barcode always changes them to green. | | moduleLoadingMessage | string \| null | localized | Android text shown only while downloading Barcode Scanning. Empty string shows only the spinner. | | locale | string | "auto" | Plugin UI/error locale (en, es, or BCP-47). | | timeoutMs | integer 0–600000 | 0 | Session timeout in milliseconds. 0 disables it. |

Document scanning

MlKit.scanDocument(options?) opens the Google ML Kit Document Scanner on Android. The native flow handles capture, automatic edge detection, crop adjustment, rotation, cleanup, filters, and optional gallery import.

The scanner UI, logic, and models are an on-demand Google Play services component. scanDocument() now prepares that component automatically and shows the native loading indicator only when a download is required. Call prepareDocumentScanner() earlier only when proactive preparation better suits the application flow:

await MlKit.prepareDocumentScanner({
    moduleLoadingMessage: "Preparing document scanner…"
});
const result = await MlKit.scanDocument({
    pageLimit: 4,
    galleryImportAllowed: true,
    resultFormats: ["JPEG", "PDF"],
    scannerMode: "FULL",
    moduleLoadingMessage: "Preparing document scanner…"
});

if (result.status === "success") {
    document.querySelector("img").src = result.pages[0].imageUri;
    console.log(result.pdf && result.pdf.path);
}

The method performs device checks before requesting the Google scanner. Android versions below API 24 and devices with less than 1.7 GB of total RAM reject with UNSUPPORTED_DEVICE instead of opening native scanner code.

Document options

| Option | Type | Default | Description | | --- | --- | --- | --- | | pageLimit | integer 1–100 | 1 | Maximum number of pages in one scan. | | galleryImportAllowed | boolean | true | Allows importing document images from the gallery. | | resultFormats | string[] \| string \| null | ["JPEG", "PDF"] | Requests JPEG pages, a PDF, or both. A comma-separated string is accepted. null uses the default; JPG aliases JPEG. | | scannerMode | "BASE" \| "BASE_WITH_FILTER" \| "FULL" \| null | "FULL" | Selects the native editing feature set. null uses the default. BASE still includes crop, rotation, page removal, and page reordering. | | moduleLoadingMessage | string \| null | localized | Android text shown only while downloading the scanner component. Empty string shows only the spinner. | | locale | string | "auto" | Plugin loading/error locale. Google's scanner UI resolves its own locale. |

Unknown options, invalid types, empty result formats, and out-of-range values reject with INVALID_ARGUMENT.

Document result

Successful results contain status, a pages array, and an optional pdf object. Each page reports imagePath, WebView-safe imageUri, MIME type, byte size, width, and height. The PDF reports its native path, WebView-safe uri, MIME type, byte size, and page count.

pages is empty when JPEG was not requested and pdf is null when PDF was not requested. Use imageUri inside the Cordova WebView and native paths with APIs such as recognizeText(), scanBarcodes(), labelImage(), and segmentSubjects().

Face capture

MlKit.face.capture(options?) combines ML Kit Face Detection with a full-screen native front-camera guide and resolves after a valid JPEG is captured.

Example:

const result = await MlKit.face.capture({
    outputWidth: 600,
    outputHeight: 720,
    gestures: ["OPEN_MOUTH", "NOD"],
    captureAfterGesture: 1,
    revealCapture: false,
    requireDeviceVertical: true,
    debugMode: false,
    timeoutMs: 90000
});

All checks except eyesOpen and neutralExpression are enabled by default. Capture starts automatically only after the enabled checks remain acceptable for a short stability window.

Face options

| Option | Type | Default | Description | | --- | --- | --- | --- | | outputWidth | integer 320–2048 | 600 | Exact JPEG width in pixels. | | outputHeight | integer 320–2048 | 720 | Exact JPEG height in pixels and crop aspect ratio. | | jpegQuality | integer 50–100 | 95 | JPEG encoding quality. | | showCloseButton | boolean | true | Shows the native close button. | | debugMode | boolean | false | Shows only active live requirements. During gestures, a compact responsive panel exposes the tracker phase, current relative movement, exact target, and a visual acceptance meter. Without gestures it keeps the compact active-check view, including device tilt when enabled. Validation is not weakened. | | beepEnabled | boolean | true | Plays a short synthesized confirmation beep after a successful capture. Device silent mode is respected. | | revealCapture | boolean | true | Shows the capturing state and message. Set to false to take the photo without revealing the exact moment. | | requireDeviceVertical | boolean | true | Requires the phone to remain within ±10° of vertical for 700 ms before accepting the face or arming a gesture. The overlay asks the user to position it at eye level. Set to false to disable this sensor gate. | | moduleLoadingMessage | string \| null | localized | Android text shown only while downloading Face Detection. Empty string shows only the spinner. | | locale | string | "auto" | Plugin UI/error locale (en, es, or BCP-47). | | gestures | string[] | [] | Ordered challenge sequence, with at most five gestures. Each gesture is armed only after the face remains frontal and neutral for a stability pause, and then ends in a neutral pose. | | captureAfterGesture | integer | gesture count | Captures after this many completed gestures. Use 1 with two gestures to keep the candidate private until the second gesture succeeds. | | gestureTimeoutMs | integer 1000–15000 | 4000 | Maximum time to complete each armed gesture. | | neutralTimeoutMs | integer 500–5000 | 2000 | Maximum time to return to neutral after a gesture. | | retryMessageMs | integer 250–3000 | 1000 | Time the restart message remains visible before the whole sequence resets. | | checks | object \| null | see below | Enables or disables individual capture gates. | | timeoutMs | integer 0–600000 | 90000 | Face-capture timeout in milliseconds (90 seconds by default). 0 disables it. |

Optional face checks

| Check | Default | Purpose | | --- | --- | --- | | singleFace | true | Requires exactly one detected face. | | faceSize | true | Rejects faces that are too small or too close. | | centering | true | Projects the detected face into the visible camera preview and requires its center to remain inside the oval's central safe region. The check is suspended while an armed gesture is being performed. | | pose | true | Limits head yaw, pitch, and roll. | | eyesOpen | false | Requires both eye-open probabilities to pass the internal threshold. Disabled by default because ML Kit may not classify every user's eyes reliably. | | neutralExpression | false | Rejects a high smiling probability. Disabled by default because expression classification can vary between users. | | stability | true | Requires a stable face position before capture. | | sharpness | true | Rejects low-detail frames and final images. | | brightness | true | Rejects images that are too dark or too bright. |

Face result

Successful results include the JPEG's imagePath, WebView-safe imageUri, dimensions, MIME type, byte size, and capture time. The quality object contains brightness and sharpness; face contains yaw, pitch, roll, eye-open probabilities, and smiling probability; appliedChecks records the checks used for capture.

Cache files are temporary. Eye-open and smiling probabilities can be null when ML Kit does not provide them.

Supported gesture names are OPEN_MOUTH, BLINK, SMILE, LOOK_UP, LOOK_DOWN, NOD, and SHAKE. NOD requires looking up and then down before returning to neutral, and the overlay identifies the current up/down subphase. While any gesture is active, centering and pose guidance cannot replace the gesture instruction. Both stages of SHAKE use the same 15-degree horizontal threshold. SHAKE requires right first and then left, with matching subphase guidance. The successful result includes completedGestures in the requested order. These active challenges are capture gates, not presentation-attack detection by themselves.

After every accepted gesture phase, its instruction remains visible in green for 500 ms. This applies to both subphases of NOD and SHAKE and to every single-phase gesture. Gesture evaluation and its timeout are frozen during the confirmation pause; the oval also turns green and the corresponding progress segment advances to its next success color. The next instruction appears only after the pause ends.

The first gesture cannot be satisfied by movement made while the camera is opening. The plugin first requires a frontal neutral face for 650 ms before arming it. The same pause is required before every later gesture, so movement from the previous gesture cannot spill into the next one. Gesture angles are measured relative to that stable neutral pose, avoiding false rejections caused by a small natural ML Kit pitch or yaw offset. Before arming, pitch outside the frontal range produces a directional instruction to raise or lower the head instead of the generic look-straight message.

By default, face capture also uses the device gravity sensor as an initial positioning gate. The phone must remain within ±10° of vertical for 700 ms before face framing, gesture validation, or capture can proceed. Tilting it beyond the exit tolerance invalidates an active gesture sequence. Devices that do not expose a usable gravity or motion sensor continue without this gate. This check helps establish the intended posture but is not, by itself, presentation-attack detection.

The native overlay shows progress as a segmented bar instead of a numeric gesture counter. It contains one segment for the initial accepted face, one per requested gesture, and one for the photo capture. Completed segments remain green, the current segment is yellow, and future segments remain gray; therefore one gesture produces three segments and two gestures produce four. Compound gestures retain an intermediate yellow-green segment after their first accepted subphase and turn fully green after their second. Every segment color change uses the same smooth 260 ms transition. Overlay labels wrap within the safe screen width. The segmented bar is placed directly below the oval; no secondary instruction label is rendered in that lower region. The overlay reserves separate responsive regions for guidance, progress, framing, instructions, and optional debug metrics. On shorter screens it reduces and lowers the oval before allowing labels to overlap; debug metrics use a compact secondary layout and consume no space when debug mode is off. When gestures are active in debug mode, the compact metrics are replaced by a contextual tracker panel. It shows the neutral and action phases, current relative value, exact threshold, and a visual acceptance meter. Secondary raw, baseline, remaining-distance, and hold-time lines are omitted to preserve space. The panel height follows this compact content and ends immediately below the meter. The final segment, green Ready message, confirmation beep, and successful result are emitted only after the JPEG passes final processing; Ready is never shown while that processing is still pending.

When captureAfterGesture is before the end of the sequence, the JPEG remains private to the native plugin. It is returned only after all later gestures pass in the same camera session. A timeout, prolonged missing/replaced face, invalid final frame, or capture failure deletes the candidate and restarts the complete sequence.

During an active gesture, a face-tracking interruption of up to 300 ms freezes all gesture and hold timers without advancing a subphase or permitting capture. Tracking resumes from the same point if the face returns within that margin; a longer interruption restarts the complete sequence.

Image labeling

MlKit.labelImage(imagePath, options?) uses ML Kit Image Labeling to classify one local image with the general-purpose default model. It resolves to an array of labels ordered by the native SDK; an image with no matching labels resolves to [].

const labels = await MlKit.labelImage(imagePath, {
    confidenceThreshold: 0.6,
    moduleLoadingMessage: "Loading image labeling…"
});

for (const label of labels) {
    console.log(label.text, label.confidence, label.index);
}
[
  { "text": "Food", "confidence": 0.93, "index": 12 }
]

confidenceThreshold is an optional number from 0 to 1; ML Kit's native default is used when omitted. Each result contains text, confidence, and the default model's index. Android follows the configured delivery mode; iOS bundles the model.

Subject segmentation

MlKit.segmentSubjects(imagePath, options?) uses ML Kit Subject Segmentation on Android to isolate the combined foreground from people, animals, or objects and save it as a transparent PNG.

const result = await MlKit.segmentSubjects(imagePath, {
    maxDimension: 2048,
    moduleLoadingMessage: "Loading subject segmentation…"
});

document.querySelector("img").src = result.imageUri;

The successful result contains status, WebView-safe imageUri, native imagePath, width, height, mimeType: "image/png", and bytes. maxDimension accepts an integer from 256 to 4096 and defaults to 2048; larger inputs are proportionally reduced before processing. The API is Android-only and unbundled: the plugin checks the Google Play services module, shows its localized loading spinner only when required, waits for installation, and then performs inference. Use prepareModels("subject-segmentation") to prepare it earlier without processing an image.

Text recognition v2

MlKit.recognizeText(imagePath, options?) runs ML Kit Text Recognition v2 for the Latin script against a local image and resolves to one plain string. Android uses the selected delivery mode; iOS always bundles the recognizer. An image containing no recognized text resolves to "".

Text Recognition v2 has no module-specific settings, so its pair shows the input workflow and a completed result instead.

const text = await MlKit.recognizeText(result.pages[0].imagePath, {
    moduleLoadingMessage: "Loading text recognition…"
});
console.log(text);

imagePath can be an absolute native file path, a file: URI, an Android content: URI, or an imageUri previously returned by this plugin. Remote HTTP images are not fetched.

Cancellation and errors

User cancellation of an interactive native UI resolves rather than rejects:

{ "status": "cancelled", "reason": "user" }

Other failures reject with a stable shape:

{
  "code": "UNSUPPORTED_DEVICE",
  "message": "ML Kit Document Scanner requires Android 7.0 or newer and at least 1.7 GB of total RAM.",
  "recoverable": false
}

| Code | Meaning | | --- | --- | | INVALID_ARGUMENT | An argument, option, or check is invalid. | | INVALID_IMAGE | The supplied local image cannot be opened or decoded. | | BUSY | Another interactive native session is active. | | CAMERA_PERMISSION_DENIED | Camera permission is unavailable. | | CAMERA_UNAVAILABLE | The requested camera or pipeline could not be opened. | | CAPTURE_FAILED | No acceptable final face photo was obtained. | | PROCESSING_FAILED | ML Kit or output persistence could not complete. | | SCANNER_UNAVAILABLE | The document scanner could not be downloaded, initialized, or opened. | | MODULE_DOWNLOAD_CANCELLED | Google Play services cancelled a requested model or scanner-component installation. | | MODULE_DOWNLOAD_FAILED | Google Play services could not check or install the requested modules. | | UNSUPPORTED_DEVICE | The current Android version, memory, or Google implementation does not support the document scanner. | | UNSUPPORTED_PLATFORM | The requested module is not implemented on the current platform. | | TIMEOUT | The configured interactive-session timeout elapsed. | | UNKNOWN | The JavaScript bridge received an unstructured or otherwise unknown native error. |

Privacy and limitations

Dependencies and licenses

The plugin uses Google ML Kit, AndroidX CameraX, and Apple system frameworks including AVFoundation. Plugin source is licensed under the MIT License; platform dependencies retain their own licenses and terms.

Privacy

The plugin requests camera permission and processes camera frames and selected local images. It does not include analytics, advertising, network upload code, face recognition, or persistent biometric storage. Document Scanner and Subject Segmentation are provided through Google Play services. The host application controls returned files and is responsible for privacy disclosures, consent, retention, transport security, and regulatory compliance.

The included Apple privacy manifest declares no tracking, collected data, or required-reason API use by the plugin itself. Host applications and transitive SDKs must provide their own accurate manifests.

Known limitations

  • The Google Document Scanner always allows basic page editing, including crop and rotation; its native UI cannot be configured as an immutable front/back capture flow.
  • Image labeling currently uses ML Kit's general-purpose default model; custom models are not yet supported.
  • Subject Segmentation is a beta, Android-only ML Kit API and requires its Google Play services module before first inference.
  • Text recognition currently includes only the Latin script recognizer.
  • Face detection is not face recognition, identity verification, liveness detection, or presentation-attack detection.
  • Face quality thresholds are heuristics and require calibration across devices, skin tones, lighting, optics, and accessibility needs.
  • The face oval is a visual guide; the returned JPEG is rectangular.
  • Cache URLs are session-local and are not durable storage.
  • Camera and document-scanner behavior must be validated on representative physical devices.

Support

If cordova-plugin-mlkit-suite is useful to you, consider starring the repository. Stars help other Cordova developers discover the project.

Financial contributions help cover the tools and devices used to develop, maintain, and test this and other open-source projects:

  • Ko-fi
  • PayPal
  • USDC on Arbitrum One: 0xe36a336fC6cc9Daae657b4A380dA492AB9601e73

[!CAUTION] Send USDC using the Arbitrum One network only. Transfers sent through another network may be permanently lost.

Tests

Run the JavaScript, Java confirmation, iOS source-contract, and localization-resource tests:

npm test

Before release, validate installation and a debug build with each supported Cordova Android major. Build iOS with cordova-ios 8.x on macOS, then test the native flows on physical devices.