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 Configuration ‣ Printers, 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

  1. Go to Configuration ‣ Printers and find the Custom Zebra product label design field.

  2. Make a small change (for example, move a line or make the price bigger).

  3. Click Save. Gem Logic automatically generates a preview image of the label.

  4. 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,30Field Origin: move to x=50, y=30 (the top-left corner of what comes next).

  • ^FDHelloField Data: the actual content to print.

  • ^FSField 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:

  • ^PWPrint Width, in dots.

  • ^LLLabel 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 as name: 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 Configuration ‣ General settings), 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,28 before the {price} line and increase the number, e.g. ^CF0,40.

Move something

Change its ^FO numbers. To shift the brand down, increase the second number in ^FO180,8 (the 8).

Add a new line of text

Copy a ^FO…^FD…^FS line, give it a larger y value 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^FS draws 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

^XA / ^XZ

Start / end of the label. Everything lives between them.

^PW

Print width in dots.

^LL

Label length (height) in dots.

^LH

Label home — the origin point (usually 0,0).

^FO x,y

Field origin — position the next element at x,y.

^CF0,h

Set the default font height (h dots) for following text.

^FD ... ^FS

Field data — the content to print — closed by a field separator.

^BQN,m,m

QR code; the last number is the size. Data starts with QA,.

^BCN,h,...

Code 128 barcode; h is the height in dots.

^GB w,h,t

Draw a box or line (width, height, thickness in dots).

^CI28

Character encoding, so symbols like print correctly.

For the complete language, Zebra publishes a full ZPL command guide, but the commands above cover almost every product label.