---
description: Run a full Node.js runtime in your Capacitor app on Android and iOS. Use npm packages and exchange messages with the Node.js engine.
title: Capacitor Node.js Plugin for Android & iOS - Capawesome
image: https://capawesome.io/docs/assets/images/social/sdks/capacitor/nodejs.png
---

<!doctype html> 

[Skip to content ](#capacitor-nodejs-plugin) 

[🖥️ Introducing the **Capacitor Electron Platform** — build desktop apps for macOS, Windows, and Linux. Free & open source. ](/blog/announcing-the-capacitor-electron-platform/) 

* [ SDKs ](/docs/sdks/)
* [ Formbricks ](/docs/sdks/capacitor/formbricks/)
* [ Geocoder ](/docs/sdks/capacitor/geocoder/)
* [ Google Sign-In ](/docs/sdks/capacitor/google-sign-in/)
* [ Grafana Faro ](/docs/sdks/capacitor/grafana-faro/)
* [ Gyroscope ](/docs/sdks/capacitor/gyroscope/)
* [ Haptics ](/docs/sdks/capacitor/haptics/)
* [ Home Indicator ](/docs/sdks/capacitor/home-indicator/)
* [ In-App Browser ](/docs/sdks/capacitor/in-app-browser/)
* [ Install Referrer ](/docs/sdks/capacitor/install-referrer/)
* [ Intercom ](/docs/sdks/capacitor/intercom/)
* [ Intune ](/docs/sdks/capacitor/intune/)
* [ Keep Awake ](/docs/sdks/capacitor/keep-awake/)
* [ libSQL ](/docs/sdks/capacitor/libsql/)
* [ Light Sensor ](/docs/sdks/capacitor/light-sensor/)
* [ Live Update ](/docs/sdks/capacitor/live-update/)
* [ Localization ](/docs/sdks/capacitor/localization/)
* [ Mail Composer ](/docs/sdks/capacitor/mail-composer/)
* [ Managed Configurations ](/docs/sdks/capacitor/managed-configurations/)
* [ Maps Launcher ](/docs/sdks/capacitor/maps-launcher/)
* [ Media Session ](/docs/sdks/capacitor/media-session/)
* [ ML Kit ](/docs/sdks/capacitor/mlkit/)
* [ Navigation Bar ](/docs/sdks/capacitor/navigation-bar/)
* [ Network ](/docs/sdks/capacitor/network/)
* [ NFC ](/docs/sdks/capacitor/nfc/)
* Node.js [ Node.js ](/docs/sdks/capacitor/nodejs/)
* [ iOS ](#ios)
* [ Configuration ](#configuration)
* [ Demo ](#demo)
* [ Usage ](#usage)
* [ API ](#api)
* [ Type Aliases ](#type-aliases)
* [ Limitations ](#limitations)
* [ FAQ ](#faq)
* [ Related Plugins ](#related-plugins)
* [ Newsletter ](#newsletter)
* [ Changelog ](#changelog)
* [ License ](#license)
* [ OAuth ](/docs/sdks/capacitor/oauth/)
* [ Passkeys ](/docs/sdks/capacitor/passkeys/)
* [ Password Autofill ](/docs/sdks/capacitor/password-autofill/)
* [ PDF Generator ](/docs/sdks/capacitor/pdf-generator/)
* [ PDF Viewer ](/docs/sdks/capacitor/pdf-viewer/)
* [ Pedometer ](/docs/sdks/capacitor/pedometer/)
* [ Permissions ](/docs/sdks/capacitor/permissions/)
* [ Phone Dialer ](/docs/sdks/capacitor/phone-dialer/)
* [ Photo Editor ](/docs/sdks/capacitor/photo-editor/)
* [ Photo Manipulator ](/docs/sdks/capacitor/photo-manipulator/)
* [ PixLive ](/docs/sdks/capacitor/pixlive/)
* [ PostHog ](/docs/sdks/capacitor/posthog/)
* [ Printer ](/docs/sdks/capacitor/printer/)
* [ Privacy Screen ](/docs/sdks/capacitor/privacy-screen/)
* [ Proximity Sensor ](/docs/sdks/capacitor/proximity-sensor/)
* [ Purchases ](/docs/sdks/capacitor/purchases/)
* [ RealtimeKit ](/docs/sdks/capacitor/realtimekit/)
* [ Root Detection ](/docs/sdks/capacitor/root-detection/)
* [ Screen Brightness ](/docs/sdks/capacitor/screen-brightness/)
* [ Screen Orientation ](/docs/sdks/capacitor/screen-orientation/)
* [ Screen Reader ](/docs/sdks/capacitor/screen-reader/)
* [ Screenshot ](/docs/sdks/capacitor/screenshot/)
* [ Secure Preferences ](/docs/sdks/capacitor/secure-preferences/)
* [ Settings Launcher ](/docs/sdks/capacitor/settings-launcher/)
* [ Shake ](/docs/sdks/capacitor/shake/)
* [ Silent Mode ](/docs/sdks/capacitor/silent-mode/)
* [ SIM ](/docs/sdks/capacitor/sim/)
* [ SMS Composer ](/docs/sdks/capacitor/sms-composer/)
* [ Speech Recognition ](/docs/sdks/capacitor/speech-recognition/)
* [ Speech Synthesis ](/docs/sdks/capacitor/speech-synthesis/)
* [ Share Target ](/docs/sdks/capacitor/share-target/)
* [ Square Mobile Payments ](/docs/sdks/capacitor/square-mobile-payments/)
* [ SQLite ](/docs/sdks/capacitor/sqlite/)
* [ Superwall ](/docs/sdks/capacitor/superwall/)
* [ System WebView ](/docs/sdks/capacitor/system-webview/)
* [ Tauri ](/docs/sdks/capacitor/tauri/)
* [ Text Interaction ](/docs/sdks/capacitor/text-interaction/)
* [ Text Zoom ](/docs/sdks/capacitor/text-zoom/)
* [ Thermal State ](/docs/sdks/capacitor/thermal-state/)
* [ Toast ](/docs/sdks/capacitor/toast/)
* [ Torch ](/docs/sdks/capacitor/torch/)
* [ Vault ](/docs/sdks/capacitor/vault/)
* [ Volume ](/docs/sdks/capacitor/volume/)
* [ Wallet ](/docs/sdks/capacitor/wallet/)
* [ Wifi ](/docs/sdks/capacitor/wifi/)
* [ YouTube Player ](/docs/sdks/capacitor/youtube-player/)
* [ Zip ](/docs/sdks/capacitor/zip/)
* [ Cordova ](/docs/sdks/cordova/)
* [ Cloud ](/docs/cloud/)
* [ Integrations ](/docs/cloud/live-updates/integrations/)
* Concepts
* Reference
* [ Troubleshooting ](/docs/cloud/live-updates/troubleshooting/)
* [ FAQ ](/docs/cloud/live-updates/faq/)
* [ Native Builds ](/docs/cloud/native-builds/)
* [ Set Up Environments ](/docs/cloud/native-builds/environments/)
* [ Overwrite Native Configurations ](/docs/cloud/native-builds/native-configurations/)
* [ Auto-Increment Build Numbers ](/docs/cloud/native-builds/auto-incrementing-build-numbers/)
* [ Configure the Web Build Script ](/docs/cloud/native-builds/web-build-script/)
* [ Build from a Monorepo ](/docs/cloud/native-builds/monorepo/)
* [ Use pnpm, Yarn, or bun ](/docs/cloud/native-builds/package-managers/)
* [ Install Private npm Packages ](/docs/cloud/native-builds/npm-private-registry/)
* [ Override the Java Version ](/docs/cloud/native-builds/override-java-version/)
* [ Custom iOS Provisioning Profiles ](/docs/cloud/native-builds/custom-ios-provisioning-profiles/)
* [ Build without Git ](/docs/cloud/native-builds/build-without-git/)
* [ Access Git Behind a Firewall ](/docs/cloud/native-builds/firewall-access/)
* [ Integrations ](/docs/cloud/native-builds/integrations/)
* Reference
* [ Troubleshooting ](/docs/cloud/native-builds/troubleshooting/)
* [ FAQ ](/docs/cloud/native-builds/faq/)
* [ App Store Publishing ](/docs/cloud/app-store-publishing/)
* [ Submit a Build ](/docs/cloud/app-store-publishing/submit-a-build/)
* [ Submit Automatically After a Build ](/docs/cloud/app-store-publishing/submit-automatically/)
* [ Troubleshooting ](/docs/cloud/app-store-publishing/troubleshooting/)
* [ FAQ ](/docs/cloud/app-store-publishing/faq/)
* [ Automations ](/docs/cloud/automations/)
* [ Reference ](/docs/cloud/automations/reference/)
* [ Troubleshooting ](/docs/cloud/automations/troubleshooting/)
* [ FAQ ](/docs/cloud/automations/faq/)
* [ Assist ](/docs/cloud/assist/)
* [ CLI ](/docs/cloud/cli/)
* APIs and SDKs
* [ Webhooks ](/docs/cloud/webhooks/)
* [ Integrations ](/docs/cloud/integrations/)
* Account
* [ Organization ](/docs/cloud/organizations/)
* [ Two-Factor Enforcement ](/docs/cloud/organizations/two-factor-authentication/)
* [ Audit Logs ](/docs/cloud/organizations/audit-logs/)
* [ Billing ](/docs/cloud/organizations/billing/)
* [ License Keys ](/docs/cloud/license-keys/)
* [ AI ](/docs/ai/)
* [ Insiders ](/docs/insiders/)
* [ Billing & Plans ](/docs/insiders/billing-and-plans/)
* [ FAQ ](/docs/insiders/faq/)
* [ License ](https://capawesome.io/legal/eula/)
* [ Support ](/docs/support/)
* [ Contributing ](/docs/contributing/)
* Contributing code
* [ Code of Conduct ](/docs/contributing/code-of-conduct/)
* [ Questions ](https://docs.github.com/en/discussions/collaborating-with-your-community-using-discussions/participating-in-a-discussion#creating-a-discussion)
* [ Blog ](/blog/)
* Categories

* [ iOS ](#ios)
* [ Configuration ](#configuration)
* [ Demo ](#demo)
* [ Usage ](#usage)
* [ API ](#api)
* [ Type Aliases ](#type-aliases)
* [ Limitations ](#limitations)
* [ FAQ ](#faq)
* [ Related Plugins ](#related-plugins)
* [ Newsletter ](#newsletter)
* [ Changelog ](#changelog)
* [ License ](#license)

# Capacitor Node.js Plugin[¶](#capacitor-nodejs-plugin "Permanent link")

Capacitor plugin for running [Node.js](https://nodejs.org/) in mobile apps.[1](#fn:1)[2](#fn:2)

[ ![Deliver Live Updates to your Capacitor app with Capawesome Cloud](../../../assets/external/cloud.capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.69628c3f.png) ](https://cloud.capawesome.io/) 

## Features[¶](#features "Permanent link")

The Capacitor Node.js plugin is one of the most complete solutions for running Node.js in Capacitor apps. Here are some of the key features:

* 🖥️ **Cross-platform**: Supports Android and iOS.
* 🚀 **Node.js runtime**: Embeds a complete Node.js runtime based on [Node.js for Mobile Apps](https://github.com/nodejs-mobile/nodejs-mobile).
* 🧵 **Background thread**: Runs the Node.js engine on a dedicated background thread to avoid blocking the UI.
* 🔁 **Bidirectional communication**: Event-based message passing between the Capacitor app and the Node.js runtime.
* 📦 **npm ecosystem**: Use npm packages that are not browser-compatible and rely on Node.js core modules.
* 🛠️ **Configurable**: Start the Node.js runtime automatically or manually with custom arguments, environment variables and script.
* 🤝 **Compatibility**: Works alongside the [Background Task](https://capawesome.io/docs/sdks/capacitor/background-task/), [SQLite](https://capawesome.io/docs/sdks/capacitor/sqlite/) and [Zip](https://capawesome.io/docs/sdks/capacitor/zip/) plugins.
* 🔁 **Up-to-date**: Always supports the latest Capacitor version.

Missing a feature? Just [open an issue](https://github.com/capawesome-team/capacitor-plugins/issues) and we'll take a look!

## Use Cases[¶](#use-cases "Permanent link")

The Node.js plugin is typically used whenever an app needs functionality that only the Node.js ecosystem provides, for example:

* **Node.js-only libraries**: Use npm packages that are not browser-compatible because they rely on Node.js core modules.
* **Code reuse**: Reuse existing Node.js code in your mobile app instead of rewriting it for the browser.
* **Background processing**: Offload heavy work to the Node.js engine, which runs on a dedicated background thread and does not block the UI.
* **Local data processing**: Process and persist data on the device using the writable directory provided by the Node.js runtime.

## Compatibility[¶](#compatibility "Permanent link")

| Plugin Version | Capacitor Version | Status         |
| -------------- | ----------------- | -------------- |
| 0.0.x          | \>=8.x.x          | Active support |

## Installation[¶](#installation "Permanent link")

You can use our **AI-Assisted Setup** to install the plugin. Add the [Capawesome Skills](https://github.com/capawesome-team/skills) to your AI tool using the following command:

`[](#%5F%5Fcodelineno-0-1)npx skills add capawesome-team/skills --skill capacitor-plugins
`

Then use the following prompt:

`` [](#%5F%5Fcodelineno-1-1) Use the `capacitor-plugins` skill from `capawesome-team/skills` to install the `@capawesome/capacitor-nodejs` plugin in my project.
 ``

If you prefer **Manual Setup**, install the plugin by running the following commands and follow the platform-specific instructions below:

`[](#%5F%5Fcodelineno-2-1)npm install @capawesome/capacitor-nodejs
[](#%5F%5Fcodelineno-2-2)npx cap sync
`

**Attention**: This plugin embeds the [Node.js for Mobile Apps](https://github.com/nodejs-mobile/nodejs-mobile) runtime binaries. The binaries are not included in the npm package but downloaded on demand: the Android binaries are downloaded by the Gradle build and the iOS binaries are downloaded during `npm install` (only on macOS). Set the `CAPACITOR_NODEJS_SKIP_DOWNLOAD` environment variable to `1` to skip the iOS download.

### Android[¶](#android "Permanent link")

#### Variables[¶](#variables "Permanent link")

If needed, you can define the following project variables in your app's `variables.gradle` file to change the default version of the runtime:

* `$nodejsMobileVersion` version of the Node.js for Mobile Apps runtime (default: `18.20.4-capawesome.1`, a [16 KB page size compatible build](https://github.com/capawesome-team/nodejs-mobile/releases))
* `$nodejsMobileAndroidUrl` download URL of the Android runtime binaries (default: GitHub release of `$nodejsMobileVersion`)
* `$nodejsMobileAndroidSha256` SHA-256 checksum of the Android runtime binaries download (default: checksum of `$nodejsMobileVersion`)

### iOS[¶](#ios "Permanent link")

This plugin currently only supports **Swift Package Manager**. CocoaPods is not supported.

If you install dependencies with disabled lifecycle scripts (e.g. `npm install --ignore-scripts`), the iOS runtime binaries are not downloaded automatically. In this case, run the download script manually before building your app:

`[](#%5F%5Fcodelineno-3-1)node node_modules/@capawesome/capacitor-nodejs/scripts/postinstall.js
`

## Configuration[¶](#configuration "Permanent link")

| Prop          | Type               | Description                                                                                                                                                                                                                                              | Default  | Since |
| ------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ----- |
| **nodeDir**   | string             | The directory of the Node.js project, relative to the Capacitor webDir. Only available on Android and iOS.                                                                                                                                               | 'nodejs' | 0.0.1 |
| **startMode** | 'manual' \| 'auto' | The start mode of the Node.js runtime. If set to auto, the Node.js runtime starts automatically when the app is launched. If set to manual, the Node.js runtime must be started manually using the start(...) method. Only available on Android and iOS. | 'auto'   | 0.0.1 |

### Examples[¶](#examples "Permanent link")

In `capacitor.config.json`:

`[](#%5F%5Fcodelineno-4-1){
[](#%5F%5Fcodelineno-4-2)  "plugins": {
[](#%5F%5Fcodelineno-4-3)    "Nodejs": {
[](#%5F%5Fcodelineno-4-4)      "nodeDir": 'custom-nodejs',
[](#%5F%5Fcodelineno-4-5)      "startMode": 'manual'
[](#%5F%5Fcodelineno-4-6)    }
[](#%5F%5Fcodelineno-4-7)  }
[](#%5F%5Fcodelineno-4-8)}
`

In `capacitor.config.ts`:

`[](#%5F%5Fcodelineno-5-1)/// <reference types="@capawesome/capacitor-nodejs" />
[](#%5F%5Fcodelineno-5-2)
[](#%5F%5Fcodelineno-5-3)import { CapacitorConfig } from '@capacitor/cli';
[](#%5F%5Fcodelineno-5-4)
[](#%5F%5Fcodelineno-5-5)const config: CapacitorConfig = {
[](#%5F%5Fcodelineno-5-6)  plugins: {
[](#%5F%5Fcodelineno-5-7)    Nodejs: {
[](#%5F%5Fcodelineno-5-8)      nodeDir: 'custom-nodejs',
[](#%5F%5Fcodelineno-5-9)      startMode: 'manual',
[](#%5F%5Fcodelineno-5-10)    },
[](#%5F%5Fcodelineno-5-11)  },
[](#%5F%5Fcodelineno-5-12)};
[](#%5F%5Fcodelineno-5-13)
[](#%5F%5Fcodelineno-5-14)export default config;
`

## Demo[¶](#demo "Permanent link")

A working example can be found [here](https://github.com/capawesome-team/capacitor-plugins/tree/main/packages/nodejs/example).

## Usage[¶](#usage "Permanent link")

The following examples show how to set up the Node.js project, communicate between Node.js and the Capacitor app, start the runtime manually, wait for it to be ready, and exchange messages with it.

### Set up the Node.js project[¶](#set-up-the-nodejs-project "Permanent link")

The plugin runs the Node.js project located in the `nodejs` directory (see the `nodeDir` configuration option) inside your Capacitor `webDir`. Make sure your web build outputs the Node.js project to this directory, for example by placing it in the `public` directory of your web project:

`[](#%5F%5Fcodelineno-6-1)my-app
[](#%5F%5Fcodelineno-6-2)├── capacitor.config.json   // webDir: 'dist'
[](#%5F%5Fcodelineno-6-3)└── src
[](#%5F%5Fcodelineno-6-4)    └── public
[](#%5F%5Fcodelineno-6-5)        └── nodejs
[](#%5F%5Fcodelineno-6-6)            ├── package.json
[](#%5F%5Fcodelineno-6-7)            └── index.js
`

The `package.json` file of the Node.js project defines the script file to run in the `main` field:

`[](#%5F%5Fcodelineno-7-1){
[](#%5F%5Fcodelineno-7-2)  "name": "nodejs-project",
[](#%5F%5Fcodelineno-7-3)  "version": "1.0.0",
[](#%5F%5Fcodelineno-7-4)  "main": "index.js"
[](#%5F%5Fcodelineno-7-5)}
`

### Communicate with the Capacitor app from Node.js[¶](#communicate-with-the-capacitor-app-from-nodejs "Permanent link")

Inside the script file (`index.js` in this example), the built-in `bridge` module provides the communication channel to the Capacitor app:

`[](#%5F%5Fcodelineno-8-1)const { app, channel } = require('bridge');
[](#%5F%5Fcodelineno-8-2)
[](#%5F%5Fcodelineno-8-3)// Receive messages from the Capacitor app.
[](#%5F%5Fcodelineno-8-4)channel.on('my-event', (...args) => {
[](#%5F%5Fcodelineno-8-5)  // Send messages to the Capacitor app.
[](#%5F%5Fcodelineno-8-6)  channel.post('my-response', 'Hello from Node.js!');
[](#%5F%5Fcodelineno-8-7)});
[](#%5F%5Fcodelineno-8-8)
[](#%5F%5Fcodelineno-8-9)// Get a writable directory for persistent file storage.
[](#%5F%5Fcodelineno-8-10)const dataDir = app.datadir();
[](#%5F%5Fcodelineno-8-11)
[](#%5F%5Fcodelineno-8-12)// Listen for app lifecycle events.
[](#%5F%5Fcodelineno-8-13)app.on('pause', pauseLock => {
[](#%5F%5Fcodelineno-8-14)  pauseLock.release();
[](#%5F%5Fcodelineno-8-15)});
[](#%5F%5Fcodelineno-8-16)app.on('resume', () => {});
`

**Attention**: The Node.js project directory may be overwritten during app updates. Store persistent data in the directory returned by `app.datadir()`.

### Start the Node.js runtime manually[¶](#start-the-nodejs-runtime-manually "Permanent link")

By default, the Node.js runtime starts automatically when the app is launched. If the `startMode` configuration option is set to `manual`, start it yourself with custom arguments, environment variables and script:

`` [](#%5F%5Fcodelineno-9-1)import { Nodejs } from '@capawesome/capacitor-nodejs';
[](#%5F%5Fcodelineno-9-2)
[](#%5F%5Fcodelineno-9-3)const start = async () => {
[](#%5F%5Fcodelineno-9-4)  // Only available if the `startMode` configuration option is set to `manual`.
[](#%5F%5Fcodelineno-9-5)  await Nodejs.start({
[](#%5F%5Fcodelineno-9-6)    args: ['--option', 'value'],
[](#%5F%5Fcodelineno-9-7)    env: { MY_ENV_VAR: 'value' },
[](#%5F%5Fcodelineno-9-8)    script: 'custom-main.js',
[](#%5F%5Fcodelineno-9-9)  });
[](#%5F%5Fcodelineno-9-10)};
 ``

### Wait for the Node.js runtime to be ready[¶](#wait-for-the-nodejs-runtime-to-be-ready "Permanent link")

The Node.js runtime is considered ready as soon as the Node.js project has required the `bridge` module. Check the current state with `isReady()` or listen for the `ready` event:

`[](#%5F%5Fcodelineno-10-1)import { Nodejs } from '@capawesome/capacitor-nodejs';
[](#%5F%5Fcodelineno-10-2)
[](#%5F%5Fcodelineno-10-3)const isReady = async () => {
[](#%5F%5Fcodelineno-10-4)  const { ready } = await Nodejs.isReady();
[](#%5F%5Fcodelineno-10-5)  return ready;
[](#%5F%5Fcodelineno-10-6)};
[](#%5F%5Fcodelineno-10-7)
[](#%5F%5Fcodelineno-10-8)const addReadyListener = async () => {
[](#%5F%5Fcodelineno-10-9)  await Nodejs.addListener('ready', () => {
[](#%5F%5Fcodelineno-10-10)    console.log('The Node.js runtime is ready.');
[](#%5F%5Fcodelineno-10-11)  });
[](#%5F%5Fcodelineno-10-12)};
`

### Exchange messages with the Node.js runtime[¶](#exchange-messages-with-the-nodejs-runtime "Permanent link")

Once the Node.js runtime is ready, send messages to it and listen for messages received from it:

`[](#%5F%5Fcodelineno-11-1)import { Nodejs } from '@capawesome/capacitor-nodejs';
[](#%5F%5Fcodelineno-11-2)
[](#%5F%5Fcodelineno-11-3)const send = async () => {
[](#%5F%5Fcodelineno-11-4)  await Nodejs.send({
[](#%5F%5Fcodelineno-11-5)    eventName: 'my-event',
[](#%5F%5Fcodelineno-11-6)    args: ['Hello from Capacitor!'],
[](#%5F%5Fcodelineno-11-7)  });
[](#%5F%5Fcodelineno-11-8)};
[](#%5F%5Fcodelineno-11-9)
[](#%5F%5Fcodelineno-11-10)const addMessageListener = async () => {
[](#%5F%5Fcodelineno-11-11)  await Nodejs.addListener('message', event => {
[](#%5F%5Fcodelineno-11-12)    console.log('Received message:', event.eventName, event.args);
[](#%5F%5Fcodelineno-11-13)  });
[](#%5F%5Fcodelineno-11-14)};
`

### Use npm packages[¶](#use-npm-packages "Permanent link")

To use npm packages, run `npm install --omit=dev` inside the Node.js project directory before building your web project. It's recommended to bundle the Node.js project into a single file (e.g. with [esbuild](https://esbuild.github.io/)) to improve the startup time.

## API[¶](#api "Permanent link")

* [isReady()](#isready)
* [send(...)](#send)
* [start(...)](#start)
* [addListener('message', ...)](#addlistenermessage-)
* [addListener('ready', ...)](#addlistenerready-)
* [removeAllListeners()](#removealllisteners)
* [Interfaces](#interfaces)
* [Type Aliases](#type-aliases)

### isReady()[¶](#isready "Permanent link")

`[](#%5F%5Fcodelineno-12-1)isReady() => Promise<IsReadyResult>
`

Check if the Node.js runtime is ready to receive messages.

The Node.js runtime is considered ready as soon as the Node.js project has required the `bridge` module.

Only available on Android and iOS.

**Returns:** `Promise<[IsReadyResult](#isreadyresult)>`

**Since:** 0.0.1

---

### send(...)[¶](#send "Permanent link")

`[](#%5F%5Fcodelineno-13-1)send(options: SendOptions) => Promise<void>
`

Send a message to the Node.js runtime.

This method is only available when the Node.js runtime is ready. Use the `isReady()` method or the `ready` event to check if the Node.js runtime is ready.

Only available on Android and iOS.

| Param       | Type                        |
| ----------- | --------------------------- |
| **options** | [SendOptions](#sendoptions) |

**Since:** 0.0.1

---

### start(...)[¶](#start "Permanent link")

`[](#%5F%5Fcodelineno-14-1)start(options?: StartOptions | undefined) => Promise<void>
`

Start the Node.js runtime manually.

This method is only available if the `startMode` configuration option is set to `manual`.

**Attention**: The Node.js runtime can only be started once per app launch. Stopping and restarting the Node.js runtime is not supported.

Only available on Android and iOS.

| Param       | Type                          |
| ----------- | ----------------------------- |
| **options** | [StartOptions](#startoptions) |

**Since:** 0.0.1

---

### addListener('message', ...)[¶](#addlistenermessage "Permanent link")

`[](#%5F%5Fcodelineno-15-1)addListener(eventName: 'message', listenerFunc: (event: MessageEvent) => void) => Promise<PluginListenerHandle>
`

Called when a message is received from the Node.js runtime.

Only available on Android and iOS.

| Param            | Type                                           |
| ---------------- | ---------------------------------------------- |
| **eventName**    | 'message'                                      |
| **listenerFunc** | (event: [MessageEvent](#messageevent)) => void |

**Returns:** `Promise<[PluginListenerHandle](#pluginlistenerhandle)>`

**Since:** 0.0.1

---

### addListener('ready', ...)[¶](#addlistenerready "Permanent link")

`[](#%5F%5Fcodelineno-16-1)addListener(eventName: 'ready', listenerFunc: () => void) => Promise<PluginListenerHandle>
`

Called when the Node.js runtime is ready to receive messages.

Only available on Android and iOS.

| Param            | Type       |
| ---------------- | ---------- |
| **eventName**    | 'ready'    |
| **listenerFunc** | () => void |

**Returns:** `Promise<[PluginListenerHandle](#pluginlistenerhandle)>`

**Since:** 0.0.1

---

### removeAllListeners()[¶](#removealllisteners "Permanent link")

`[](#%5F%5Fcodelineno-17-1)removeAllListeners() => Promise<void>
`

Remove all listeners for this plugin.

**Since:** 0.0.1

---

### Interfaces[¶](#interfaces "Permanent link")

#### IsReadyResult[¶](#isreadyresult "Permanent link")

| Prop      | Type    | Description                                                      | Since |
| --------- | ------- | ---------------------------------------------------------------- | ----- |
| **ready** | boolean | Whether or not the Node.js runtime is ready to receive messages. | 0.0.1 |

#### SendOptions[¶](#sendoptions "Permanent link")

| Prop          | Type           | Description                                           | Since |
| ------------- | -------------- | ----------------------------------------------------- | ----- |
| **args**      | MessageArg\[\] | The arguments to send to the Node.js runtime.         | 0.0.1 |
| **eventName** | string         | The name of the event to send to the Node.js runtime. | 0.0.1 |

#### StartOptions[¶](#startoptions "Permanent link")

| Prop       | Type                         | Description                                                                    | Default                                                         | Since |
| ---------- | ---------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------- | ----- |
| **args**   | string\[\]                   | The arguments to pass to the Node.js process.                                  |                                                                 | 0.0.1 |
| **env**    | { \[key: string\]: string; } | The environment variables to set for the Node.js process.                      |                                                                 | 0.0.1 |
| **script** | string                       | The path of the script file to run, relative to the Node.js project directory. | The main field of the package.json file of the Node.js project. | 0.0.1 |

#### PluginListenerHandle[¶](#pluginlistenerhandle "Permanent link")

| Prop       | Type                |
| ---------- | ------------------- |
| **remove** | () => Promise<void> |

#### MessageEvent[¶](#messageevent "Permanent link")

| Prop          | Type           | Description                                              | Since |
| ------------- | -------------- | -------------------------------------------------------- | ----- |
| **args**      | MessageArg\[\] | The arguments received from the Node.js runtime.         | 0.0.1 |
| **eventName** | string         | The name of the event received from the Node.js runtime. | 0.0.1 |

### Type Aliases[¶](#type-aliases "Permanent link")

#### MessageArg[¶](#messagearg "Permanent link")

A single argument of a message that is exchanged with the Node.js runtime.

The value must be JSON-serializable.

`string | number | boolean | null | MessageArg[] | { [key: string]: [MessageArg](#messagearg) }`

## Limitations[¶](#limitations "Permanent link")

The underlying [Node.js for Mobile Apps](https://github.com/nodejs-mobile/nodejs-mobile) runtime has some limitations that you should be aware of:

* **Single instance**: The Node.js runtime can only be started once per app launch. Stopping and restarting the runtime is not supported.
* **No child processes**: The `child_process` module is not supported on mobile platforms.
* **No JIT on iOS**: On iOS, the JavaScript engine runs in interpreter-only mode (no JIT compilation), which results in slower JavaScript execution compared to Android.
* **App size**: Embedding the Node.js runtime increases the app size by several tens of megabytes per CPU architecture.
* **Native addons**: Node.js native addons are only supported on Android if they are provided as prebuilds (see [node-gyp-build](https://github.com/prebuild/node-gyp-build)) for the target architectures.
* **`process.exit()`**: Calling `process.exit()` is not allowed by the Apple App Store guidelines.

## FAQ[¶](#faq "Permanent link")

### Which Node.js version is supported?[¶](#which-nodejs-version-is-supported "Permanent link")

The plugin currently runs Node.js `18.20.4`, the latest version available from [Node.js for Mobile Apps](https://github.com/nodejs-mobile/nodejs-mobile). Support for newer Node.js versions requires self-built runtime binaries for mobile platforms, which we are evaluating.

### Why is there no `stop()` method?[¶](#why-is-there-no-stop-method "Permanent link")

The underlying runtime only supports a single Node.js instance per app launch and provides no API to stop or restart it. A `stop()` method would therefore leave the app in a state where Node.js could never be started again until the app is restarted. If you need to stop work in the Node.js runtime, send a message (e.g. a `shutdown` event) and let your Node.js code stop its servers and timers. The idle runtime consumes negligible resources.

### Where should I store persistent data in the Node.js project?[¶](#where-should-i-store-persistent-data-in-the-nodejs-project "Permanent link")

Store persistent data in the directory returned by `app.datadir()` of the built-in `bridge` module. The Node.js project directory itself may be overwritten during app updates, so any files written there can be lost.

### Why is JavaScript execution slower on iOS than on Android?[¶](#why-is-javascript-execution-slower-on-ios-than-on-android "Permanent link")

On iOS, the JavaScript engine runs in interpreter-only mode without JIT compilation, which results in slower JavaScript execution compared to Android. This is a limitation of the underlying Node.js for Mobile Apps runtime. See the [Limitations](#limitations) section for more details.

### Can I use this plugin with Ionic, React, Vue or Angular?[¶](#can-i-use-this-plugin-with-ionic-react-vue-or-angular "Permanent link")

Yes, the plugin is framework-agnostic. It works in any Capacitor app regardless of the web framework, including Ionic with Angular, React, or Vue, as well as plain JavaScript projects.

## Related Plugins[¶](#related-plugins "Permanent link")

* [Background Task](https://capawesome.io/docs/sdks/capacitor/background-task/): Run background tasks in your Capacitor app.
* [SQLite](https://capawesome.io/docs/sdks/capacitor/sqlite/): Access SQLite databases with support for encryption, transactions, and schema migrations.
* [Zip](https://capawesome.io/docs/sdks/capacitor/zip/): Zip and unzip files and directories.

## Newsletter[¶](#newsletter "Permanent link")

Stay up to date with the latest news and updates about the Capawesome, Capacitor, and Ionic ecosystem by subscribing to our [Capawesome Newsletter](https://cloud.capawesome.io/newsletter/).

## Changelog[¶](#changelog "Permanent link")

See [CHANGELOG.md](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/nodejs/CHANGELOG.md).

## License[¶](#license "Permanent link")

See [LICENSE](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/nodejs/LICENSE).

---

1. This project is not affiliated with, endorsed by, sponsored by, or approved by the OpenJS Foundation or any of their affiliates or subsidiaries. [↩](#fnref:1 "Jump back to footnote 1 in the text")
2. `Node.js` is a registered trademark of the OpenJS Foundation. [↩](#fnref:2 "Jump back to footnote 2 in the text")

July 8, 2026 

Back to top

```json
{"@context": "https://schema.org", "@graph": [{"@type": "TechArticle", "@id": "https://capawesome.io/docs/sdks/capacitor/nodejs/#article", "headline": "Capacitor Node.js Plugin for Android & iOS", "name": "Capacitor Node.js Plugin for Android & iOS", "description": "Run a full Node.js runtime in your Capacitor app on Android and iOS. Use npm packages and exchange messages with the Node.js engine.", "inLanguage": "en", "url": "https://capawesome.io/docs/sdks/capacitor/nodejs/", "mainEntityOfPage": "https://capawesome.io/docs/sdks/capacitor/nodejs/", "author": {"@type": "Organization", "name": "Capawesome", "url": "https://capawesome.io", "logo": {"@type": "ImageObject", "url": "https://capawesome.io/assets/images/logo.svg"}}, "publisher": {"@type": "Organization", "name": "Capawesome", "url": "https://capawesome.io", "logo": {"@type": "ImageObject", "url": "https://capawesome.io/assets/images/logo.svg"}}, "about": {"@id": "https://capawesome.io/docs/sdks/capacitor/nodejs/#software"}}, {"@type": "SoftwareSourceCode", "@id": "https://capawesome.io/docs/sdks/capacitor/nodejs/#software", "name": "Capacitor Node.js Plugin for Android & iOS", "description": "Run a full Node.js runtime in your Capacitor app on Android and iOS. Use npm packages and exchange messages with the Node.js engine.", "url": "https://capawesome.io/docs/sdks/capacitor/nodejs/", "programmingLanguage": "TypeScript", "runtimePlatform": "Capacitor", "codeRepository": "https://github.com/capawesome-team", "author": {"@type": "Organization", "name": "Capawesome", "url": "https://capawesome.io", "logo": {"@type": "ImageObject", "url": "https://capawesome.io/assets/images/logo.svg"}}, "publisher": {"@type": "Organization", "name": "Capawesome", "url": "https://capawesome.io", "logo": {"@type": "ImageObject", "url": "https://capawesome.io/assets/images/logo.svg"}}}]}
{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "Which Node.js version is supported?", "acceptedAnswer": {"@type": "Answer", "text": "The plugin currently runs Node.js 18.20.4, the latest version available from Node.js for Mobile Apps. Support for newer Node.js versions requires self-built runtime binaries for mobile platforms, which we are evaluating."}}, {"@type": "Question", "name": "Why is there no stop() method?", "acceptedAnswer": {"@type": "Answer", "text": "The underlying runtime only supports a single Node.js instance per app launch and provides no API to stop or restart it. A stop() method would therefore leave the app in a state where Node.js could never be started again until the app is restarted. If you need to stop work in the Node.js runtime, send a message (e.g. a shutdown event) and let your Node.js code stop its servers and timers. The idle runtime consumes negligible resources."}}, {"@type": "Question", "name": "Where should I store persistent data in the Node.js project?", "acceptedAnswer": {"@type": "Answer", "text": "Store persistent data in the directory returned by app.datadir() of the built-in bridge module. The Node.js project directory itself may be overwritten during app updates, so any files written there can be lost."}}, {"@type": "Question", "name": "Why is JavaScript execution slower on iOS than on Android?", "acceptedAnswer": {"@type": "Answer", "text": "On iOS, the JavaScript engine runs in interpreter-only mode without JIT compilation, which results in slower JavaScript execution compared to Android. This is a limitation of the underlying Node.js for Mobile Apps runtime. See the Limitations section for more details."}}, {"@type": "Question", "name": "Can I use this plugin with Ionic, React, Vue or Angular?", "acceptedAnswer": {"@type": "Answer", "text": "Yes, the plugin is framework-agnostic. It works in any Capacitor app regardless of the web framework, including Ionic with Angular, React, or Vue, as well as plain JavaScript projects."}}], "url": "https://capawesome.io/docs/sdks/capacitor/nodejs/"}
```
