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.
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.
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.
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.
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.
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.
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 printerA 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.