Guides › Printing ZPL from a browser

Printing ZPL from a browser

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.

Why the direct approach cannot 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.

Pattern 1 — the server relays

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.

Pattern 2 — a local helper on the operator's machine

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.

Pattern 3 — render, then use the browser's print dialog

Convert the ZPL to an image or PDF, show it, and let the operator print through the normal driver. No sockets involved.

Whatever you choose, look at the label first

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.

Frequently asked questions

Can JavaScript send ZPL directly to a printer?

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.

How do web apps print ZPL then?

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).

Related guides

What is ZPL?

ZPL is the language Zebra thermal printers understand. How to read the commands, how a label is put together, and the most common mistakes.

Which barcode symbology should I use?

EAN-13, Code 128 or QR? Practical rules for picking a barcode based on your data, your space and the scanner that has to read it.

How to preview a ZPL file without a printer

A ZPL file is just text — the label only exists once something draws it. Three practical ways to see a ZPL label before it reaches the printer.

Try your own ZPL code →