ZPL compatibility of the OpenZPL engine
The OpenZPL engine draws the 51 ZPL commands of the command reference, one of them partially, and skips the ones that configure the printer. The barcode and text commands listed under “Not supported yet” don't draw correctly today.
Tested 2026-10-20 with openzpl-api 689632b at 8 dpmm.
How we test
Every example on this site is a fixture: a short synthetic label that the engine renders to a PNG when the site is built. If a fixture's ZPL changes and its image isn't rendered again, the build fails, so the image always shows what the engine does with that exact code.
The 116 fixtures are public in fixtures.json, with their size, density and image, under CC0. Use them to test any ZPL renderer.
A preview isn't a print. Darkness, media, firmware and the fonts installed on a printer change the result, so check critical labels on the printer itself.
Drawn
| Command | What it does | Category | Evidence |
|---|---|---|---|
^XA |
Opens a label. Everything up to ^XZ is one label. | Label format | Rendered example |
^XZ |
Closes the label opened by ^XA and prints it. | Label format | Rendered example |
^PW |
Sets the label width in dots. | Label format | Rendered example |
^LL |
Sets the label length in dots. | Label format | Rendered example |
^LH |
Moves the origin that every field position is measured from. | Label format | Rendered example |
^LS |
Shifts every field left by the given number of dots. | Label format | Rendered example |
^LT |
Moves the whole label up or down by the given number of dot rows. | Label format | Rendered example |
^PO |
Prints the label normally (N) or upside down (I). | Label format | Rendered example |
^PM |
Mirrors the whole label horizontally when set to Y. | Label format | Rendered example |
^PQ |
Sets how many labels to print; each one counts as a label in the preview. | Label format | Rendered example |
^MU |
Changes the unit of measurement to dots, inches or millimetres. | Label format | Rendered example |
^CI |
Selects the character set. ^CI28 is UTF-8. | Label format | Rendered example |
^FO |
Sets the field position: x, y coordinates in dots from the top-left corner. | Fields and position | Rendered example |
^FT |
Positions a field by its baseline instead of its top-left corner. | Fields and position | Rendered example |
^FD |
The text or barcode data of the current field. | Fields and position | Rendered example |
^FS |
Ends the current field. | Fields and position | Rendered example |
^FB |
Wraps text into a block with a width, line count and alignment. | Fields and position | Rendered example |
^FR |
Prints the field white on black over whatever is under it. | Fields and position | Rendered example |
^FH |
Lets ^FD contain hex escapes such as _0D. | Fields and position | Rendered example |
^FW |
Sets the default rotation for the fields that follow. | Fields and position | Rendered example |
^FN |
Names a variable field in a stored format. | Fields and position | Rendered example |
^FX |
A comment. The printer ignores everything up to the next command. | Fields and position | Rendered example |
^SN |
Prints a number that increments on each label. | Fields and position | PartialRead but not drawn: the serial field is left out and copies aren't incremented (the same as Labelary's preview). Rendered example |
^A |
Selects the font, rotation and size for the next text field. | Text and fonts | Rendered example |
^A@ |
Selects a font by its file name on the printer. | Text and fonts | Rendered example |
^CF |
Sets the font and size used when a field has no ^A. | Text and fonts | Rendered example |
^CW |
Assigns a one-letter name to a font file. | Text and fonts | Stores or recalls data; no image of its own |
^BY |
Sets module width, wide-to-narrow ratio and height for the barcodes that follow. | Barcodes | Rendered example |
^BC |
Code 128 barcode, the most common one on shipping labels. | Barcodes | Rendered example |
^B3 |
Code 39 barcode. | Barcodes | Rendered example |
^B2 |
Interleaved 2 of 5 barcode, numeric only. | Barcodes | Rendered example |
^BE |
EAN-13 retail barcode. | Barcodes | Rendered example |
^B8 |
EAN-8 retail barcode. | Barcodes | Rendered example |
^BU |
UPC-A retail barcode. | Barcodes | Rendered example |
^B9 |
UPC-E retail barcode. | Barcodes | Rendered example |
^BQ |
QR Code. The data starts with an error correction and input mode, e.g. QA, | Barcodes | Rendered example |
^BX |
Data Matrix 2D barcode. | Barcodes | Rendered example |
^B7 |
PDF417 stacked 2D barcode. | Barcodes | Rendered example |
^BO |
Aztec 2D barcode. | Barcodes | Rendered example |
^BD |
MaxiCode, used by UPS. | Barcodes | Rendered example |
^GB |
Draws a box or a line: width, height, border thickness, colour and rounding. | Graphics | Rendered example |
^GC |
Draws a circle: diameter, border thickness and colour. | Graphics | Rendered example |
^GE |
Draws an ellipse. | Graphics | Rendered example |
^GD |
Draws a diagonal line. | Graphics | Rendered example |
^GF |
Embeds a bitmap image in the label (ASCII hex, binary or Z64). | Graphics | Rendered example |
^GS |
Prints a registered, copyright or other symbol. | Graphics | Rendered example |
^DF |
Stores the label format on the printer under a name. | Stored formats and images | Rendered example |
^XF |
Recalls a stored format to fill its ^FN fields. | Stored formats and images | Rendered example |
~DG |
Stores an image on the printer under a name. | Stored formats and images | Stores or recalls data; no image of its own |
^XG |
Prints an image stored with ~DG. | Stored formats and images | Stores or recalls data; no image of its own |
^IM |
Prints a stored image at the current field origin. | Stored formats and images | Stores or recalls data; no image of its own |
Ignored on purpose
These commands set up the printer, not the label. The API accepts them and renders the label as if they weren't there; we checked that the image is byte-identical without them.
| Group | Commands |
|---|---|
| Media and sensors | ^MM, ^MN, ^MT, ^MF, ~JS |
| Speed, darkness and tear-off | ^PR, ~SD, ^MD, ~TA |
| Calibration and printer state | ~JC, ~JA, ~JR, ^JU, ~HS |
| Network, RFID setup and host queries | ^NC, ^NI, ^RS, ~HI, ~HM |
Not supported yet
Each one was tested by placing it in a label at 8 dpmm. None of them fails the request: the label renders, without the symbol.
| Command | Symbology or feature | What the engine does today |
|---|---|---|
^TB | Text block | Text is drawn on one line; the block doesn't wrap. Use ^FB instead. |
^B0 | Aztec (alias) | No symbol drawn. ^BO, the other Aztec command, is drawn. |
^B1 | Code 11 | No bars; the data is printed as text. |
^B4 | Code 49 | No bars; the data is printed as text. |
^B5 | Planet Code | No bars; the data is printed as text. |
^BA | Code 93 | No bars; the data is printed as text. |
^BB | CODABLOCK | No symbol; the data is printed as text. |
^BF | MicroPDF417 | No symbol; the data is printed as text. |
^BK | ANSI Codabar | No bars; the data is printed as text. |
^BL | LOGMARS | No bars; the data is printed as text. |
^BM | MSI | No bars; the data is printed as text. |
^BP | Plessey | No bars; the data is printed as text. |
^BR | GS1 DataBar | No symbol; the data is printed as text. |
^BS | UPC/EAN extensions | No bars; the data is printed as text. |
^BT | TLC39 | No symbol; the data is printed as text. |
^BZ | POSTAL | No bars; the data is printed as text. |
Known differences
- A format with no fields, such as
^XA^XZ, returns400 ERROR: No labels found in the ZPLinstead of a blank image. - Fonts: Zebra's font 0 (CG Triumvirate Bold Condensed) can't be bundled, so
^A0is drawn with Roboto Condensed Bold, with spacing calibrated per character. The bitmap fonts^AA–^AHare drawn with DejaVu Sans Mono. Text widths can differ by a few dots from a given printer. - An RFID write (
^RFfollowed by^FD…^FS) draws its data as text; a printer encodes it in the tag and prints nothing.
Moving from Labelary
The API keeps Labelary's v1 paths and headers, so most clients only change the host. See Migrate from Labelary for the tested differences and OpenZPL vs Labelary for the comparison.