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