Published:
ZPL is a printer language: the printer itself renders it. On macOS and Linux the print system is CUPS, and CUPS normally does the opposite of what a ZPL job needs — it runs every job through filters that convert documents into printer commands. Your job already is printer commands, so the queue must pass bytes through untouched. That is what a raw queue does.
If the queue has a driver or filter attached, one of two things
happens: the filter rejects the job, or — the classic symptom — the
printer dutifully prints your ^XA…^XZ source as visible
text on the label. The label is not wrong; the queue treated ZPL as
a document. Nothing in the ZPL can fix that: it is a queue setting.
Both macOS and Linux ship lpadmin:
sudo lpadmin -p zebra-raw -E -v socket://192.168.1.50:9100 -m raw
-p names the queue, -E enables it,
-v is the device URI (here the printer's IP with raw port
9100), and -m raw says: no driver, no filtering. For a USB
printer, find the URI first with lpinfo -v and use the
usb://… line it prints.
Recent CUPS versions print a deprecation warning for raw queues. They still work; the warning is about CUPS's future direction, and the direct-socket alternative below does not depend on CUPS at all.
lp -d zebra-raw label.zpl
If you must use an existing, driver-backed queue, you can ask for
pass-through per job with lp -d zebra -o raw label.zpl —
but a dedicated raw queue is harder to get wrong.
The printer dialogs in System Settings want to pick a driver or
AirPrint — both are for documents, not for raw ZPL, so set the queue up
from the terminal with lpadmin as above. If you prefer a
browser UI, the CUPS web interface is off by default; enable it with
cupsctl WebInterface=yes and open
localhost:631.
lpstat -p lists queues and their state,
lpstat -o lists waiting jobs, cancel -a
clears them. A job that reports "completed" only means CUPS handed the
bytes over — like port 9100 itself, it is not proof the label printed
correctly. Paste the ZPL into the
online viewer before sending: paper
has no undo.
For a one-off job, sending straight to the printer's TCP port 9100 is simpler — no queue to configure; see how to send ZPL to a network printer. What CUPS adds is spooling: named queues, ordering, retries and permissions. If several people or systems share one printer, that layer earns its keep. For the wider driver question — all three raw routes, and when a real driver helps — see printing ZPL without a driver.
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
Because the CUPS queue has a driver or filter attached that treats the ZPL source as a document. Make the queue raw (lpadmin with -m raw) or pass -o raw per job; nothing inside the ZPL itself can fix a queue setting.
No. The printer's own firmware renders ZPL, so the queue only has to pass bytes through untouched — that is exactly what a raw CUPS queue does. A driver is for converting documents, which a ZPL job by definition is not.
Raw queues still work; the warning is about CUPS's future direction. If it ever bites, sending straight to the printer's TCP port 9100 does not depend on CUPS at all and achieves the same pass-through.
A 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.
Printing ZPL from a browserA browser cannot open a socket to port 9100. The three patterns that actually deliver ZPL from a web app, and what each one costs.
Why did my label print on the wrong printer?Labels landing on the wrong printer are an identity problem, not bad luck: queue names, DHCP leases and shared drivers. How to diagnose and stop it.
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.