Sign In
Products
ZPL ViewerBarcode GeneratorImage → ZPLZPL cheat sheetLabel DesignerTemplate Gallery
Developers
API QuickstartAPI ReferenceMCP ServerBulk GenerationWebhooksSDKs & ExamplesLimitsDirectPrint agent NewGitHub ActionVS Code extensionOn-Premise
Solutions
Logistics & ShippingE-CommerceERP & WMSManufacturingRetailHealthcare & LaboratoryAll solutions
Tools
ZPL Diagnostics HubZPL DebuggerSize & DPI AnalyzerDPI ConverterBarcode fit calculatorShipping Label AnalyzerFont InspectorOrientation DebuggerCalibration AssistantPrinter Compatibility CheckerBarcode Readability CheckerPrinter Language DetectorThermal Printer Test PackZPL ToolsEPL ToolsTSPL ToolsCPCL ToolsPrinter Language ConverterAll ToolsGuidesPricing
Language
EnglishTürkçeDeutsch
Home›Guides›ZPL special characters print wrong

ZPL special characters print wrong

Published: · Updated:

Paste your code

Paste code or load the sample — the result appears below, with the line and severity of each finding.

Result

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

Open this label in the ZPL viewer →

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.

Third layer: the driver and the toolchain

When ^CI28 is in the file and the font has the glyph, the character can still die between your program and the head. Three places to look, in the order they are usually found:

Related lint rule

The preview assumes UTF-8, so the screen can look right while the paper is wrong. Our linter flags non-ASCII text in a label that has no ^CI command at all: rule ZPL5004 shows an example and the fix.

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.

I added ^CI28 and still get question marks — why?

Three usual reasons: the job goes through a generic Windows driver that does not pass ^CI through (send the ZPL raw or use ^FH hex escapes); the text still calls font 0 while the downloaded font was assigned another letter with ^CW; or the file was saved as ANSI/Windows-1254 instead of UTF-8.

Related guides

The printer prints gibberish

Raw text and control characters instead of a label point to dump mode; truly scrambled glyphs point to a language mismatch. Telling them apart takes a minute.

Only the last graphic prints

A format with several ^GB boxes prints only the final one on a mobile printer. The file is usually innocent: check the active printer language first.

Every label in the job prints the same time (^FC, ^SL)

A multi-label ZPL job stamps every label with the same clock value. That is ^SL's documented default, not a bug — and ^SLT changes it.

Zebra prints an extra blank label

A blank label after every print, a skipped or half-printed label: two causes in the ZPL (^LL, ^PQ), two in the printer, one in the driver. Check in that order.

Try your own ZPL code →