Skip to content

@tauri-apps/api/core

Invoke your custom commands.

This package is also accessible with window.__TAURI__.core when app.withGlobalTauri in tauri.conf.json is set to true.

function addPluginListener<T>(
plugin: string,
event: string,
cb: (payload: T) => void
): Promise<PluginListener>;

Defined in: packages/api/src/core.ts:287

Adds a listener to a plugin event.

This is meant to be used by plugin authors to wrap the register_listener command their mobile plugin implements; application code normally calls the wrapper the plugin exposes instead of this function.

import { addPluginListener } from '@tauri-apps/api/core';
interface ScanEvent {
value: string
}
const listener = await addPluginListener<ScanEvent>(
'barcode-scanner',
'scan',
(payload) => console.log('scanned', payload.value)
);
// stop listening when the scanner screen is closed
await listener.unregister();
Type Parameter
T
Parameter Type Description
plugin string The plugin name, as used in the `plugin:
event string The plugin event name.
cb (payload: T) => void The callback executed for each event payload.

Promise<PluginListener>

The listener object to stop listening to the events.

2.0.0


function checkPermissions<T>(plugin: string): Promise<T>;

Defined in: packages/api/src/core.ts:335

Get permission state for a plugin.

This should be used by plugin authors to wrap their actual implementation, it calls the plugin:<name>|check_permissions command implemented by the mobile plugin and returns its permission status object without prompting the user.

import { checkPermissions, type PermissionState } from '@tauri-apps/api/core';
interface Permissions {
camera: PermissionState
}
const status = await checkPermissions<Permissions>('barcode-scanner');
if (status.camera === 'prompt') {
// ask the user, see requestPermissions
}
Type Parameter
T
Parameter Type Description
plugin string The plugin name, as used in the `plugin:

Promise<T>

2.0.0


function convertFileSrc(filePath: string, protocol?: string): string;

Defined in: packages/api/src/core.ts:495

Convert a device file path to a URL that can be loaded by the webview.

The asset protocol must be enabled and the files you want to expose must be included in its scope. The protocol origins must also be allowed by the relevant app.security.csp directive. For example, this configuration allows images from the user’s downloads directory:

{
"app": {
"security": {
"assetProtocol": {
"enable": true,
"scope": ["$DOWNLOAD/**"]
},
"csp": "default-src 'self'; img-src 'self' asset: http://asset.localhost"
}
}
}

See assetProtocol for the available scope variables and platform-specific protocol details.

import { downloadDir, join } from '@tauri-apps/api/path';
import { convertFileSrc } from '@tauri-apps/api/core';
const downloads = await downloadDir();
const filePath = await join(downloads, 'photo.png');
const assetUrl = convertFileSrc(filePath);
const image = document.getElementById('my-image') as HTMLImageElement;
image.src = assetUrl;
Parameter Type Default value Description
filePath string undefined The file path.
protocol string 'asset' The protocol to use. Defaults to asset. You only need to set this when using a custom protocol.

string

the URL that can be used as source on the webview.

1.0.0


function invoke<T>(
cmd: string,
args?: InvokeArgs,
options?: InvokeOptions
): Promise<T>;

Defined in: packages/api/src/core.ts:443

Sends a message to the backend.

import { invoke } from '@tauri-apps/api/core';
await invoke('login', { user: 'tauri', password: 'poiwe3h4r5ip3yrhtew9ty' });
Type Parameter
T
Parameter Type Description
cmd string The command name.
args InvokeArgs The optional arguments to pass to the command.
options? InvokeOptions The request options.

Promise<T>

A promise resolving or rejecting to the backend response.

1.0.0


function isTauri(): boolean;

Defined in: packages/api/src/core.ts:605

Checks whether the code is running inside a Tauri webview.

Useful for frontends that are also served on the web, to guard calls to APIs that only exist inside the application.

import { isTauri } from '@tauri-apps/api/core';
import { getVersion } from '@tauri-apps/api/app';
const version = isTauri() ? await getVersion() : 'web';

boolean

true when running inside a Tauri app, false otherwise (e.g. in a browser or in unit tests).

2.0.0


function requestPermissions<T>(plugin: string): Promise<T>;

Defined in: packages/api/src/core.ts:365

Request permissions.

This should be used by plugin authors to wrap their actual implementation, it calls the plugin:<name>|request_permissions command implemented by the mobile plugin, which shows the native permission prompt when needed, and returns the resulting permission status object.

import { requestPermissions, type PermissionState } from '@tauri-apps/api/core';
interface Permissions {
camera: PermissionState
}
const status = await requestPermissions<Permissions>('barcode-scanner');
if (status.camera !== 'granted') {
throw new Error('camera permission denied');
}
Type Parameter
T
Parameter Type Description
plugin string The plugin name, as used in the `plugin:

Promise<T>

2.0.0


function transformCallback<T = unknown>(callback?: (response: T) => void, once?: boolean): number;

Defined in: packages/api/src/core.ts:69

Stores the callback in a known location, and returns an identifier that can be passed to the backend. The backend uses the identifier to eval() the callback.

Type Parameter Default type
T unknown
Parameter Type Default value
callback? (response: T) => void undefined
once? boolean false

number

An unique identifier associated with the callback function.

1.0.0

Defined in: packages/api/src/core.ts:119

A message channel used to stream values from Rust to the frontend.

A Channel is the JavaScript counterpart of tauri::ipc::Channel. Pass an instance as a command argument and the Rust command can declare a tauri::ipc::Channel<T> parameter with the same name; every value sent from Rust is then delivered to Channel.onmessage. Messages are delivered in the order they were sent, even when they arrive out of order.

The channel stays alive until the Rust Channel is dropped, so it can be used for long-running work such as download progress or log streaming.

Raw byte payloads are delivered to the frontend as an ArrayBuffer rather than a JSON value, so declare the channel as Channel<ArrayBuffer> when the Rust side sends tauri::ipc::InvokeResponseBody::Raw — for example through a Channel<tauri::ipc::Response> whose values are built with tauri::ipc::Response::new(bytes).

import { Channel, invoke } from '@tauri-apps/api/core';
const onEvent = new Channel<string>();
onEvent.onmessage = (message) => {
console.log(`got download event ${message}`);
};
await invoke('download', { url: 'https://tauri.app', onEvent });

The matching Rust command:

#[tauri::command]
async fn download(url: String, on_event: tauri::ipc::Channel<String>) -> tauri::Result<()> {
on_event.send("started".to_string())?;
on_event.send("finished".to_string())?;
Ok(())
}

2.0.0

Type Parameter Default type
T unknown

new Channel<T = unknown>(onmessage?: (response: T) => void): Channel<T>;

Defined in: packages/api/src/core.ts:134

Parameter Type
onmessage? (response: T) => void

Channel<T>

Property Type Description Defined in
id number The callback id returned from transformCallback. This is the value sent across the IPC, it is used by the Rust side to address this channel and should not be changed. packages/api/src/core.ts:126

get onmessage(): (response: T) => void;

Defined in: packages/api/src/core.ts:209

(response: T) => void

set onmessage(handler: (response: T) => void): void;

Defined in: packages/api/src/core.ts:205

The handler called for every message sent by the Rust side of this channel.

Assigning a new handler replaces the previous one; messages that arrived before a handler was set are not replayed, so set it (or pass it to the constructor) before sending the channel to the backend.

Parameter Type
handler (response: T) => void

void

__TAURI_TO_IPC_KEY__(): string;

Defined in: packages/api/src/core.ts:213

string

toJSON(): string;

Defined in: packages/api/src/core.ts:217

string


Defined in: packages/api/src/core.ts:232

A handle to a listener registered with addPluginListener.

Keep the returned instance around and call PluginListener.unregister when the listener goes out of scope, otherwise the plugin keeps sending events to a handler nothing uses anymore.

2.0.0

new PluginListener(
plugin: string,
event: string,
channelId: number
): PluginListener;

Defined in: packages/api/src/core.ts:240

Parameter Type
plugin string
event string
channelId number

PluginListener

Property Type Description Defined in
channelId number The id of the Channel backing this listener. packages/api/src/core.ts:238
event string The plugin event name the listener is registered to. packages/api/src/core.ts:236
plugin string The plugin name the listener is registered to. packages/api/src/core.ts:234

unregister(): Promise<void>;

Defined in: packages/api/src/core.ts:247

Removes this listener from the plugin, so its handler stops being called.

Promise<void>


Defined in: packages/api/src/core.ts:557

A rust-backed resource stored through tauri::Manager::resources_table API.

The resource lives in the main process and does not exist in the Javascript world, and thus will not be cleaned up automatically except on application exit. If you want to clean it up early, call Resource.close or use Explicit Resource Management.

Several API types are resources and inherit this behavior, among them Menu, TrayIcon, Image, Webview and the menu item classes.

To support older browsers with Explicit Resource Management, use a supported compiler (e.g. tsc) or bundler (e.g. rollup).

import { Resource, invoke } from '@tauri-apps/api/core';
export class DatabaseHandle extends Resource {
static async open(path: string): Promise<DatabaseHandle> {
const rid: number = await invoke('open_db', { path });
return new DatabaseHandle(rid);
}
async execute(sql: string): Promise<void> {
await invoke('execute_sql', { rid: this.rid, sql });
}
}

Only asynchronous disposal is implemented (Symbol.asyncDispose), because closing a resource is an IPC call. Use await using; the synchronous using form does not work with resources.

await using db = await DatabaseHandle.open('test.db');
await db.execute('SELECT *');
// `db` is closed here, by awaiting `db[Symbol.asyncDispose]()`

To support older browsers, add the following to the globals (e.g. adding to the HTML file):

Symbol.asyncDispose ??= Symbol("Symbol.asyncDispose");

And for the compiler, for example tsc, rollup, vite, add the following to tsconfig.json:

{
"compilerOptions": {
"target": "es2022",
"lib": ["es2022", "esnext.disposable", "dom"]
}
}

new Resource(rid: number): Resource;

Defined in: packages/api/src/core.ts:564

Parameter Type
rid number

Resource

get rid(): number;

Defined in: packages/api/src/core.ts:560

number

asyncDispose: Promise<void>;

Defined in: packages/api/src/core.ts:581

Promise<void>

close(): Promise<void>;

Defined in: packages/api/src/core.ts:575

Destroys and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Promise<void>

Uses the core:resources:allow-close permission, which is part of the core:resources:default permission set enabled by default.

Defined in: packages/api/src/core.ts:408

2.0.0

Property Type Description Defined in
headers HeadersInit Headers to send along with the IPC request. They are readable on the Rust side through tauri::ipc::Request::headers and are useful to pass metadata (such as a content type for a raw payload) without adding it to the command arguments. Example import { invoke } from '@tauri-apps/api/core'; await invoke('upload', new Uint8Array([1, 2, 3]), { headers: { 'x-file-name': 'image.png' } }); packages/api/src/core.ts:425

type InvokeArgs =
| Record<string, unknown>
| number[]
| ArrayBuffer
| Uint8Array;

Defined in: packages/api/src/core.ts:403

Command arguments.

An object is the usual form: each key becomes a command parameter, serialized as JSON (application/octet-stream is used instead when a value implements SERIALIZE_TO_IPC_FN, see its documentation).

The ArrayBuffer, Uint8Array and number[] variants are a raw payload: the whole request body is sent as application/octet-stream instead of JSON, which avoids the cost of base64/array encoding for large binary data. The command then has a single tauri::ipc::Request parameter and reads the bytes from it:

#[tauri::command]
fn upload(request: tauri::ipc::Request<'_>) -> Result<(), String> {
let tauri::ipc::InvokeBody::Raw(bytes) = request.body() else {
return Err("expected a raw body".into());
};
println!("got {} bytes", bytes.len());
Ok(())
}
import { invoke } from '@tauri-apps/api/core';
await invoke('upload', new Uint8Array([1, 2, 3]));

A command that returns tauri::ipc::Response likewise resolves to an ArrayBuffer on the frontend instead of a JSON value.

1.0.0


type PermissionState = "granted" | "denied" | "prompt" | "prompt-with-rationale";

Defined in: packages/api/src/core.ts:307

const SERIALIZE_TO_IPC_FN: "__TAURI_TO_IPC_KEY__" = '__TAURI_TO_IPC_KEY__';

Defined in: packages/api/src/core.ts:59

A key to be used to implement a special function on your types that define how your type should be serialized when passing across the IPC.

Given a type in Rust that looks like this

#[derive(serde::Serialize, serde::Deserialize)
enum UserId {
String(String),
Number(u32),
}

UserId::String("id") would be serialized into { String: "id" } and so we need to pass the same structure back to Rust

import { SERIALIZE_TO_IPC_FN } from "@tauri-apps/api/core"
class UserIdString {
id
constructor(id) {
this.id = id
}
[SERIALIZE_TO_IPC_FN]() {
return { String: this.id }
}
}
class UserIdNumber {
id
constructor(id) {
this.id = id
}
[SERIALIZE_TO_IPC_FN]() {
return { Number: this.id }
}
}
type UserId = UserIdString | UserIdNumber

© 2026 Tauri Contributors. CC-BY / MIT