@kosadchiy/plugin-esc-pos
v0.2.0
Published
Tauri plugin for ESC/POS receipt printers over USB and TCP.
Maintainers
Readme
Tauri Plugin ESC/POS
ESC/POS printer plugin for Tauri applications.
The plugin supports:
- USB printing on desktop and Android
- TCP printing on desktop, Android, and iOS
- Cash drawer opening over USB or TCP
- USB printer discovery on desktop and Android
- Receipt text formatting, barcodes, and QR codes with platform-specific support
Platform Support
| Platform | USB Print | TCP Print | Open Drawer | List Printers | | --- | --- | --- | --- | --- | | Desktop | ✅ | ✅ | ✅ | USB only | | Android | ✅ | ✅ | ✅ | USB only | | iOS | ❌ | ✅ | ✅ | ❌ |
Notes:
- USB printing is not supported on iOS due to platform limitations.
Demo App
The repository includes a Tauri demo app in examples/tauri-app for testing the plugin against real USB and TCP printers.
It lets you:
- switch between USB and TCP targets
- discover USB printers
- edit receipt markup live
- send
print,printAndOpenDrawer, andopenDrawerrequests - try the bundled retail and kitchen receipt samples
Run it with:
cd examples/tauri-app
npm install
npm run tauri devScreenshot:

Installation
Rust
Add the plugin to your Tauri app:
[dependencies]
tauri-plugin-esc-pos = "0.2.0"Register it in your Tauri app setup:
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_esc_pos::init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}JavaScript
Install the JavaScript bindings:
npm install @kosadchiy/plugin-esc-posimport {
listPrinters,
openDrawer,
print,
printAndOpenDrawer,
} from "@kosadchiy/plugin-esc-pos"Permissions
The plugin ships with these permissions:
esc-pos:allow-printesc-pos:allow-print-and-open-draweresc-pos:allow-list-printersesc-pos:allow-open-drawer
API Reference
Types
type PrinterTarget =
| { type: "usb"; printerId: string }
| { type: "tcp"; address: string; port?: number }
interface PrintRequest {
target: PrinterTarget
receipt: string
paperWidth?: 58 | 80
encoding?: PrintEncoding
}
type PrintEncoding =
| "utf8"
| "pc437"
| "pc737"
| "pc850"
| "pc852"
| "pc855"
| "pc857"
| "pc858"
| "pc860"
| "pc861"
| "pc862"
| "pc863"
| "pc865"
| "pc866"
| "pc869"
| "wpc775"
| "iso8859_2"
| "iso8859_7"
| "iso8859_15"
| "wpc1250"
| "wpc1251"
| "wpc1252"
| "wpc1253"
| "wpc1254"
| "wpc1257"
interface OpenDrawerRequest {
target: PrinterTarget
}
interface PrinterInfo {
id: string
connection: "usb"
manufacturerName?: string
productName?: string
vendorId?: string
productId?: string
}listPrinters(): Promise<PrinterInfo[]>
Returns detected USB printers.
Behavior:
- Desktop: scans USB printers via
nusb - Android: scans USB printers via native Android USB APIs
- iOS: returns an empty list
Example:
const printers = await listPrinters()
for (const printer of printers) {
console.log(printer.id, printer.productName)
}print(request: PrintRequest): Promise<void>
Prints a receipt to the selected target.
Fields:
target: printer connection targetreceipt: receipt markup stringpaperWidth: optional paper width in millimeters,58or80encoding: optional text encoding/code page, seePrintEncoding
Defaults:
- If
paperWidthis omitted, the plugin uses58 - If
encodingis omitted, the plugin uses"utf8"
Encoding notes:
- Many ESC/POS printers do not support UTF-8 text mode.
- For Russian/Cyrillic receipt text, try
"pc866"first, then"pc855"or"wpc1251"depending on the printer's supported code pages. - For Western Europe try
"pc850","pc858","wpc1252", or"iso8859_15". - For Central/Eastern Europe try
"pc852","wpc1250", or"iso8859_2". - For Greek try
"pc737","pc869","wpc1253", or"iso8859_7". - For Turkish try
"pc857"or"wpc1254". - For Hebrew try
"pc862". - For Baltic text try
"wpc775"or"wpc1257". - The selected encoding must match a code page supported by the printer firmware.
Example:
await print({
target: { type: "usb", printerId: "1155:22336" },
paperWidth: 80,
encoding: "pc866",
receipt: "[C]<b>Hello</b>\n[L]Coffee[R]3.50",
})printAndOpenDrawer(request: PrintRequest): Promise<void>
Prints a receipt and opens the cash drawer as part of the same operation.
Use this when the drawer opening should be coupled to the print job.
Example:
await printAndOpenDrawer({
target: { type: "tcp", address: "192.168.1.50", port: 9100 },
paperWidth: 80,
receipt: "[C]Paid\n[R]Total:[R]12.49",
})openDrawer(request: OpenDrawerRequest): Promise<void>
Opens the cash drawer without printing a receipt.
Example:
await openDrawer({
target: { type: "tcp", address: "192.168.1.50", port: 9100 },
})Targets
USB Target
const target: PrinterTarget = { type: "usb", printerId: "1155:22336" }Notes:
printerIdis the USB identifier returned bylistPrinters()- USB is supported on desktop and Android only
TCP Target
const target: PrinterTarget = {
type: "tcp",
address: "192.168.1.50",
port: 9100,
}Notes:
portdefaults to9100- TCP is supported on desktop, Android, and iOS
Receipt Format
The receipt field is a plain string with line-based markup.
Each line is printed in order. Use \n to create a new line.
Basic example:
[C]Northline Coffee
[L]Americano[R]3.50
[L]Croissant[R]2.80
[R]Total:[R]6.30Special elements such as barcodes, QR codes, and images should be placed on their own line.
Alignment Tags
Use these tags at the beginning of a segment:
[L]left aligned[C]centered[R]right aligned
Example:
[L]Item[R]Qty[R]Total
[L]Flat White[R]2[R]7.00
[R]Total:[R]7.00You can combine multiple aligned segments in the same line:
[L]Order:[R]A-1024
[L]Date:[R]2026-04-26 12:40Universal API
If you want one receipt template that works across desktop, Android, and iOS, treat this subset as the portable API.
Portable commands:
print()printAndOpenDrawer()openDrawer()
Portable target:
- TCP:
{ type: "tcp", address: string, port?: number }
Portable receipt markup:
- alignment tags:
[L],[C],[R] - inline tags:
<b>...</b>,<u>...</u>,<font size="big">...</font> - QR code:
<qrcode>...</qrcode>
Portable text encoding:
encoding: "utf8"is the default- Common ESC/POS presets include
pc437,pc850,pc852,pc858,pc866,wpc1252, and regional DOS/Windows/ISO code pages listed inPrintEncoding
Portable receipt example:
[C]<b>Northline Coffee</b>
[C]<u><font size="big">RECEIPT</font></u>
[L]Order:[R]A-1024
[L]Date:[R]2026-04-26 12:40
[L]<b>Item</b>[R]<b>Qty</b>[R]<b>Total</b>
[L]Flat White[R]2[R]7.00
[L]Brownie[R]1[R]3.50
[R]<b>Total:</b>[R]<b>12.49</b>
[C]<qrcode>https://example.com/order/A-1024</qrcode>Demo app receipt example:
This is the larger default receipt used in examples/tauri-app/src/App.svelte.
[C]Northline Coffee
[C]23 Makarious III Ave
[C]Limassol 4000
[C]--------------------------------
[C]<u><font size="big">RECEIPT</font></u>
[C]--------------------------------
[L]Order:[R]A-1024
[L]Date:[R]2026-04-26 12:40
[C]--------------------------------
[L]<b>Item</b>[R]<b>Qty</b>[R]<b>Total</b>
[L]Flat White[R]2[R]7.00
[L]Brownie[R]1[R]3.50
[C]--------------------------------
[R]Subtotal:[R]10.50
[R]Tax:[R]1.99
[R]<b>Total:</b>[R]<b>12.49</b>
[C]--------------------------------
[C]Thank you
[L]
[C]<qrcode>https://example.com/order/A-1024</qrcode>
[C]<barcode type="ean13">831254784551</barcode>
[L]
[L]
[L]Platform Differences
Android:
- Android still uses the ESCPOS-ThermalPrinter-Android connection helpers for USB discovery and transport.
iOS:
- Due to iOS platform limitations, printing is available only over TCP.
Error Behavior
Typical validation and runtime errors include:
Missing printerId for USB targetMissing TCP address for TCP targetInvalid target: expected USB targetInvalid target: expected TCP targetPrinter not foundConnection failed: ...
Examples
Print to first discovered USB printer
const printers = await listPrinters()
if (!printers.length) {
throw new Error("No USB printers found")
}
await print({
target: { type: "usb", printerId: printers[0].id },
paperWidth: 80,
receipt: `
[C]<b>Northline Coffee</b>
[L]Americano[R]3.50
[R]Total:[R]3.50
`.trim(),
})Print over TCP
await print({
target: { type: "tcp", address: "192.168.1.50", port: 9100 },
paperWidth: 58,
receipt: `
[C]KITCHEN TICKET
[L]2x Burger
[L]1x Fries
`.trim(),
})Open the drawer over TCP
await openDrawer({
target: { type: "tcp", address: "192.168.1.50" },
})TODO
- Add image printing support
