Guides › Working with carrier ZPL labels

Working with carrier ZPL labels

Published:

Ask FedEx or UPS for a thermal label and what comes back is not an image — it is ZPL, usually base64-encoded inside a JSON response. That is good news: text can be inspected, rendered and diagnosed before a single label is burned. It also means a whole class of "the label printed wrong" tickets is solvable at the integration layer instead of at the printer.

First: decode, do not print

The label field in a carrier response is typically base64. Decode it and you have plain ZPL beginning with ^XA. Write it to a file before you send it anywhere — the file is your evidence when something looks wrong, and it costs nothing to keep.

base64 -d label.b64 > label.zpl
head -c 200 label.zpl        # should start with ^XA

If the decoded text does not start with ^XA, you asked for a different format (PNG, PDF, EPL) or the field you read is not the label payload. Check the exact request field names in the carrier's current API reference — they differ between FedEx and UPS and change across API versions, so a value copied from a blog post is a common source of wasted hours.

What you must not change

A carrier label is a compliance document. The barcode content, the routing block and the service markings are generated by the carrier and must reach the printer unmodified: altering the tracking barcode or the routing code can make the parcel unscannable in the carrier's network, and that failure surfaces days later at a sorting hub, not in your tests.

Adding your own information is a different matter. Print it as a separate label — an internal SSCC, a pick-list code, a warehouse location — rather than editing the carrier's format. Two labels that each stay valid beat one label that nobody will accept responsibility for.

The resolution trap

Carrier labels are almost always 4×6 inches, and the ZPL is written in dots for a specific density. Send a label generated for 203 dpi to a 300 dpi printer and it prints at roughly two-thirds size with a wide margin; the reverse overflows and clips. Nothing in the file is "wrong" — the dots simply mean different physical distances on the two heads.

Confirm which density a label assumes before blaming the printer: the size and DPI analyzer reads the declared dimensions out of the file and reports the density that makes them come out as a standard label size, or says plainly that it cannot tell.

A validation gate that pays for itself

Because the label is text, you can check it in the same code path that receives it. A minimal gate looks like this: request the label, decode it, run diagnostics, and only queue it for printing when there are no errors. Findings with a severity of error mean the label will not render as intended; warnings are worth logging even when you proceed.

curl -X POST "https://api.labelixa.com/v1/diagnostics?dpmm=8&w=4&h=6"      --data-binary @label.zpl

The same check is available as a command line step for CI or a shipping worker (npx labelixa validate label.zpl exits non-zero when the label carries errors), and as a browser paste in the ZPL viewer when you are investigating one specific parcel.

Failures that look like carrier problems but are not

None of these require the carrier's support desk. All three are visible in the file, which is exactly why decoding before printing is worth the two extra lines of code.

Related guides

What is ZPL?

ZPL is the language Zebra thermal printers understand. How to read the commands, how a label is put together, and the most common mistakes.

Which barcode symbology should I use?

EAN-13, Code 128 or QR? Practical rules for picking a barcode based on your data, your space and the scanner that has to read it.

How to preview a ZPL file without a printer

A ZPL file is just text — the label only exists once something draws it. Three practical ways to see a ZPL label before it reaches the printer.

Try your own ZPL code →