Stripy Horse
Stripy Horse

← All guides

How to print Arabic and Russian on Zebra printers

Send a Zebra printer ZPL containing Arabic and you get disconnected letter shapes in the wrong order. Send it Russian and you usually get blanks or mojibake. This guide explains why, and the fix that doesn't sacrifice your barcodes.

Why Zebra printers fail at Arabic and Cyrillic

  1. No text shaping. Arabic letters change form depending on their neighbors (contextual joining) and run right-to-left. A Zebra's built-in fonts draw one glyph per character, left to right — structurally incapable of correct Arabic, no matter what encoding you use.
  2. The ^CI encoding minefield. ZPL predates Unicode. Getting even Cyrillic out of a printer means matching ^CI code pages, printer font files, and your bytes exactly — and the failure mode is silent garbage on physical media.
  3. Fonts on the printer. Zebra's resident fonts cover Latin. Anything else means buying and flashing font files to every printer in the fleet, then keeping them in sync.

The fix: selective rasterization

The insight is that you don't need the printer to understand Arabic — you need the pixels to be right. A ^GFA graphic field prints exactly the bitmap you send.

So: parse the ZPL, find the text fields containing characters the printer can't render, shape that text the way a browser would (HarfBuzz shaping — proper joining, RTL, per-script font fallback), rasterize it at printhead resolution, and emit a ^GFA at the field's exact position and size. Everything else passes through byte-for-byte: ASCII text stays native (and crisp at any density), barcodes stay native (and scannable), boxes and graphics untouched.

Before:

^FO50,290^A0N,44,44^FDمحمد الأمين^FS
^FO50,430^BY3^BCN,130,Y,N,N,A^FDRU4055713RIY^FS

After (the Arabic became a positioned bitmap; the barcode is untouched):

^FO50,290^A0N,44,44^GFA,1428,1428,42,,...^FS
^FO50,430^BY3^BCN,130,Y,N,N,A^FDRU4055713RIY^FS

Try it on the free Unicode tool — paste ZPL, get printable ZPL — or from code:

curl https://api.stripyhorse.io/v1/unicode \
  -H "X-Api-Key: sh_live_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"zpl":"^XA^FO50,50^A0N,40,40^FDАлексей Петров^FS^XZ"}'

The response reports how many fields were rasterized and lists any it deliberately left alone (rotated fields and ^FH hex-escaped fields pass through unchanged rather than risk being wrong).

FAQ

Does this work for Hebrew, Greek, Chinese, Japanese?

Hebrew (RTL) and Greek work the same way. CJK works when a font covering those scripts is installed on the converting server — the shaping engine falls back per character.

Why not rasterize the whole label?

Bloat and barcodes. A full-label bitmap is 10–50× more data over the wire and down the print head, and rasterized barcodes lose the module-precision that makes them scan reliably. Selective rasterization keeps native fields native.

Why not load Arabic fonts onto the printer?

You can — Zebra sells Unicode font kits — but you must flash and maintain them on every printer, they still don't fix shaping on older firmware, and your ZPL becomes coupled to fleet state. Rasterization makes the ZPL self-contained: it prints the same on any ZPL-II printer on earth.

Does the text look different from native fonts?

Slightly — rasterized text is anti-aliased to the threshold rather than drawn from the printer's bitmap fonts. At 203 dpi and typical label sizes the difference is cosmetic; the alternative is text that's wrong.

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