Guides › ZPL special characters print wrong

ZPL special characters print wrong

Published:

Health report

Ö becomes Ö, ü becomes ü, a Turkish ş turns into two junk symbols. The data is right in your system, right in the file — and wrong on the label. This is not corruption; it is two sides decoding the same bytes with different tables.

What actually happens to the bytes

Modern systems write text as UTF-8, where Ö is two bytes. A Zebra printer without instructions decodes ^FD data with its default legacy code page, where every byte is one character — so those two bytes print as two wrong characters. The signature is exact: each accented letter becomes a two-character pair, and plain ASCII around it stays perfect.

The fix: declare UTF-8 with ^CI28

Put ^CI28 once near the top of the format, before the first ^FD. It tells the printer to decode field data as UTF-8 — the same assumption your system already makes. Any other numeric ^CI value selects a single-byte legacy table and only remaps a handful of positions; for real multilingual text, 28 is the value that matches what you send.

^XA
^CI28
^FO50,50^A0N,40,40^FDGüteschließung — Ölçüm^FS
^XZ

Why the preview can look right while the printer is wrong

An honest detail about testing this on screen: a browser preview (ours included) assumes UTF-8 throughout, so a file without ^CI28 can render perfectly in the preview and still garble on a printer whose default is a legacy page. The structural check therefore warns when a numeric ^CI other than 28 is present; the absence of ^CI28 is the thing to check by eye before sending multilingual text to hardware.

Second layer: the font must have the glyph

Encoding delivers the right character code; the font must then contain the character's shape. Built-in printer fonts cover Latin scripts well but not everything. When a correctly encoded character prints as a blank or a box, load a TTF that contains the glyph (~DU) and call it with ^A@ — the label then carries its own font instead of hoping the printer has one.

Control characters: ^FH

For bytes you cannot type — or when an integration mangles raw high-bit bytes in transit — ^FH switches the field to hex escapes: ^FH^FD_C3_96^FS prints Ö by value. It is the robust path for generated files where an intermediate system cannot be trusted to preserve UTF-8 bytes.

Frequently asked questions

Why do umlauts and accents print as two junk characters?

Your system sends UTF-8, where an accented letter is two bytes; a printer without instructions decodes them with a one-byte legacy code page and prints two wrong characters. Add ^CI28 near the top of the format, before the first ^FD.

Why does the label look right in the preview but wrong on the printer?

A browser preview assumes UTF-8 throughout, so a file without ^CI28 can render perfectly on screen and still garble on hardware whose default is a legacy code page. Check for ^CI28 before sending multilingual text to a printer.

^CI28 is set but a character still prints as a box — why?

Encoding delivers the character code; the font must contain its shape. Load a TTF with the glyph via ~DU and call it with ^A@, so the label carries its own font instead of relying on the printer's built-ins.

Related guides

What is ZPL?

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 printer

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

Try your own ZPL code →