Published:
Sooner or later a web application needs to put a label on a thermal printer, and the first attempt is always the same: open a socket to the printer from JavaScript. That is not possible, and understanding why points straight at the patterns that do work.
Raw thermal printing means writing bytes to TCP port 9100. Browsers deliberately provide no API for arbitrary TCP sockets — page JavaScript can speak HTTP, WebSocket and WebRTC, all of which require a cooperating server on the other end. A label printer answering on port 9100 is not such a server: it speaks no HTTP and performs no handshake. The restriction is a security boundary, not a missing feature, so no library works around it.
The browser posts the label to your backend; the backend opens the socket to the printer and forwards the bytes. This is the default answer for warehouse and back-office applications, where printers and servers sit on the same network.
A small program runs next to the browser, listens on localhost, and the page sends the label to it over HTTP; the helper writes to port 9100. This is how most vendor "web printing" tools work, and it is the only pattern that reaches a printer the server cannot see.
Convert the ZPL to an image or PDF, show it, and let the operator print through the normal driver. No sockets involved.
Port 9100 has no undo: the printer starts moving media the moment the job lands. Rendering the job in the browser before sending costs nothing and catches the structural problems — fields outside the label, a missing terminator, a barcode with unencodable data. Paste the job into the ZPL viewer, or call the rendering API from the same backend that will do the sending. The operating-system side of actually delivering bytes is covered in sending ZPL to a network printer.
If your labels are rendered or stored in Labelixa, the DirectPrint agent is the local-helper pattern run for you: a small program on a computer in the printer's network that collects print jobs from the API and hands them to the printer — over the network or through a USB printer's print queue. It opens no inbound port. Download and setup: /download
Printing ZPL to a USB Zebra printer from the cloud
No. Raw thermal printing writes bytes to TCP port 9100, and browsers provide no API for arbitrary TCP sockets — only HTTP, WebSocket and WebRTC, which all need a cooperating server. A printer on port 9100 speaks none of them. It is a security boundary, so no library works around it.
Three patterns: the backend relays the job to port 9100 (needs network reachability), a small local helper listens on localhost and forwards to the printer (needs an install per workstation), or the label is rendered to an image or PDF and printed through the normal driver (no install, but the driver rasterises the barcode).
Set up a raw CUPS queue with lpadmin, send ZPL with lp, and avoid the classic trap: a filtering queue that prints your ZPL code as plain text.
Printing ZPL Without a Printer DriverWhy ZPL needs no driver, three ways to send it raw — direct socket, CUPS raw queue, Windows Generic/Text Only — and when a driver helps.
Printing ZPL to a USB Zebra printer from the cloudA USB label printer has no port 9100. How the operating system's print queue carries raw ZPL, and how the Labelixa agent connects that queue to a cloud API.
How to Send ZPL Directly to a Network PrinterZebra network printers accept raw ZPL on TCP port 9100. How to send a file from Windows, macOS or Linux, from code, and what to check when nothing prints.