Published: · Updated:
| # | Font | Type | H × W (dots) | H × W (mm) | Rotation | Text |
|---|
Zebra's built-in fonts (^A0, ^AD…)
cover most labels. But if you need your brand typeface, or characters outside
the built-in sets, you have to supply the font yourself. ZPL has two commands
for this: ~DU loads a font, ^A@
calls it.
Converting a TrueType font to ZPL produces one enormous line:
~DUR:BRAND.TTF,48213,00010000000A0080...
Three parts: the destination drive and name
(R:BRAND.TTF), the byte count, and the whole font
as hex. The command is the font — a 50 KB font takes
roughly 100 KB in ZPL, because every byte is written as two characters.
Once the font is in place, the field command looks like this:
^XA
~DUR:BRAND.TTF,48213,0001...
^FO50,50^A@N,60,60,R:BRAND.TTF^FDHello^FS
^XZOpen this label in the ZPL viewer →
^A@ takes orientation (N/R/
I/B), height, width and the font path. Omit the path
and the last selected font is used. Give a path for a font that was never
loaded and the text is not drawn — you get a warning instead. A silently empty
field usually goes unnoticed until the label is in someone's hand.
The example above works but does not scale. ~DU travels
inside the label, so using one font across fifty templates means
shipping the same 100 KB hex block fifty times. On every print. Across the
network, through the queue, and through the printer's parser.
Nobody works that way on a real Zebra printer: the font is loaded
once into the printer's R: memory and labels only
call it with ^A@. The label becomes 40 bytes instead of
100 KB.
Labelixa's equivalent is account-level font memory: upload
the font once to /v1/fonts/library, and your labels carry only
^A@. At render time your account's fonts are prepended to the
stream — so your labels are written as if real printer memory existed.
# once: upload the font to your account
curl -X POST https://api.labelixa.com/v1/fonts/library -H "X-API-Key: $KEY" -H "X-Font-Name: BRAND.TTF" -F file=@Brand-Bold.ttf
# from now on, every label is just the call
^XA
^FO50,50^A@N,60,60,R:BRAND.TTF^FDHello^FS
^XZ
If a label still carries its own ~DU, that one wins: the
in-stream font overrides the stored one. This is deliberate — a real printer
behaves the same way, and it gives you an escape hatch when a template must be
independent of account state.
A font carries thousands of glyphs; your label might use fifty. Both
endpoints accept a chars parameter that keeps only the characters
you list. On a label with fixed text this often cuts the file to a tenth.
curl -X POST "https://api.labelixa.com/v1/fonts?chars=ABCDEFGHI0123456789" -H "X-API-Key: $KEY" -F file=@Brand-Bold.ttf
chars up to 2000
characters.A-Z 0-9 . _ -, up to 32
characters; they are upper-cased, and .TTF is appended when there
is no extension. The drive is a single letter and a colon (R:).If the labels go to a real Zebra rather than through an account, the "upload once" path is the printer's own memory. Three details decide whether that works on the first try.
~DY or ~DU.
~DU is the older, TrueType-only download in ASCII hex. Zebra's
current general-purpose download is ~DY, which also carries
graphics and can send the data in binary — half the size on the wire.
ZebraDesigner and Zebra Setup Utilities emit ~DY; most online
converters emit ~DU. Both end up as the same file in printer
memory, and ^A@ calls either.
~DYE:BRAND.TTF,B,T,48213,,<binary data>
^XA^HWE:*.*^XZ ; list the E: drive — is BRAND.TTF there?
E: or R:. E: is flash and survives a power
cycle; R: is DRAM and is cleared when the printer is switched off.
A font sent to R: in the morning is gone after the first
restart — the most common reason a working label starts printing in the
default font a week later. Put permanent fonts on E:; the
^HW directory listing above confirms what is really stored.
^CW: give the font a letter. ^CW binds a
stored font to a single-character identifier, so a template that was written
with the built-in ^A letters can switch
typeface without touching every field:
^XA
^CWQ,E:BRAND.TTF
^FO50,50^AQN,60,60^FDHello^FS
^XZOpen this label in the ZPL viewer →
The identifier must be a single letter A–Z or digit
0–9; a two-character or lowercase identifier is silently ignored
and the field falls back to the default font — the mismatch described in the
special characters
guide. Whichever route you take, pair the font with
^CI28 when the text is UTF-8, otherwise the
glyphs are present but the bytes are decoded as a single-byte code page. The
font inspector reads a TTF and shows
which characters it actually contains before you send it anywhere.
Embed the font when the label has to travel on its own — archived as a file, handed to a third party, or sent to a printer that never goes through your account. Upload it when the same font is used across templates and printed regularly; there the saving repeats on every print.
Two ways: embed the font into every job with ~DU, or upload it once to printer memory and reference it with ^A@. Upload-once wins when many templates share the same font.
It was stored in DRAM (R:), which clears on power-off. Store fonts in flash (E:) so they survive restarts.
Subset it: strip the glyphs you never print. Label fonts rarely need more than a few dozen characters, and subsetting cuts the file size dramatically.
^CW binds a font stored in printer memory to a one-character identifier (^CWQ,E:BRAND.TTF), so fields written with ^AQ use that font. The identifier must be a single letter A-Z or digit 0-9; anything else is ignored and the default font prints.
A label format can switch the printer to thermal transfer — by design. Why ^MT exists, when it helps, and what disabling it costs your fleet.
How to center text in ZPLZPL has no center command for plain text. Use a ^FB block with C justification, or measure the text width and compute the x position yourself.
PDF or ZPL: choosing a label pipelineTwo pipelines for the same label: a rendered PDF through a driver, or native ZPL to the printer. What each costs in speed, fidelity and support.
ZPL dots, millimetres and inchesEvery ZPL coordinate is a dot. Conversion tables for 152/203/300/600 dpi, common label sizes in dots, and what really changes when a 203 dpi file moves to 300.