Based on contributions by ThomasVrakking.
Zebra label printers are programmed with their own markup language, ZPL (Zebra Programming Language). This guide shows how to install a Zebra printer, build a ZPL label with a GS1 barcode from Python, and send it to the printer over USB or Ethernet. The example uses a Zebra R110Xi4, but the same principles apply to other Zebra printers.
What you need
- A Zebra printer (this example: Zebra R110Xi4)
- Zebra printer drivers, from the Zebra support & downloads page (select your printer model)
- Python 3.x with
pywin32(forwin32print) if printing via USB/driver on Windows
Steps
1. Install the drivers
Download the drivers for your exact printer model from the Zebra support page and follow the installation instructions, selecting the correct printer model when prompted.
2. Find the installed printer name
import win32print
for printer in win32print.EnumPrinters(2):
print(printer[2])
If the driver installed correctly, your Zebra printer will appear in this list. Note down its exact name — you’ll need it later to print without specifying a host/IP.
3. Build the ZPL label
ZPL is Zebra’s own markup language describing what to print and where. This example prints a product name, GTIN, expiry date, and batch number, plus a GS1-128 barcode encoding the same data:
ZPL label example
zpl = f"""
^XA
^CF0,40
^FO65,40^FDProduct:^FS
^FO235,40^FD{product_name}^FS
^FO65,80^FDGTIN:^FS
^FO235,80^FD{gtin}^FS
^FO65,120^FDExpiry:^FS
^FO235,120^FD{expiry}^FS
^FO65,160^FDBatch:^FS
^FO235,160^FD{batch}^FS
^BY2,2,80
^FO65,225^BCN,80,Y,N,N
^FD>;>801{gtin}17{expiry}10>6{batch}>8^FS
^XZ
"""
To also write an RFID tag on labels that support it, add this to the ZPL string:
^RS8 ; RFID settings (EPC Gen 2, automatic settings)
^RF5,5,2,1^FD{RFID}^FS ; Write the RFID value (hex/ASCII) to the tag's EPC memory
^WT ; Start writing
Check: the barcode field data string (
^FD>;>801{gtin}17{expiry}10>6{batch}>8^FS) is the GS1-128 encoding used in the original project — verify the application identifiers (01,17,10) and separator characters match your actual GS1 requirements before relying on it in production.
4. Send the label to the printer
Import win32print and socket. For an Ethernet-connected printer, connect by IP (host/port); for a USB/driver-installed printer, use the printer name from step 2:
Function to send ZPL to the printer
import logging
import socket
import win32print
logger = logging.getLogger(__name__)
def send_zpl_to_printer(zpl, host=None, port=9100, printer_name=None):
if host is not None:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, port))
s.sendall(zpl.encode('utf-8'))
except OSError as e:
print(f"Error connecting to the printer over the network: {e}")
else:
if printer_name is None:
printer_name = win32print.GetDefaultPrinter()
hprinter = win32print.OpenPrinter(printer_name)
try:
win32print.StartDocPrinter(hprinter, 1, ("ZPL Label", None, "RAW"))
win32print.StartPagePrinter(hprinter)
win32print.WritePrinter(hprinter, zpl.encode('utf-8'))
win32print.EndPagePrinter(hprinter)
win32print.EndDocPrinter(hprinter)
logger.info("Successfully sent data to printer")
finally:
win32print.ClosePrinter(hprinter)
Call it with either a host (Ethernet) or a printer name (USB):
# Ethernet, port 9100 is the standard Zebra raw-print port
send_zpl_to_printer(zpl, host="192.168.1.50")
# USB / installed driver
send_zpl_to_printer(zpl, printer_name="ZDesigner R110Xi4")
Troubleshooting
- Printer not listed by
win32print.EnumPrinters: the driver isn’t installed correctly, or you selected the wrong model during installation. - Nothing prints over Ethernet: confirm the printer’s IP address and that port 9100 (the standard raw ZPL port) is reachable; check firewalls between your PC and the printer.
- Barcode doesn’t scan correctly: double-check the GS1 application identifiers and field lengths in the ZPL
^FDline against your actual GTIN/expiry/batch format.
Rewritten and consolidated (Sept 2026) from the original student how-to’s: Printing using zebra code.