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

@fctc/usb-printer-drawer-capacitor

v1.3.5

Published

USB Printer and Cash Drawer plugin for Capacitor Android

Readme

🖨️ Capacitor USB Printer Plugin

A Capacitor plugin that allows Android apps to print receipts or images directly to a USB thermal printer using the ESC/POS command set.
Supports both PNG/JPEG and SVG (base64) formats.


📦 Installation

npm i @atomsolution/usb-printer-capacitor
npx cap sync

⚙️ Android Setup

This plugin depends on the DantSu ESC/POS Thermal Printer library, distributed via JitPack.
Add this line to your root android/build.gradle file:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

💡 Usually located at android/build.gradle (not inside app/).


🚀 Usage

1. Import the Plugin

import { UsbPrinter } from "@atomsolution/usb-printer-capacitor";

2. Connect to the USB Printer

async function connectPrinter() {
  try {
    await UsbPrinter.connect();
    console.log('✅ Connected to USB printer');
  } catch (err) {
    console.error('❌ Failed to connect:', err);
  }
}

3. Print Text

await UsbPrinter.printText({
  text: 'Hello from Capacitor USB Printer ✅\n\n',
});

4. Print Base64 Image (PNG / JPG / SVG)

You can print base64-encoded images (including SVG):

await UsbPrinter.printBase64({
  data: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...',
});

or:

await UsbPrinter.printBase64({
  data: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDov...',
});

5. Print Labels (die-cut decal) — TSPL/TSPL2

Thermal label printers (Xprinter XP-365B, TSC, Godex…) must not be driven with ESC/POS. ESC/POS is a continuous-roll protocol with no notion of where a label starts, so on die-cut decal the content drifts further down with every print and eventually spills onto the next label. TSPL declares SIZE + GAP, so the printer uses its gap sensor to re-align to the top edge of each label.

One-time preparation per label roll: calibrate the gap sensor (power off → hold FEED → power on, keep holding until the printer ejects a few labels and stops at an edge). Measure 10 labels in a row and divide by 10 to get accurate label height + gap.

Vietnamese / any non-ASCII text — render the label to an image and send it as a TSPL bitmap. TSPL's built-in TEXT fonts have no diacritic glyphs:

await UsbPrinter.printLabelTo({
  role: 'label',
  data: pngBase64,     // ảnh render sẵn của con tem
  widthMM: 50,         // đo trên tem thật
  heightMM: 30,
  gapMM: 2,
  marginMM: 1.5,       // lề an toàn
  copies: 1,
});

The image is scaled (aspect preserved) to fit inside the label box, so it can never bleed onto the next label.

ASCII-only content — build TSPL commands and send them raw:

import { UsbPrinter, TsplLabel, mm } from "@atomsolution/usb-printer-capacitor";

const label = new TsplLabel({ widthMM: 50, heightMM: 30, gapMM: 2 })
  .text(mm(2), mm(2), 'SP001', { font: '3' })
  .barcode(mm(2), mm(9), '8935001234567', { height: mm(12) });

await UsbPrinter.printRawTo({ role: 'label', text: label.build() });

Coordinates are in dots, origin (0,0) = top-left of that label. At 203 DPI, 8 dot = 1 mm, so a 50×30mm label is 400×240 dot. build() throws if an element would run past the label edge — the printer silently clips the overflow instead of reporting it, so this is caught in code rather than by burning through a roll of labels.

Fine-tuning when the position is still off:

| Symptom | Fix | |---------|-----| | Off by a constant few mm | offsetMM | | Content needs to move down | shiftDots, or referenceYMM | | Off by a random amount each print | Gap sensor not calibrated | | Labels have a black-printed backing | Use blineMM (black mark) instead of gapMM | | Output is a negative image | invert: true |

printRawTo() is a plain byte passthrough, so it also carries ZPL or CPCL if the printer speaks those instead.


💡 Example React + Capacitor App

Here’s a simple example UI you can include in your React app (e.g. src/App.tsx) to test connection and printing:

import React, { useState } from 'react';
import { UsbPrinter } from "@atomsolution/usb-printer-capacitor";

function App() {
  const [status, setStatus] = useState('Not connected');

  const connect = async () => {
    try {
      await UsbPrinter.connect();
      setStatus('✅ Connected');
    } catch (e) {
      setStatus('❌ Connection failed');
    }
  };

  const printText = async () => {
    try {
      await UsbPrinter.printText({ text: 'Hello World!\nFrom Capacitor 🖨️' });
      alert('Printed successfully!');
    } catch (e) {
      alert('Print failed: ' + e);
    }
  };

  const printImage = async () => {
    try {
      const base64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...'; // your image
      await UsbPrinter.printBase64({ data: base64 });
      alert('Image printed!');
    } catch (e) {
      alert('Print failed: ' + e);
    }
  };

  return (
    <div style={{ padding: 20, fontFamily: 'sans-serif' }}>
      <h2>🖨️ Capacitor USB Printer Demo</h2>
      <p>Status: {status}</p>
      <button onClick={connect}>Connect Printer</button>
      <button onClick={printText}>Print Text</button>
      <button onClick={printImage}>Print Image</button>
    </div>
  );
}

export default App;

💡 You can run this with npm start and test on your connected Android device via npx cap open android.


🧾 Supported Printers

Tested with:

  • XPrinter XP-N160I / XP-58 / XP-80
  • Rongta RP80
  • Zjiang ZJ-5890 / ZJ-80
  • Any printer supporting ESC/POS USB

⚙️ Printer Configuration

| Setting | Default | Description | |----------|----------|-------------| | DPI | 203 | Printer resolution | | Paper Width | 72f mm | Physical paper width | | Printable Width | auto-calculated | Fitted to printer width | | Output | Monochrome | Dithered bitmap for better contrast |


🧠 Notes

  • Works on Android 5.0 (Lollipop) and above.
  • Requires USB Host mode on the device.
  • Automatically asks for USB permission.
  • Supports PNG, JPEG, and SVG base64 formats.
  • Automatically scales and pads width to prevent skew or cutoff.

🧰 Troubleshooting

| Issue | Possible Fix | |--------|----------------| | Printer not connected | Ensure printer is powered on and permission granted | | Failed to decode image data | Verify correct base64 prefix | | Image shifted or cropped | Adjust paperWidthMM in plugin | | Faint output | Use higher contrast or adjust printer density |


🧑‍💻 Development

If you’re building the plugin locally:

# Inside plugin folder
npm run build

# Link with your Capacitor app
npx cap sync android

Then open the Android Studio project:

npx cap open android

📜 License

MIT License © 2025


❤️ Credits