Published: · Updated:
ZPL has no unit. ^FO50,50 means fifty dots from
the left and fifty from the top, and a dot is as big as the print head makes
it. That single fact explains most "the label came out the wrong size"
tickets, so here are the numbers, computed rather than copied.
Printers are sold by dots per millimetre (dpmm) or dots per inch (dpi); the pairs below are the industry's nominal values. The heads are really 8, 12 and 24 dots per millimetre — 203.2, 304.8 and 609.6 dpi — and "203" and "300" are rounded names. The engine, the converter and these tables all work in dots per millimetre, exactly as the printer does.
Measured, not assumed. On 2026-09-04 we printed a ruler ladder on a Zebra GK420d (203 dpi nominal) and measured it on paper: a 300-dot bar came out 37.96 mm against 37.50 expected, and seven 100-dot steps spanning 700 dots measured 87.36 mm against 87.50 — head axis and feed axis, both inside the ±1.2 % the photo method allows, and deviating in opposite directions, which is what measurement noise looks like rather than a scaled head. The 8 dots/mm figure this page rests on holds on real hardware. What that measurement cannot tell you is sub-1 % accuracy; that needs a flat label and a caliper.
Then we did exactly that. On 2026-09-14 the same GK420d printed a 400-dot bar along each axis — 50.00 mm by design at 8 dots/mm — and a vernier caliper read each one three times: head axis 50.0 mm, feed axis 49.5 mm, and the 80-dot bar thickness 10.0 mm. The head axis is exact; the feed axis runs 1 % short on this printer, repeatably, and that sign was already visible in both ruler rounds. One printer, one firmware, one media — not a statement about every GK420d — but it settles what the ruler could not: the dot pitch the tables rest on is what the head produces, and a small length error comes from the feed, not from the dots. (A first print measured 45.0 mm and it was not the head: a 560-dot print width left behind by an earlier EPL job clipped the bar. Worth checking before blaming the printer.)
| Density | dpi | dots / mm | dots / inch | 1 mm | 10 mm |
|---|---|---|---|---|---|
| 6 dpmm | 152 dpi | 6 | 152.4 | 6 | 60 |
| 8 dpmm | 203 dpi | 8 | 203.2 | 8 | 80 |
| 12 dpmm | 300 dpi | 12 | 304.8 | 12 | 120 |
| 24 dpmm | 600 dpi | 24 | 609.6 | 24 | 240 |
Width × height, computed the way the engine sizes its canvas: inches × dpmm × 25.4, rounded down. Note that 4 inches on a "300 dpi" head is 1219 dots, not 1200 — the head is 12 dpmm, and 12 × 25.4 × 4 = 1219.2.
| Label | 152 dpi | 203 dpi | 300 dpi | 600 dpi |
|---|---|---|---|---|
| 4 × 6 in | 609 × 914 | 812 × 1219 | 1219 × 1828 | 2438 × 3657 |
| 4 × 3 in | 609 × 457 | 812 × 609 | 1219 × 914 | 2438 × 1828 |
| 2 × 1 in | 304 × 152 | 406 × 203 | 609 × 304 | 1219 × 609 |
| 100 × 150 mm | 600 × 900 | 800 × 1200 | 1200 × 1800 | 2400 × 3600 |
| 57 × 32 mm | 342 × 192 | 456 × 255 | 684 × 384 | 1368 × 768 |
A file written for 203 dpi and sent to a 300 dpi head prints at 8/12 of its size — exactly two thirds — with a wide empty margin. The reverse overflows and clips. Nothing in the file is wrong; the dots simply mean a different physical distance. To move a design, every dot value scales by the ratio of the two densities in dots per millimetre — 1.5, not the 1.478 you get from dividing the rounded dpi names:
| Migration | Factor | 4 in width in dots | ^BY2 becomes |
|---|---|---|---|
| 203 → 300 dpi (8 → 12 dpmm) | × 1.500 | 812 → 1218 | 3 |
| 300 → 203 dpi (12 → 8 dpmm) | × 0.667 | 1219 → 813 | 1 |
| 203 → 600 dpi (8 → 24 dpmm) | × 3.000 | 812 → 2436 | 6 |
| 300 → 600 dpi (12 → 24 dpmm) | × 2.000 | 1219 → 2438 | 4 |
| 152 → 203 dpi (6 → 8 dpmm) | × 1.333 | 609 → 812 | 3 |
Three things do not scale cleanly, and this is where a mechanical find-and-replace fails:
^BY) is an integer.
2 dots at 203 dpi is exactly 3 at 300, but 3 dots becomes 4.5 — you choose
4 or 5 and the symbol shrinks or grows by a sixth. Check the quiet zone
still fits.^A0 are dots too; bitmap fonts
(^A with a letter) have fixed cell sizes and do not scale at all.
They are rendered at a different physical size or need a different font.^GF) are pixel data at the original
density; scaling them means resampling the image, not editing numbers.The DPI converter applies the factor to every coordinate and flags the values it had to round; the size analyzer reads a file and reports which density makes its declared dimensions come out as a standard label.
It depends on the printer: 8 dots at 203 dpi, 12 at 300 dpi and 24 at 600 dpi (6 at 152 dpi). ZPL itself carries no unit — a coordinate is a dot, and the print head decides how large a dot is.
Because the file's dot values now mean shorter physical distances: 8/12 of the original, exactly two thirds, leaving a wide margin. Scale every coordinate by 1.5 (the dpmm ratio, not 300/203) or use the DPI converter, then re-check barcode module widths, which must stay integers.
Nominally. 8 dots per millimetre is 203.2 dpi; printers and software round to 203. The difference is under a tenth of a percent — about half a dot over a full 4-inch width — and never the cause of a visibly wrong label.
ZPL has no center command for plain text. Use a ^FB block with C justification, or measure the text width and compute the x position yourself.
How to preview a ZPL file without a printerA ZPL file is just text — the label only exists once something draws it. Four ways to see and test a ZPL label without a printer, including CI.
Using custom fonts in ZPLTwo ways to print your own font on a Zebra printer: embed it in every label, or upload it once and call it with ^A@. The difference and the limits.
How to open a ZPL fileA .zpl file opens in any text editor, because ZPL is plain text. What the file contains, how to read it, and how to see the label it describes.