The complete Zebra Programming Language manual — anatomy, commands, fonts, barcodes and copy-paste examples for shipping, retail and logistics labels.
TL;DR
ZPL (Zebra Programming Language) is the de-facto standard for thermal label printing since the 1980s. Every label starts with ^XA and ends with ^XZ. Commands prefixed with ^ go inside the format; ~ commands configure the printer. Coordinates use dots (203 dpi = 8 dots/mm, 300 dpi = 12 dots/mm). Built-in fonts 0 and A–H cover most cases — Font 0 is fully scalable. The most-used barcodes are ^BC (Code 128) for shipping, ^BQ (QR) for tracking and ^BE (EAN-13) for retail. Set the field origin with ^FO, write data with ^FD, and close every field with ^FS. Use ^CI28 to enable UTF-8 for international characters.
Try our free ZPL tools right now
Free, runs in your browser — Instant results
ZPL stands for Zebra Programming Language, a page-description language created by Zebra Technologies in the 1980s to drive thermal label printers. It is the industry standard for shipping labels, warehouse identification, retail price tags and pharmaceutical packaging because it is compact, deterministic and supported by every Zebra printer model (ZD, ZT, ZE, ZQ, GK, GX, ZM and the older 105SL/110XiIII series).
A ZPL program is a plain-text stream of commands the printer interprets line by line. Each command starts with a control character — ^ (caret) for format commands or ~ (tilde) for setup commands — followed by a two-character code and optional comma-separated parameters. ZPL II, the current revision, adds graphics, downloadable fonts, fixed and serialised fields, multi-format labels and bidirectional communication. The same code prints the same output on every Zebra printer, regardless of model, which is what makes ZPL the lingua franca of label production worldwide.
Every printable label is a self-contained block called a format. The format opens with ^XA, contains one or more fields, and closes with ^XZ. Inside the block, the order of commands matters: the printer applies them sequentially as state. A field — text, barcode or graphic — is defined by a position command (^FO or ^FT), a content command (^A, ^BC, ^GB, etc.) and a separator (^FS). Anything outside ^XA..^XZ is treated as printer configuration and executed immediately.
^XA ; Start format
^CI28 ; Enable UTF-8
^CF0,40 ; Default font 0, size 40
^FO50,50 ; Position X=50, Y=50
^FDHello ZPL World^FS ; Print text, close field
^FO50,120^BY3 ; New field + barcode width
^BCN,100,Y,N,N ; Code 128, 100 dots tall
^FD1234567890^FS ; Barcode data, close field
^XZ ; End format → label printsZPL positions every element using dot coordinates measured from the top-left corner of the label. The conversion between millimetres or inches and dots depends on the printer's print density (DPI). Knowing the exact dot count of your label is essential for pixel-perfect alignment, especially for pre-printed forms and shipping carriers like FedEx, UPS or Mercado Libre that enforce strict label dimensions.
Three progressively richer examples. Paste each one into the ZPL viewer to see exactly what comes out of the printer.
The minimal valid ZPL program. Opens a format, prints a single text field at position (50,50) using the default scalable Font 0 at 40 dots tall, and closes the format.
^XA
^CF0,40
^FO50,50^FDHello ZPL^FS
^XZAdds a Code 128 barcode (^BC), the standard for shipping labels. ^BY sets the module width before declaring the barcode. The barcode renders the human-readable digits below itself thanks to the Y flag.
^XA
^CF0,40
^FO50,50^FDOrder #1042^FS
^FO50,120^BY3
^BCN,100,Y,N,N
^FD1234567890^FS
^XZCombines variable text, a multi-line address block, a QR code and a Code 128 tracking barcode — the structure of a real e-commerce shipping label.
^XA
^CI28
^CF0,32
^FO40,40^FDShip To:^FS
^FO40,90^FB540,4,0,L,0^FDJane Doe\&123 Main St\&Brooklyn, NY 11201\&United States^FS
^FO40,260^FDOrder #A-7782^FS
^FO40,310^BY3^BCN,90,Y,N,N^FD1Z999AA10123456784^FS
^FO450,260^BQN,2,5^FDHA,https://example.com/track/A-7782^FS
^XZThe most-used ZPL II commands grouped by purpose. For every command we list a short description, a working example you can paste into a viewer, and the parameter meaning.
| Command | Description | Example | Parameters |
|---|---|---|---|
| ^XA | Start of label format. Required at the beginning of every printable label. | ^XA ... ^XZ | None |
| ^XZ | End of label format. Sends the label to the print queue. | ^XA^FO50,50^FDHi^FS^XZ | None |
| ^FS | Field separator. Closes the current field. Mandatory after every printable element. | ^FO50,50^FDText^FS | None |
| ^CI | Change international character set. ^CI28 enables UTF-8 for accents and non-Latin scripts. | ^CI28 | 28 = UTF-8, 13 = Latin-1 |
| ^CF | Default font, height and width for the entire label. Saves repeating ^A per field. | ^CF0,30,30 | font,height,width |
| ^LH | Label home — shifts the origin (0,0) of all coordinates. | ^LH30,30 | x,y in dots |
| ^PQ | Print quantity. Issues the same label N times after ^XZ. | ^PQ5,0,0,N | qty,pause,replicate,override |
| ~JR | Printer reset. Sent outside a format; the printer reboots. | ~JR | None |
| Command | Description | Example | Parameters |
|---|---|---|---|
| ^FO | Field origin — places the next field by its top-left corner. | ^FO50,80 | x,y in dots |
| ^FT | Field typeset — places the next field by the text baseline. Best for mixed font sizes. | ^FT50,80 | x,y in dots |
| ^A | Font selection for the next field. Overrides ^CF locally. | ^A0N,40,40 | font,orientation,height,width |
| ^FD | Field data. The literal text or numeric value to print. | ^FDOrder #42^FS | text (up to 3072 chars) |
| ^FB | Field block — multi-line text with word wrap and alignment. | ^FB400,3,0,L,0^FD…^FS | width,maxLines,lineGap,alignment,indent |
| ^FN | Field number — template placeholder filled later with ^FN data. | ^FN1^FS | 1–999 |
| ^SN | Serial number — auto-increments across copies in a print job. | ^SN001,1,Y | start,increment,zero-pad |
| Command | Description | Example | Parameters |
|---|---|---|---|
| ^BY | Default barcode module width and ratio. Must precede the barcode command. | ^BY3,3,100 | moduleWidth,ratio,height |
| ^BC | Code 128 barcode — the standard for shipping/logistics. | ^BCN,100,Y,N,N | orientation,height,line-below,line-above,checkDigit |
| ^BQ | QR Code — URLs, JSON, tracking IDs. Up to 7089 numeric chars. | ^BQN,2,5 | orientation,model,magnification |
| ^BE | EAN-13 — global retail product code (13 digits). | ^BEN,100,Y,N | orientation,height,line-below,line-above |
| ^BU | UPC-A — North American retail product code (12 digits). | ^BUN,100,Y,N | orientation,height,line-below,line-above |
| ^BX | Data Matrix — high-density 2D code for small items and pharma. | ^BXN,200,200 | orientation,height,quality |
| ^B0 | Aztec — 2D code used in transport tickets and SmartCard tags. | ^B0N,7,N,0,N | orientation,magnification(1-10),ECI(Y/N),errorControl(0-300),menu(Y/N) |
| ^B7 | PDF417 — stacked 2D barcode used on driver licences and shipping. | ^B7N,8,5,10,30,N | orientation,rowHeight,security(0-8),cols(1-30),rows(3-90),truncate(Y/N) |
| Command | Description | Example | Parameters |
|---|---|---|---|
| ^GB | Graphic box — rectangles, borders, separators. | ^GB300,2,2,B^FS | width,height,thickness,colour |
| ^GC | Graphic circle. | ^GC100,3,B^FS | diameter,thickness,colour |
| ^GD | Graphic diagonal line. | ^GD200,200,2,B,R^FS | width,height,thickness,colour,orientation |
| ^GF | Graphic field — embedded bitmap (ASCII or compressed). | ^GFA,1024,1024,32,… | format,bytes,total,bytesPerRow,data |
| ^FR | Field reverse-print — inverts black/white inside the field. | ^FO50,50^FR^GB100,30,30^FS | None |
Zebra printers ship with a fixed set of bitmap fonts (A through H) plus one fully scalable font (0). Font 0 is the only one that can be set to any height and width via ^CF or ^A; the bitmap fonts have fixed sizes you can stretch but not redraw cleanly. The ^A command selects font + size for a single field; ^CF sets the default for the whole label.
| Code | Name | Size | Notes |
|---|---|---|---|
| 0 | Font 0 (CG Triumvirate) | Scalable, any height/width | Default scalable font. Best for prices, titles, dynamic-size content. |
| A | Font A | 9 × 5 dots (fixed) | Smallest bitmap. Ideal for fine print and dense labels. |
| B | Font B | 11 × 7 dots (fixed) | Slightly bigger than A. Common for line items. |
| C / D | Font C, D | 18 × 10 dots (fixed) | Mid-size bitmaps used for variable fields. |
| E | Font E | 28 × 15 dots (OCR-B) | Optical-character-recognition friendly. |
| F | Font F | 26 × 13 dots | General-purpose larger bitmap. |
| G | Font G | 60 × 40 dots | Display-size, used for headers. |
| H | Font H (OCR-A) | 21 × 13 dots | OCR-A standard, designed for machine reading. |
| P–V | Soft fonts P–V | Variable | Letters P, Q, R, S, T, U, V — bitmap legacy fonts on older firmware. |
^XA
^CF0,50,50 ; Default Font 0 at 50x50
^FO50,50^FDPrice: $19.99^FS
^FO50,120^ABN,30,15 ; Font B explicit
^FDSKU: ABC-001^FS
^FO50,170^A0N,80,80 ; Big Font 0 inline
^FDSALE^FS
^XZZPL natively renders every common 1D and 2D symbology. Always declare ^BY (module width and ratio) before the barcode command to keep scanners happy.
Shipping, logistics, parcel tracking. Numbers + letters. Industry default for FedEx, UPS, USPS.
^FO50,50^BY3^BCN,100,Y,N,N^FD1234567890^FSURLs, JSON payloads, tracking IDs. Up to 7089 numeric chars. Wide reader support.
^FO50,50^BQN,2,6^FDHA,https://zplpdf.com^FSRetail products worldwide. Exactly 12 digits — 13th is the auto-checksum.
^FO50,50^BY2^BEN,100,Y,N^FD750123456789^FSNorth American retail. 11 digits + auto checksum.
^FO50,50^BY2^BUN,100,Y,N^FD01234567890^FSPharmaceutical UDI, electronics, very small items. Reads at any angle.
^FO50,50^BXN,200,200^FDPharmaCode-42^FSTransport tickets, boarding passes. Compact, no quiet-zone required.
^FO50,50^B0N,7,N,0,N^FDBOARDING-A14^FSDriver licences, ID cards, shipping. Stacked 2D, holds ~1.1 KB.
^FO50,50^B7N,8,5,10,30,N^FDLastName/FirstName/DOB^FSInternal inventory, asset tags. Alphanumeric but lower density than 128.
^FO50,50^BY3^B3N,N,100,Y,N^FDASSET-001^FSWorking programs ready to drop into the ZPLPDF viewer. Each example is a full ^XA..^XZ block tested at 203 dpi on a 4×6 inch label.
Sender, receiver, Code 128 tracking barcode and QR for tracking URL.
^XA
^CI28
^PW812
^LL1218
^CF0,28
^FO40,40^FDFROM:^FS
^FO40,80^FB400,3,0,L,0^FDZPLPDF Warehouse\&500 Logistics Ave\&Miami, FL 33101^FS
^FO40,210^FDTO:^FS
^FO40,250^A0N,38,38^FB500,4,0,L,0^FDJane Doe\&123 Main St, Apt 4B\&Brooklyn, NY 11201\&United States^FS
^FO40,520^GB720,2,2,B^FS
^FO40,540^FDTracking:^FS
^FO40,580^BY3^BCN,110,Y,N,N^FD1Z999AA10123456784^FS
^FO520,540^BQN,2,6^FDHA,https://zplpdf.com/track/1Z999AA10123456784^FS
^FO40,820^FDOrder #A-7782^FS
^FO40,860^FD2026-05-21^FS
^XZProduct name, SKU, EAN-13 barcode and price highlighted with a reverse-print box.
^XA
^CI28
^CF0,40
^FO40,30^A0N,50,50^FDOrganic Coffee 250g^FS
^FO40,100^FDSKU: COF-ORG-250^FS
^FO40,150^BY2^BEN,100,Y,N^FD750123456789^FS
^FO40,290^GB300,80,80,B^FS
^FO50,300^FR^A0N,60,60^FD$ 12.99^FS
^XZDrug name, batch and expiry, with a Data Matrix carrying GS1 application identifiers — common in pharma supply chains.
^XA
^CI28
^CF0,32
^FO40,40^A0N,44,44^FDAcetaminophen 500 mg^FS
^FO40,100^FDBatch: B25C-0481^FS
^FO40,150^FDExp: 2027-09^FS
^FO40,200^BXN,200,200^FD>;(01)07640123456789(17)270930(10)B25C-0481^FS
^XZ^PQ50 prints 50 copies; ^SN auto-increments the serial number on each one.
^XA
^CF0,40
^FO50,50^FDBatch SN^FS
^FO50,120^A0N,80,80^SN0001,1,Y^FS
^PQ50,0,0,N
^XZLabel prints blank or skips paper.
→ Missing ^XZ at the end, or extra characters between ^XA and ^XZ.
✓ Make sure the format starts with ^XA, ends with ^XZ, and that no stray bytes break the stream.
Text shows ? instead of accents (á, é, ñ).
→ Default encoding is CP-850, which doesn't carry UTF-8 bytes.
✓ Add ^CI28 right after ^XA to switch the printer to UTF-8.
Barcode prints but scanner can't read it.
→ Module width too small or ratio out of spec.
✓ Set ^BY3,3,100 before the barcode and verify quiet zones around it.
Field appears in the wrong position.
→ Mixing ^FO and ^FT — they use different reference points.
✓ Pick one: ^FO (top-left of bounding box) or ^FT (text baseline). Don't switch mid-label.
Multi-line text overflows the label edge.
→ ^FD wraps only when ^FB is used.
✓ Wrap multi-line text in ^FBwidth,maxLines,lineGap,alignment,indent before ^FD.
Image (^GF) prints corrupted.
→ Byte count or bytes-per-row don't match the data length.
✓ Re-encode the image with a known tool — bytesPerRow must equal ceil(width/8).
Paste any of the examples on this page into our free online ZPL viewer to see exactly what your printer will produce — runs in your browser.