^FD (Field Data) and ^FS (Field Separator) are the ZPL II commands that supply the actual content of a field and then close it. Every text string, barcode value, or graphic data block on a Zebra label lives between a ^FD and a ^FS. Label Toolkit generates these commands automatically when you design labels in the browser, but understanding the raw syntax lets you debug output, write API payloads, and spot encoding issues instantly.
- ^FD marks the start of field data and accepts any printable ASCII string, plus escape sequences for special characters.
- ^FS closes the field with no parameters; the printer ignores everything after
^FSuntil the next field command opens. - The pair always follows a
^FO(Field Origin) and a font or barcode command, forming the three-command sequence that describes one complete element on the label. - Forgetting
^FSis the single most common cause of garbled or merged fields in hand-written ZPL.
What exactly do ^FD and ^FS do?
ZPL II, the programming language spoken by every modern Zebra thermal printer, treats a label as a collection of discrete fields. A field has an origin (position), a renderer (font, barcode type, or graphic), and data (content). ^FD opens the data portion. Everything between ^FD and ^FS is the string the printer hands off to whatever renderer was declared earlier in the field. ^FS signals the end of the data and commits the field to the label image buffer.
Because ZPL is a streaming language, the printer reads commands in order. If you omit ^FS, the parser keeps accumulating characters as field data until it hits another recognized caret command, which corrupts the next field or silently swallows it entirely. Real printers handle this differently from ZPL emulators, so always close every field.
Syntax reference
^FD syntax
The formal syntax from the Zebra ZPL Programming Guide is:
^FD<data>There is no separator between ^FD and the data string. The data starts immediately after the second letter D. Valid characters are printable ASCII (0x20 to 0x7E) plus a handful of special escape sequences shown in the table below. The maximum field length depends on the printer model and firmware, but 3,072 bytes is a safe working limit for most ZD and ZT series printers.
^FS syntax
^FSNo parameters. No data follows. The command is exactly three characters. Some authors write it as ^FS on its own line for readability, and others append it immediately after the data string. Both are valid; the printer does not care about whitespace between ZPL commands unless that whitespace is inside a ^FD block, in which case spaces become part of the printed string.
Special characters inside ^FD
| Character needed | Escape sequence in ^FD | Notes |
|---|---|---|
| Caret (^) | ^5E or _5E | Hex code for ASCII 0x5E; avoids triggering a ZPL command |
| Tilde (~) | ~7E or _7E | Avoids ZPL tilde-command prefix |
| FNC1 (GS1 separator) | ~1E | Required in GS1-128 and GS1 DataMatrix fields |
| Non-printable ASCII | _XX (underscore + hex) | Underscore is the default sub-delimiter; change with ^CC and ^CD |
The escape prefix character is configurable with ^CT (Change Tilde) and ^CC (Change Caret). If your data naturally contains underscores, change the sub-delimiter with ^CD to avoid accidental substitution.
The three-command field trio: ^FO, font or barcode, ^FD, ^FS
No field exists in isolation. The printer needs to know where to draw the field before it knows what to draw. The canonical sequence is:
- ^FO sets the X and Y origin of the field in dots from the label's top-left corner. (See the dedicated ^FO field origin command reference for full positioning details.)
- A font command (
^A) or barcode command (^BC,^BQ, etc.) tells the printer which renderer to use. ^FDdelivers the data string to that renderer.^FScloses the field and flushes it to the image buffer.
If you skip step 2, the printer uses whatever font or barcode was active from a previous field, which sometimes works by accident and always creates fragile labels that break when you add other elements later.
Complete working examples
Printing a plain text line
The label below prints the word "FRAGILE" in Zebra's scalable font A at 40 x 30 dots from the top-left corner, on a 203 DPI (dots per inch) printer. At 203 DPI, one dot equals approximately 0.125 mm.
^XA
^FO40,30
^A0N,36,36
^FDFragile^FS
^XZBreaking it down: ^A0N,36,36 selects scalable font 0, no rotation, height 36 dots, width 36 dots (about 4.5 mm tall at 203 DPI). ^FDFragile hands the string to the font renderer. ^FS ends the field. ^XA and ^XZ wrap the entire label format, as described in the ^XA and ^XZ label start and end reference.
Printing a Code 128 barcode
^XA
^FO50,50
^BCN,80,Y,N,N
^FD12345678^FS
^XZ^BCN,80,Y,N,N configures a Code 128 barcode: N for no rotation, 80 dots tall (about 10 mm at 203 DPI), Y to print the human-readable text below, N for no check digit (Code 128 computes its own), N for no start/stop characters in the human-readable line. The string 12345678 between ^FD and ^FS is the value encoded.
Printing a QR Code
^XA
^FO60,60
^BQN,2,4
^FDQA,https://labeltoolkit.com^FS
^XZ^BQN,2,4 selects QR Code, normal orientation, model 2 (standard QR), magnification factor 4 (each module is 4 x 4 dots, giving a module size of about 0.5 mm at 203 DPI). The ^FD data for QR starts with a two-character prefix: Q (error correction level, here Q = 25% recovery) and A (indicates the data type is automatically detected). The URL follows immediately with no space. This is a common point of confusion: the prefix is part of the ^FD value, not a separate command.
Variable data with multiple fields
^XA
^FO30,20
^A0N,28,28
^FDOrder: 90021^FS
^FO30,60
^A0N,28,28
^FDShip to: Austin, TX^FS
^FO30,100
^BCN,60,Y,N,N
^FD90021^FS
^XZEach field gets its own ^FO, renderer, ^FD, and ^FS. The three fields are completely independent. Changing the data in one does not shift any other field, which is why ZPL is well-suited to high-speed variable-data printing.


