Receipt Printers 101

Receipt printers are a complicated subject because of many variables. There are many different types of printers and ways to connect them, but this article will help you navigate most pitfalls.

The answers and suggestions in this article are all based on my libraries, which are open-source and freely available for anyone to use and experiment with. They are all part of the same family and work together, but of course you can also pick and choose some individual components.

Now I am not going to explain how these libraries are used, they have proper documentation. Also in the future I will write some more detailed articles about how these libraries will work together with some example code. So watch this space!

Dealing with printer languages

First, receipt printers usually accept text-based input but offer some basic formatting using escape codes. The most popular language used by receipt printers is ESC/POS, which dates back to the 1980s. This language was invented by Epson, and most printers nowadays are compatible—although not every printer supports every feature.

There is one big exception: Star printers use the language StarPRNT by default, which uses the same concept, except it uses an entirely different set of escape codes. So, it is not compatible by default, although you can manually turn on ESC/POS compatibility mode by changing software settings or configuring the printer using dip switches.

If you want to talk to a receipt printer, you can use ThermalPrinterEncoder. You can use this library to write a receipt, add text, set text styles, add tables and even insert barcodes, QR codes and images. 

Under the hood, this library uses EscPosEncoder and StarPrntEncoder, so it is compatible with both languages. 

What you end up with is an array of bytes. These bytes represent the receipt you want to print, and you need to send those bytes to the printer. 


Sending data to the printer

This is the part where it gets complicated. Receipt printers can use many interfaces, such as USB, Serial, or Network. Some printers may also support Bluetooth Low Energy for mobile use, and some support multiple interfaces simultaneously.

There is also a difference between printing from the browser and using a server to share the ability to print to multiple clients.

Printing straight from the browser

You can print directly from the browser. However, you need a Chromium-based browser because, depending on how the printer is connected to your computer, you need APIs like WebUSB, WebSerial, and WebBluetooth. 

You can use WebUSB for USB-connected devices on Linux and macOS but not Windows because the printer driver exclusively claims the device for private use. Luckily, most Windows printer drivers can create a virtual serial port for backward compatibility.

If you want to print from the browser to a USB-connected receipt printer, you can use WebUSBReceiptPrinter

You can use WebSerialReceiptPrinter to print to a serial port-connected browser or when the driver creates a virtual serial port. Of course, computers do not have any real serial ports anymore, but this also applies to printers connected to a USB-to-Serial dongle.

Finally, when you want to use Bluetooth Low Energy, you can use WebBluetoothReceiptPrinter. But this is only for Bluetooth Low Energy devices—if your printer supports only Bluetooth Classic, you will need to manually add it to your system using the operating system’s Bluetooth stack, after which it will create a virtual serial port.

You cannot use network printers from the browser due to security issues with opening raw network sockets.

Printing from the server

If you use Node on a server, there are other options, but they are more limited. I’ve yet to work on USB, Serial, or Bluetooth, but connecting these printers is certainly possible. 

However, if you want to print on a network printer, you can use the library NetworkReceiptPrinter

Those who do not want to talk directly to the printer but use the system printer driver instead can use SystemReceiptPrinter. This library abstracts away the whole connection method. As long as there is a printer driver, it will just send the data to the printer no matter how it is connected. 


Status information from the printer

Some receipt printers do not only allow you to send data, but they will also give back status information. For example, you can tell whether or not the printer is out of paper or the paper is jammed.

Most printers also support connecting a cash drawer to the printer and using a command to open it automatically. You can also query the cash drawer’s status to see if it is opened or closed.

Finally, some printers support connecting a barcode scanner directly to the printer. You can query the printer for the last scanned barcode.

All of this is possible with ThermalPrinterStatus.

Once you have established a connection with the printer, you can use this library to query for information and get events for status updates. All of the libraries mentioned above work with ThermalPrinterStatus—except for SystemReceiptPrinter—as it requires two-way communication, and printer drivers only support printing to the printer. 


TL;DR

You need ThermalPrinterEncoder to encode your receipts. 

You need ThermalPrinterStatus to get back status information from the printer. 

You need one of these libraries to facilitate communication to and from the printer: WebUSBReceiptPrinter, WebSerialReceiptPrinter, WebBluetoothReceiptPrinter, NetworkReceiptPrinter, or SystemReceiptPrinter