ZPL Reference: Programming Language, Fonts & Format
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, no signup required — Instant results
What is ZPL (Zebra Programming Language)?
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.
ZPL Format Anatomy
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.
- Every label format begins with ^XA and ends with ^XZ. Anything outside is configuration, not printable content.
- Commands starting with ^ are format commands and live inside the ^XA..^XZ block.
- Commands starting with ~ are control commands that configure the printer and can be sent standalone (e.g., ~JR resets the printer).
- Each printable field must close with ^FS (field separator) — forgetting ^FS is the most common cause of garbled output.
- Parameters are comma-separated and positional. Missing parameters fall back to the printer default or the last set value.
- Use ^CI28 inside the format to enable UTF-8 for non-ASCII characters (accents, ñ, ç, é, ü, Chinese, Cyrillic).
- Commands are case-sensitive. ^FO and ^fo are not the same — always uppercase.
- Whitespace and line breaks between commands are ignored, so you can format your ZPL for readability.
^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 printsCoordinate System & DPI
ZPL 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.
- 203 dpi printers: 8 dots per mm (203 dots per inch). A 4×6 inch label is 812×1218 dots.
- 300 dpi printers: 12 dots per mm (300 dots per inch). The same 4×6 label is 1200×1800 dots.
- 600 dpi printers: 24 dots per mm. Used mostly for ultra-fine retail price tags and jewellery labels.
- ^FO x,y places a field by the top-left corner of its bounding box.
- ^FT x,y places a field by the text baseline — useful when mixing font sizes.
- Y grows downward. ^FO0,0 is the top-left corner; ^FO0,1218 is the bottom of a 6-inch label at 203 dpi.
- Always test at 100% scale; rendering tools may rescale the preview but the printer applies dot coordinates literally.
ZPL Programming Guide: From Hello World to a Shipping Label
Three progressively richer examples. Paste each one into the ZPL viewer to see exactly what comes out of the printer.
Step 1 — Hello World
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
^XZStep 2 — Text + Code 128 barcode
Adds 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
^XZStep 3 — Complete shipping label
Combines 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^FDQA,https://example.com/track/A-7782^FS
^XZZPL Commands Reference
The 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.
Format & control
| 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 |
Positioning & text
| 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 |
Barcodes
| 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) |
Graphics
| 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 |
ZPL Fonts: Built-in & Scalable
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
^XZBarcodes in ZPL
ZPL natively renders every common 1D and 2D symbology. Always declare ^BY (module width and ratio) before the barcode command to keep scanners happy.
Code 128
^BCShipping, logistics, parcel tracking. Numbers + letters. Industry default for FedEx, UPS, USPS.
^FO50,50^BY3^BCN,100,Y,N,N^FD1234567890^FSQR Code
^BQURLs, JSON payloads, tracking IDs. Up to 7089 numeric chars. Wide reader support.
^FO50,50^BQN,2,6^FDQA,https://zplpdf.com^FSEAN-13
^BERetail products worldwide. Exactly 12 digits — 13th is the auto-checksum.
^FO50,50^BY2^BEN,100,Y,N^FD750123456789^FSUPC-A
^BUNorth American retail. 11 digits + auto checksum.
^FO50,50^BY2^BUN,100,Y,N^FD01234567890^FSData Matrix
^BXPharmaceutical UDI, electronics, very small items. Reads at any angle.
^FO50,50^BXN,200,200^FDPharmaCode-42^FSAztec
^B0Transport tickets, boarding passes. Compact, no quiet-zone required.
^FO50,50^B0N,7,N,0,N^FDBOARDING-A14^FSPDF417
^B7Driver licences, ID cards, shipping. Stacked 2D, holds ~1.1 KB.
^FO50,50^B7N,8,5,10,30,N^FDLastName/FirstName/DOB^FSCode 39
^B3Internal inventory, asset tags. Alphanumeric but lower density than 128.
^FO50,50^BY3^B3N,N,100,Y,N^FDASSET-001^FSComplete ZPL Examples (Copy & Paste)
Working 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.
Shipping label — e-commerce parcel
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^FDQA,https://zplpdf.com/track/1Z999AA10123456784^FS
^FO40,820^FDOrder #A-7782^FS
^FO40,860^FD2026-05-21^FS
^XZRetail price tag with EAN-13
Product 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
^XZPharmacy label with Data Matrix (GS1)
Drug 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
^XZSerialised batch — 50 unique labels
^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
^XZCommon ZPL Errors & How to Fix Them
Label 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).
ZPL Reference — Frequently Asked Questions
What is ZPL used for?
Is ZPL the same as Zebra Programming Language?
How do I learn ZPL fast?
Which ZPL command sets the font?
How do I add a QR code in ZPL?
How do I print a Code 128 barcode?
What is the difference between ^FO and ^FT?
How many DPI is my Zebra printer?
Can I test ZPL without a printer?
Is ZPL the same as EPL?
Test your ZPL right now
Paste any of the examples on this page into our free online ZPL viewer to see exactly what your printer will produce — no signup, no download.