Designing Zebra (ZPL) labels¶
Zebra label printers do not understand normal documents. Instead, they read a small set of text commands called ZPL (Zebra Programming Language). A ZPL design is just a block of text that tells the printer what to put on the label and where: a line of text here, a price there, a QR code in the corner.
This page explains ZPL from scratch so you can read, edit, and build your own product labels without help. You design your label under , in the Custom Zebra product label design field (see Printer configuration).
Tip
You rarely start from a blank page. Gem Logic gives every label a working default design. The fastest way to learn is to open that default, change one thing, save, and look at the preview image. Repeat until it looks right.
Quick start¶
Go to and find the Custom Zebra product label design field.
Make a small change (for example, move a line or make the price bigger).
Click Save. Gem Logic automatically generates a preview image of the label.
Look at the preview. If it is wrong, adjust and save again.
Nothing is sent to a real printer while you experiment — the preview is generated from your design, so you can iterate safely before printing a single label.
How a ZPL label is built¶
Every label starts with ^XA and ends with ^XZ. Everything in between describes the label.
A command always begins with a caret ^ (or sometimes a tilde ~).
^XA (start of the label)
... commands that build the label ...
^XZ (end of the label)
Inside, the most common pattern is “go to a position, then print something there”:
^FO50,30^FDHello^FS
That single line means: go to position 50,30 and print the text “Hello”. Broken down:
^FO50,30— Field Origin: move to x=50, y=30 (the top-left corner of what comes next).^FDHello— Field Data: the actual content to print.^FS— Field Separator: marks the end of this piece. Always close a field with^FS.
That is 90% of label design: a series of “position + content” lines stacked together.
Label size, dots and millimetres¶
Zebra printers measure everything in dots, not millimetres. Most label printers print at 203 DPI, which means:
1 mm ≈ 8 dots
1 inch = 203 dots
So a label that is 56 mm wide and 13 mm tall is about 448 dots wide and 104 dots tall.
Two commands set the printable area:
^PW— Print Width, in dots.^LL— Label Length (height), in dots.
^PW448 (label is 448 dots wide ≈ 56 mm)
^LL104 (label is 104 dots tall ≈ 13 mm)
Important
The physical label size also comes from the Product label width and
Product label length fields next to the design. Keep those in sync with your
actual label stock. The {label_length} variable is filled in automatically from the length
field, which is why the default design uses ^LL{label_length}.
Positioning: the coordinate grid¶
Think of the label as a grid. The point 0,0 is the top-left corner. The first number is
x (how far right) and the second is y (how far down), both in dots.
^FO0,0 top-left corner
^FO200,0 200 dots to the right, same height
^FO0,40 left edge, 40 dots down
To move an element, change its ^FO numbers. Bigger x = further right; bigger y = further
down. This is how you put the SKU on one line and the metal on the next: give them the same x but
a larger y on the second line.
Adding and sizing text¶
Before printing text you usually choose a font size. The simplest way is ^CF0,h (Change
default Font), where h is the character height in dots:
^CF0,28 use ~28-dot-tall text from here on
^FO50,30^FDPrice^FS print "Price" at 50,30 in that size
Every ^FD ... ^FS after a ^CF uses that size until you set a different one. So to mix
sizes on one label, set ^CF0,28 before the big text and ^CF0,14 before the small text.
Tip
To add a new line of text, you do not press Enter — you add another positioned field
lower down. Copy an existing line, give it a larger y value, and change its content.
Inserting product data¶
A label design is reused for every product, so you do not type the SKU or price by hand. Instead you insert variables in curly braces, and Gem Logic replaces them with each product’s real data when the label prints.
^FO1,8^FD{item_sku}^FS prints this product's SKU
^FO180,50^FD{currency}{price}^FS prints e.g. €129
The same variables are shown as clickable badges directly under the design field in the app, so you can see which ones are available while you edit.
Available variables¶
Product
{brand}: brand name{product_title}: product title{item_sku}: product SKU{ean_code}: EAN barcode (used for the QR code){price}and{currency}: price and currency symbol{serial_number}: serial number{year_of_manufacture}: year of manufacture{supplier_product_reference}: supplier’s product reference{supplier_reference}: supplier reference
Materials and gems
{material_1}to{material_5}: full material description (weight, name, and gem details){material_only_1}to{material_only_5}: material or gem name only
Attributes
{attribute_1}to{attribute_5}: attribute asname: value{attribute_name_1}to{attribute_name_5}: attribute name only{attribute_value_1}to{attribute_value_5}: attribute value only
Dimensions
{weight},{length},{width},{height},{diameter},{size},{thickness},{quality}
Collections
{collections}: the collections the product belongs to
Cost code
{encoded_cost}: the purchase cost converted into your private cost code (the letters are set under ), so the real cost is not readable on the label.
RFID (only needed for labels with RFID tags)
{item_sku_epc_hex}: the SKU encoded as an EPC value for the RFID chip{item_sku_epc_word_count}: the EPC length, used by the ZPL RFID command
Layout
{label_length}: filled in automatically from the label length setting
QR codes and barcodes¶
A QR code is added with ^BQN followed by a data field that starts with QA,:
^FO0,30^BQN,2,2^FDQA,{ean_code}^FS
^FO0,30— where the QR code goes.^BQN,2,2— a QR code. The last number is the size (magnification). Raise it (3, 4, 5…) for a bigger, easier-to-scan code; lower it to save space.^FDQA,{ean_code}^FS— the data inside the code. Here it encodes the product’s EAN.
For a classic 1D barcode instead, use ^BCN (Code 128):
^FO20,20^BCN,60,Y,N,N^FD{ean_code}^FS
The 60 is the barcode height in dots, and Y prints the human-readable number underneath.
The default design, explained¶
This is the starting design Gem Logic gives you, annotated line by line. Reading it is the quickest way to understand how the pieces fit together.
^XA start of label
^CI28 character encoding (so € and accents print)
^PW540 print width in dots
^LL{label_length} label height (from the length setting)
^LH0,0 origin = top-left corner
^CF0,18 text size ~18 dots
^FO180,8^FD{brand}^FS brand, near the top
^CF0,14 smaller text from here
^FO50,45^FD{material_2}^FS second material
^FO50,60^FD{material_3}^FS third material
^FO180,27^FD{material_1}^FS first material
^CF0,28 larger text for the price
^FO180,50^FD{currency}{price}^FS price, e.g. €129
^CF0,16 medium text
^FO1,8^FD{item_sku}^FS SKU, top-left
^FO1,23^FD{supplier_product_reference}^FS
^FO50,60^FD{supplier_reference}^FS
^FO0,30^BQN,2,2 QR code, lower-left
^FDQA,{ean_code}^FS QR contents = EAN
^XZ end of label
Note
The text after a semicolon ; on a line is a comment for humans — the printer ignores it.
You can add your own notes the same way.
Common changes¶
- Make the price bigger
Find the
^CF0,28before the{price}line and increase the number, e.g.^CF0,40.- Move something
Change its
^FOnumbers. To shift the brand down, increase the second number in^FO180,8(the8).- Add a new line of text
Copy a
^FO…^FD…^FSline, give it a largeryvalue so it sits lower, and change the content or variable.- Make the QR code bigger
Increase the last number in
^BQN,2,2(try^BQN,3,3). If it gets cut off, give it more room or move it left/up with its^FO.- Add a separator line
Use a graphic box.
^FO0,40^GB540,2,2^FSdraws a thin horizontal line 540 dots wide.
Preview and test before printing¶
You have two easy ways to check a design before using real labels:
In Gem Logic: every time you save, a preview image of the label appears under the design field. Use it as your main feedback loop.
Online: paste your ZPL into the free Labelary viewer to see an instant render at different label sizes. (Replace the
{variables}with sample text first, since Labelary does not know your product data.)
If a real label looks wrong — clipped text, a QR that will not scan, wrong size — see the label section of Troubleshooting.
Command quick reference¶
Command |
What it does |
|---|---|
|
Start / end of the label. Everything lives between them. |
|
Print width in dots. |
|
Label length (height) in dots. |
|
Label home — the origin point (usually |
|
Field origin — position the next element at x,y. |
|
Set the default font height ( |
|
Field data — the content to print — closed by a field separator. |
|
QR code; the last number is the size. Data starts with |
|
Code 128 barcode; |
|
Draw a box or line (width, height, thickness in dots). |
|
Character encoding, so symbols like |
For the complete language, Zebra publishes a full ZPL command guide, but the commands above cover almost every product label.