Stripy Horse
Stripy Horse

← All guides

How to test ZPL without a Zebra printer

Zebra printers have no screen, no preview, and no test mode. The traditional way to test a label is to print it, walk to the printer, and squint — which is why label bugs ship to production more than any other kind of output bug. Two better ways:

1. Render the ZPL to an image

Paste ZPL into the free viewer and get a pixel-true PNG at exact label size and density — what you see is what the printhead does. Or from code:

curl https://api.stripyhorse.io/v1/render.png \
  -H "X-Api-Key: sh_live_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"zpl":"^XA^FO50,50^A0N,45,45^FDHello^FS^XZ","preset":"4x6"}' -o label.png

Rendering answers "what does this ZPL look like?" — but it doesn't test the thing that actually breaks in production: your system's printing pipeline.

2. Point your code at a virtual Zebra printer

Real label bugs live in the integration: the template variables your WMS fills in, the bytes your print service actually sends, the ~HS status polling, the reconnect logic when the printer jams. To test those you need something that behaves like a printer, not an image converter.

A virtual Zebra printer is a hosted endpoint that speaks the printer's own protocols:

Try it right now against the public demo printer, no signup:

printf '^XA^FO50,50^A0N,45,45^FDhello from my terminal^FS^XZ' | nc -q1 print.stripyhorse.io 9100

Testing label printing in CI

This is where virtual printers earn their keep. The pattern:

  1. Your pipeline creates a printer via the API and gets a TCP address.
  2. Your fulfillment code runs against that address, exactly as in production.
  3. The test asserts on captured jobs — and fails the build if a template change broke a label.
sim = SimulatorApi(client)
printer = sim.create_printer(CreatePrinterInputBody(name="ci-run", preset="4x6"))

run_fulfillment_against(f"{printer.tcp.host}:{printer.tcp.port}")

jobs = sim.list_jobs(printer.id)
assert len(jobs.jobs) == 1
assert jobs.jobs[0].status == "rendered"

Golden-diff the rendered PNGs and a one-pixel barcode regression fails in CI instead of on the dock. You can also inject faults — paper out, head open, paused — and watch jobs hold in the receive buffer, then flush on clear: the failure modes you can never trigger politely on production hardware.

FAQ

Is there a free ZPL viewer online?

Yes — stripyhorse.io/tools/zpl-viewer renders multi-label streams at 6–24 dpmm with rotation, free, no signup. Labelary is the long-standing alternative; ours adds exact label-size presets and the virtual-printer integration.

Can I run a Zebra emulator locally?

Zebra's own ZebraDesigner has no emulator, and hobby emulators cover fragments of ZPL. The practical options are a rendering engine (this site's is open-source-derived and cross-validated on thousands of carrier labels) or a hosted virtual printer with the TCP/status behavior included.

Does the virtual printer support ^XA…^XZ framing quirks?

Yes — partial frames buffer until complete, multiple labels per connection work, and leftovers flush on disconnect, matching real firmware behavior.

Stripy Horse is the developer platform for Zebra printing — convert PDFs and images, design labels in HTML, preview ZPL pixel-true, and test against virtual printers in CI. Join the early access or try the free tools.

Published 2026-08-24 · Ben Faerber — software engineer, five years building warehouse fulfillment and label-printing systems; maintainer of pdf-to-zpl (26,000+ installs powering production label generation).