ZPL tools API

All 33 tools of zplcloud.com/tools as endpoints on api.zplcloud.com: render, lint and analyse ZPL, convert PDF, images, HTML, SVG, EPL2, DPL and TSPL to ZPL, print ZPL in 11 other printer languages, generate barcodes, QR and GS1 codes, check barcodes and convert units.

Overview

POST https://api.zplcloud.com/v1/tools/{slug}
  • JSON body in camelCase. API key via X-API-Key or Basic Auth; auth, errors and request IDs are described on the API overview.
  • Same logic as the website tools under /en/tools/{slug}, but no rate limits and larger input limits. Responses and error messages are always English.
  • Binary inputs (PDF, PNG, other images) are base64 strings; data URIs such as data:image/png;base64,… are accepted.
  • dpi is 152, 203, 300 or 600 (default 203) for every tool except the dpi calculator and the printer-language tools, which accept the resolutions of their print heads.
  • Errors: { "error": "…", "tool": "<slug>", "requestId": "…" }, usually 400; 413 for oversized input.
  • Webhook: every tool accepts webhookId and webhookResult. Event api.tool.completed, summary.tool is the slug plus tool-specific values; with webhookResult=true files come as base64, SVG as UTF-8 text and JSON responses as JSON (payload).
ToolInputResponseRenders
zpl-to-pdfZPLapplication/pdf1 per label
zpl-to-pngZPLimage/png1
zpl-to-jpgZPLimage/jpeg1
zpl-to-svgZPLimage/svg+xml1
zpl-linterZPLJSON issues1
zpl-analyserZPLJSON analysis1
zpl-dpi-converterZPLJSON zpl + engine check1
check-barcodephoto/scan or dataJSON findings1
html-to-zplPNG of the HTMLJSON zpl1
pdf-to-zplPDFJSON zpl1 per page
image-to-zplPNG, JPG, GIF, BMPJSON zpl, grf1
svg-to-zplSVG markupJSON zpl1
epl2-to-zplEPL2 codeJSON zpl1
dpl-to-zplDPL codeJSON zpl1
tspl-to-zplTSPL codeJSON zpl1
zpl-to-tsplZPLraw print job1 per label
zpl-to-epl2ZPLraw print job1 per label
zpl-to-dplZPLraw print job1 per label
zpl-to-sbplZPLraw print job1 per label
zpl-to-cpclZPLraw print job1 per label
zpl-to-escposZPLraw print job1 per label
zpl-to-brotherZPLraw print job1 per label
zpl-to-pclZPLraw print job1 per label
zpl-to-easyplugZPLraw print job1 per label
zpl-to-tpclZPLraw print job1 per label
zpl-to-jscriptZPLraw print job1 per label
barcode-to-zplsymbology + dataJSON zpl1
qr-code-to-zplQR type + fieldsJSON zpl1
gs1-ai-128-to-zplGS1 AIsJSON zpl1
gs1-ai-datamatrix-to-zplGS1 AIsJSON zpl1
gs1-ai-qr-code-to-zplGS1 AIsJSON zpl1
gs1-ai-databar-to-zplGS1 AIsJSON zpl1
dpi-calculatorvaluesJSON conversions1

Sending files - ZPL or code as a JSON string, binary files as base64:

# text file (ZPL, SVG, EPL2 …) as JSON string
jq -Rs '{zpl: ., dpi: 203}' label.zpl \
  | curl -X POST https://api.zplcloud.com/v1/tools/zpl-to-pdf \
      -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
      --data-binary @- -o label.pdf

# binary file as base64 (GNU base64; on macOS: base64 -i file.pdf)
base64 -w0 label.pdf | jq -Rs '{pdfBase64: ., pages: "all"}' \
  | curl -X POST https://api.zplcloud.com/v1/tools/pdf-to-zpl \
      -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
      --data-binary @- | jq -r .zpl > label.zpl

Render counting

The tools are never blocked by the monthly label quota (no 429), but every successful call counts as a render in the account's usage and the dashboard API statistics:

ToolRenders
zpl-to-pdfone per label (^XA…^XZ block)
pdf-to-zplone per converted page
zpl-to-tspl, zpl-to-epl2 … (printer languages)one per label
all other toolsone per call
failed calls (HTTP 400 and above)none

Plans and counting: API overview → quota.

Input limits

Protection against overload, independent of the plan:

InputLimit
ZPL, EPL2/DPL/TSPL code, SVG2,000,000 characters (413)
Images (PNG, JPG, GIF, BMP)20 MB (413) and 16 megapixels
PDF50 MB (413), 100 pages per call
Label size400 × 400 mm
ZPL to printer languages1,000 labels and 256 MB of uncompressed image data per call
Request bodyabout 4 MB for text tools; 72 MB for html-to-zpl, pdf-to-zpl, image-to-zpl and check-barcode
Barcode data128 characters (linear), 4,096 (QRCode, DataMatrix, Pdf417, AztecCode, MaxiCode); GS1 AI string 4,096
QR field value / check-barcode data2,000 characters each

From ZPL

ZPL to PDF

POST /v1/tools/zpl-to-pdf · website tool. Renders raw ZPL to a PDF: one page per ^XA…^XZ label, or labels at original size on A4/Letter sheets for office printers.

FieldTypeDefaultNotes
zplstringrequiredOne or more labels, max 2,000,000 characters.
dpiint203152, 203, 300 or 600.
widthMmnumber^PW, else 75Label width in mm, max 400.
heightMmnumber^LL, else 50Label height in mm, max 400.
layoutstringlabellabel: one page per label in label size. a4 / letter: labels at original size on sheets, max 2,000 labels.
cutLinesbooltrueSheet layouts only: thin dashed cut lines around every label.
curl -X POST https://api.zplcloud.com/v1/tools/zpl-to-pdf \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"zpl":"^XA^FO50,50^A0N,40,40^FDLabel 1^FS^XZ^XA^FO50,50^A0N,40,40^FDLabel 2^FS^XZ","widthMm":100,"heightMm":50}' \
  -o labels.pdf

Response: application/pdf (label.pdf). Renders: one per label. Summary: { tool, widthMm, heightMm, dpi, labels, bytes }. Errors: zpl is required., dpi must be 152, 203, 300 or 600., Label size must not exceed 400 × 400 mm., Rendering produced no PDF - check the ZPL., layout must be "label", "a4" or "letter"., A … mm label does not fit on an A4 sheet - use layout "label"., 413 zpl is too long … or Too many labels for a sheet PDF (max 2,000).

ZPL to PNG

POST /v1/tools/zpl-to-png · website tool. Renders one label as PNG - by default the first one. Fields, size rules and errors as for zpl-to-pdf, plus labelIndex (int, 0-based, default 0) to pick a label in multi-label ZPL. The response header X-ZplCloud-Label-Count returns how many labels the ZPL contains; an index out of range is answered with 400.

curl -X POST https://api.zplcloud.com/v1/tools/zpl-to-png \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"zpl":"^XA^FO50,50^A0N,40,40^FDOne^FS^XZ^XA^FO50,50^A0N,40,40^FDTwo^FS^XZ","dpi":203,"labelIndex":1}' -o label-2.png

Response: image/png. Renders: 1. Summary: { tool, widthMm, heightMm, dpi, labels: 1, bytes }.

ZPL to JPG

POST /v1/tools/zpl-to-jpg · website tool. Renders one label as JPEG. Fields and errors as for zpl-to-png, including labelIndex and X-ZplCloud-Label-Count.

curl -X POST https://api.zplcloud.com/v1/tools/zpl-to-jpg \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"zpl":"^XA^FO50,50^A0N,40,40^FDHello^FS^XZ","widthMm":60,"heightMm":30}' -o label.jpg

Response: image/jpeg. Renders: 1.

ZPL to SVG

POST /v1/tools/zpl-to-svg · website tool. Renders ZPL as vector SVG. Only zpl is needed; dpi, widthMm and heightMm are validated like for zpl-to-pdf but do not change the SVG.

curl -X POST https://api.zplcloud.com/v1/tools/zpl-to-svg \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"zpl":"^XA^FO50,50^GB300,120,4^FS^FO80,90^A0N,40,40^FDHello^FS^XZ"}' -o label.svg

Response: image/svg+xml; charset=utf-8 (in the webhook result as utf-8 text). Renders: 1. Errors: as zpl-to-pdf, plus Rendering produced no SVG - check the ZPL.

Verify

ZPL DPI converter and rotation

POST /v1/tools/zpl-dpi-converter · website tool. Converts ZPL written for one printer resolution to another and/or rotates the whole label clockwise. Positions, label size, fonts, barcode heights and module widths, boxes, text blocks and ^GFA graphics are recalculated; for rotation the rendered size of every field is measured, so the rotated field lands exactly where it belongs. Afterwards the rendering engine compares every element with its expected position and size.

FieldTypeDefaultNotes
zplstringrequiredOne or more labels, max 2,000,000 characters.
sourceDpiint203Resolution the ZPL was written for: 152, 203, 300 or 600.
targetDpiintsourceDpiResolution of the target printer: 152, 203, 300 or 600.
rotationint0Clockwise: 0, 90, 180 or 270. 90 and 270 swap width and height.
widthMm, heightMmnumber^PW / ^LL, else 75 × 50Label size in mm (at sourceDpi). Needed for an exact rotation if the ZPL has no ^PW / ^LL.
jq -Rs '{zpl: ., sourceDpi: 203, targetDpi: 300, rotation: 90}' label.zpl \
  | curl -X POST https://api.zplcloud.com/v1/tools/zpl-dpi-converter \
      -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" -d @-

{
  "zpl": "^XA^PW751^LL1200...",
  "sourceDpi": 203, "targetDpi": 300, "rotation": 90,
  "sourceWidthMm": 101.6, "sourceHeightMm": 63.6,
  "targetWidthMm": 63.6, "targetHeightMm": 101.6,
  "notes": [
    { "code": "QR", "command": "BQ", "line": 8, "message": "QR codes have no orientation parameter in ZPL - ..." }
  ],
  "check": {
    "elements": 6, "compared": 6, "maxDeviationMm": 0.25, "toleranceMm": 0.3, "passed": true,
    "deviations": [
      { "element": "A", "content": "SHIP TO", "line": 6, "deltaX": 0, "deltaY": -1, "deltaWidth": -3, "deltaHeight": 0, "maxMm": 0.25 }
    ]
  }
}

check.passed is true when no element deviates by more than toleranceMm (0.3 mm). Deviations are measured in dots of the target printer; typical causes are module widths and font sizes that can only be whole dots. notes[].code: SIZE, MODULE, QR_MAG, DM_MODULE, AZTEC_MAG, GRAPHIC_SCALE, GRAPHIC_ROTATE, STORED_SCALE, STORED_ROTATE, UNITS, MAXICODE, QR, UNVERIFIED. Renders: 1. Summary: { tool, sourceDpi, targetDpi, rotation, passed, maxDeviationMm }. Errors: zpl is required., sourceDpi and targetDpi must be 152, 203, 300 or 600., rotation must be 0, 90, 180 or 270., Nothing to do: set a different targetDpi or a rotation., 413.

ZPL linter

POST /v1/tools/zpl-linter · website tool. Checks ZPL for syntax errors, fields outside the label, fonts, barcodes and printer pitfalls.

FieldTypeDefaultNotes
zplstringrequiredMax 2,000,000 characters.
dpiint-Optional: 152, 203, 300 or 600 for resolution-dependent checks.
widthMm, heightMmnumber-Optional label size for the bounds checks.
profilestring-Optional rule set: amazon-fba adds Amazon FBA label checks (e.g. FNSKU format).
curl -X POST https://api.zplcloud.com/v1/tools/zpl-linter \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"zpl":"^XA^PR20^FO50,50^A0N,40,40^FDHello^FS^XZ","dpi":203}'

{
  "clean": false,
  "profile": null,
  "errorCount": 0,
  "warningCount": 1,
  "infoCount": 0,
  "issues": [
    {
      "severity": "warning",
      "code": "ZPL-060",
      "category": "Hardware",
      "message": "^PR 20 ips exceeds the maximum of most printers (14 ips).",
      "line": 1,
      "column": 4,
      "fix": "Lower the print speed (e.g. ^PR6)."
    }
  ]
}

clean is true when there are no errors and no warnings (infos are allowed). severity: error, warning or info. Renders: 1. Summary: { tool, clean, errorCount, warningCount, infoCount }. Errors: zpl is required., dpi must be 152, 203, 300 or 600., Unknown profile. Known profiles: amazon-fba., 413.

ZPL analyser

POST /v1/tools/zpl-analyser · website tool. Explains every command, measures the label and predicts print, network and rendering times.

FieldTypeDefaultNotes
zplstringrequiredMax 2,000,000 characters.
dpiint-Optional: 152, 203, 300 or 600.
widthMm, heightMmnumber-Fallback size when the ZPL has no ^PW / ^LL.
networkMbitint10Line speed for the transfer prediction, 1 to 100,000 Mbit/s.
curl -X POST https://api.zplcloud.com/v1/tools/zpl-analyser \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"zpl":"^XA^PW812^LL1218^MD20^PR8^FO50,50^A0N,40,40^FDHello^FS^XZ","networkMbit":100}'
Response fieldContent
commands[]{ code, params, description, count } per command
logs[]Step-by-step sequence { time, code, params, details }
labelWidthMm, labelHeightMm, dpiDetected label size and resolution
zplBytes, zplChars, commandCountSize figures
printSpeedIps, darknessFrom ^PR / ^MD, otherwise the Zebra defaults 5 ips and 15
timePerLabelEstimated print time per label (text)
predictions[]{ count, print, network, render, networkMb, cloud } for 10, 1,000 and 10,000 labels
assumedAssumptions behind the prediction: printSpeedIps, speedFromZpl, labelLengthInch, lengthFromZpl, feedSeconds, networkMbit, renderBaseMs, renderKbPerSec

Renders: 1. Summary: { tool, labelWidthMm, labelHeightMm, dpi, commandCount, timePerLabel }. Errors: zpl is required., dpi must be 152, 203, 300 or 600., networkMbit must be between 1 and 100000., 413.

Check barcode

POST /v1/tools/check-barcode · website tool. Decodes every barcode in a photo or scan - or takes the raw content - and checks GS1 structure, check digits, dates and lengths.

FieldTypeDefaultNotes
imageBase64string-Photo or scan (PNG, JPG, GIF, BMP, WebP), max 20 MB and 16 megapixels. Takes precedence over data.
datastring-Alternatively the barcode content, max 2,000 characters, e.g. in bracket notation.
curl -X POST https://api.zplcloud.com/v1/tools/check-barcode \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"data":"(01)04006381333931(17)271231(10)L-2026-0417"}'

{
  "count": 1,
  "valid": true,
  "codes": [
    {
      "symbology": null,
      "source": "text",
      "raw": "(01)04006381333931(17)271231(10)L-2026-0417",
      "kind": "gs1",
      "valid": true,
      "number": "04006381333931",
      "numberType": "GTIN-14 / ITF-14",
      "bracketed": "(01)04006381333931(17)271231(10)L-2026-0417",
      "parts": [ { "ai": "01", "title": "GTIN", "value": "04006381333931", "ok": true, "note": null }, … ],
      "findings": [ { "ok": true, "code": "checkDigitOk", "ai": "01", "message": "Check digit matches." }, … ]
    }
  ]
}
  • source: image or text; symbology is the detected format for images (e.g. Code 128 / GS1-128), null for data.
  • kind: gs1, digitallink, number or plain. Control characters in raw appear as <GS>, <RS>, <EOT>.
  • valid per code is null for plain content; the top-level valid is false as soon as one code is invalid. Finding codes as for the GS1 tools.

Renders: 1 per call. Summary: { tool, count, valid }. Errors: 400 Send imageBase64 (photo or scan) or data (the barcode content)., imageBase64 is not valid base64., not an image, too many pixels; 413 image too large; 422 No barcode found in the image.

To ZPL

HTML to ZPL

POST /v1/tools/html-to-zpl · website tool. Turns an HTML label into monochrome ZPL graphics. The API does not render HTML itself: render the page to PNG first (e.g. a headless-browser screenshot) and send the PNG. It is converted pixel by pixel without cropping, so render it at printer resolution - widthMm / 25.4 × dpi pixels wide (100 × 50 mm at 203 dpi = 799 × 400 px).

FieldTypeDefaultNotes
pngBase64stringrequiredThe rendered HTML label as PNG, max 20 MB.
widthMm, heightMmnumberrequiredLabel size in mm, max 400.
dpiint203152, 203, 300 or 600.
thresholdLowint60Black threshold; together with thresholdHigh it defines the dither band.
thresholdHighint40Equal values give a hard black/white cut without dithering.
compressbooltrueCompress the ^GFA hex data.
base64 -w0 label.png \
  | jq -Rs '{pngBase64: ., dpi: 203, widthMm: 100, heightMm: 50}' \
  | curl -X POST https://api.zplcloud.com/v1/tools/html-to-zpl \
      -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
      --data-binary @- | jq -r .zpl > label.zpl

Response: { zpl, widthPx, heightPx, dpi, widthMm, heightMm, zplBytes }. Renders: 1. Errors: pngBase64 is required …, widthMm and heightMm are required., dpi must be 152, 203, 300 or 600., size over 400 mm; 413 PNG too large.

PDF to ZPL

POST /v1/tools/pdf-to-zpl · website tool. Converts PDF pages (shipping labels, delivery notes) into ^GFA graphics ZPL, one label per page.

FieldTypeDefaultNotes
pdfBase64stringrequiredPDF document, max 50 MB.
pagesstring"1"1, 1-3,5 or all; max 100 pages per call.
widthMm, heightMmnumberPDF page sizeLabel size in mm (max 400). Without them the size of the first PDF page is used.
usePdfSizeboolfalsetrue ignores widthMm/heightMm and uses the PDF page size.
rotateint00, 90, 180 or 270.
scalestringcontaincontain, cover, fill, fitToWidth or fitToHeight.
darknessint150 to 30, written as ^MD.
speedint22 to 12, written as ^PR.
dpiint203152, 203, 300 or 600.
offsetXmm, offsetYmmnumber-Offset in mm (0 or more).
zplOffsetbooltrueApply the offset as ^FO in the ZPL instead of shifting the bitmap.
base64 -w0 shipping-labels.pdf \
  | jq -Rs '{pdfBase64: ., pages: "all", widthMm: 101.6, heightMm: 152.4, dpi: 203, darkness: 20}' \
  | curl -X POST https://api.zplcloud.com/v1/tools/pdf-to-zpl \
      -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
      --data-binary @- | jq -r .zpl > shipping-labels.zpl

Response: { zpl, pageCount, widthMm, heightMm, widthPx, heightPx, dpi, zplBytes }. Renders: one per page (pageCount). Errors: pdfBase64 is required., pdfBase64 is not a PDF document., pages must look like "1", "1-3,5" or "all"., Too many pages (max 100 per call)., range errors for rotate, scale, darkness, speed; 413 PDF too large.

Image to ZPL

POST /v1/tools/image-to-zpl · website tool. Converts a logo or picture into ZPL: inline as ^GFA and as a ~DG download command that stores it on the printer. Transparency becomes white, the white border is cropped.

FieldTypeDefaultNotes
imageBase64stringrequiredPNG, JPG, GIF or BMP, max 20 MB and 16 megapixels.
blacknessint50Black threshold in percent, 0 to 100.
rotateint00, 90 (counter-clockwise), 180 or 270 (clockwise).
flipH, flipVboolfalseMirror horizontally / vertically (before rotating).
compressbooltrueCompress the hex data.
dpiint203Only used for the mm size in the response.
fileNamestringLOGOGRF name, up to 40 letters, digits, _ or -; .GRF is appended.
base64 -w0 logo.png \
  | jq -Rs '{imageBase64: ., blackness: 45, fileName: "LOGO"}' \
  | curl -X POST https://api.zplcloud.com/v1/tools/image-to-zpl \
      -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
      --data-binary @- > logo.json
jq -r .grf logo.json > logo-download.zpl   # store once as LOGO.GRF
jq -r .zpl logo.json > logo-inline.zpl     # or embed directly

Response: { zpl, grf, grfName, widthPx, heightPx, widthMm, heightMm, dpi, zplBytes }. Renders: 1. Errors: imageBase64 is required (PNG, JPG, GIF or BMP)., not an image, too many pixels, rotate must be 0, 90, 180 or 270., fileName may contain up to 40 letters, digits, _ or -.; 413 image too large.

SVG to ZPL

POST /v1/tools/svg-to-zpl · website tool. Rasterises SVG markup at the printer resolution and returns a complete label with the graphic at 0,0.

FieldTypeDefaultNotes
svgstringrequiredSVG markup, max 2,000,000 characters.
sizeMmnumberrequiredLength of the longer side in mm, max 400.
dpiint203152, 203, 300 or 600.
jq -Rs '{svg: ., sizeMm: 40, dpi: 203}' logo.svg \
  | curl -X POST https://api.zplcloud.com/v1/tools/svg-to-zpl \
      -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
      --data-binary @- | jq -r .zpl > logo.zpl

Response: { zpl, widthPx, heightPx, dpi, zplBytes }, zpl = ^XA^FO0,0^GFA…^FS^XZ. Renders: 1. Errors: svg is required., sizeMm is required (size of the longer side in mm)., The SVG could not be converted.; 413.

EPL2 to ZPL

POST /v1/tools/epl2-to-zpl · website tool. Converts Zebra EPL2 printer code to ZPL II.

FieldTypeDefaultNotes
codestringrequiredPrinter code, max 2,000,000 characters.
jq -Rs '{code: .}' label.epl \
  | curl -X POST https://api.zplcloud.com/v1/tools/epl2-to-zpl \
      -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
      --data-binary @- | jq -r .zpl > label.zpl

Response: { zpl, labels, zplBytes }. Renders: 1 per call, regardless of labels. Errors: code is required., The code could not be converted.; 413.

DPL to ZPL

POST /v1/tools/dpl-to-zpl · website tool. Converts Datamax / Honeywell DPL code to ZPL II. Field code, response and errors as for epl2-to-zpl.

jq -Rs '{code: .}' label.dpl \
  | curl -X POST https://api.zplcloud.com/v1/tools/dpl-to-zpl \
      -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
      --data-binary @- | jq -r .zpl > label.zpl

TSPL to ZPL

POST /v1/tools/tspl-to-zpl · website tool. Converts TSC TSPL / TSPL2 code to ZPL II. Field code, response and errors as for epl2-to-zpl.

jq -Rs '{code: .}' label.tspl \
  | curl -X POST https://api.zplcloud.com/v1/tools/tspl-to-zpl \
      -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
      --data-binary @- | jq -r .zpl > label.zpl

ZPL to other printer languages

Print ZPL on printers that do not speak ZPL. Every ^XA…^XZ label is rendered dot for dot at the printer resolution - without anti-aliasing, like a thermal print head - and written as a monochrome bitmap in the target language. Fonts, barcodes and emulation differences no longer matter: the printer only prints dots. The response is the raw print job; send it unchanged to TCP port 9100.

FieldTypeDefaultNotes
zplstringrequiredOne or more labels, max 2,000,000 characters. Each label (including ^PQ copies) becomes one label in the job.
dpiintper languageResolution of the target print head, allowed values per language below. Brother: set by model.
widthMmnumber^PW, else 75Label width in mm, max 400.
heightMmnumber^LL, else 50Label height in mm, max 400.
compressboolfalseUse the compressed image format of the language (400 if it has none).
hexboolfalseSBPL and CPCL: image data as hex text instead of binary.
cutbooltrueESC/POS and Brother: cut after each label.
paperstringa4PCL: a4 or letter.
modelstringql-820Brother: model family, see zpl-to-brother.
mediastringcontinuousBrother QL and TD-4: continuous or diecut.

Response application/octet-stream with Content-Disposition: attachment; filename=label.<ext> and the header X-ZplCloud-Label-Count. Every label counts as a render. Limits: 1,000 labels and 256 MB of uncompressed image data per call (413). Errors as for the other tools, e.g. dpi must be 203, 300, 600 for TSPL.

jq -Rs '{zpl: ., dpi: 203, compress: true}' label.zpl \
  | curl -X POST https://api.zplcloud.com/v1/tools/zpl-to-tspl \
      -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
      --data-binary @- -o label.tspl

# send the job to the printer
nc -q 1 192.168.1.50 9100 < label.tspl
ToolPrintersdpiImage commandcompress
zpl-to-tsplTSC, Printronix T-series203, 300, 600BITMAPPCX via DOWNLOAD + PUTPCX
zpl-to-epl2Zebra EPL (LP/TLP 2844 …)203, 300GW-
zpl-to-dplHoneywell, Datamax-O'Neil203, 300, 600<STX>I PCX + Y fieldalways PCX
zpl-to-sbplSATO203, 300, 600ESC GB / ESC GHPCX via ESC GP
zpl-to-cpclZebra and Honeywell mobile203CG / EGPCX via PCX
zpl-to-escposEpson TM, Star, Bixolon, Citizen180, 203GS v 0-
zpl-to-brotherBrother QL, TD-4, PTby modelraster lines g / GTIFF PackBits
zpl-to-pclHP LaserJet, PCL 5 lasers300, 600ESC*b#WTIFF PackBits (mode 2)
zpl-to-easyplugAvery Dennison, Novexx203, 300, 600#YIBRLE via #YIR
zpl-to-tpclToshiba Tec203, 300, 600{SG;…,1,…|}TOPIX ({SG;…,3,…|})
zpl-to-jscriptcab203, 300, 600d BMP + I fieldPCX via d PCX

Printing the job

The job contains binary image data: it has to reach the printer byte for byte - no text encoding, no appended line break. Four ways:

WayHowNotes
Directly to TCP 9100nc -q 1 192.168.1.50 9100 < label.tsplAny socket client that sends bytes unchanged.
zplCloud CLIzplcloud send --target 192.168.1.50 --file label.tspl
zplcloud send --usb --file label.bin
zplcloud send --target 192.168.1.50 --file label.zpl --language tspl
TCP or USB. The job extensions are sent byte-exact automatically; --language converts through this API first. From CLI v1.2.26 - see CLI docs.
POST /v1/remote-printers/{id}/raw{ "base64": "…", "fileName": "label.tspl" } or { "zpl": "^XA…", "language": "tspl", "dpi": 203 }Through the zplCloud CLI agent in the printer's network - no inbound ports. With zpl + language the cloud converts first (same fields as above, renders counted per label). Agent v1.2.22+ for TCP printers, v1.2.26+ for USB printers.
POST /v1/print/folder{ "agent", "folder", "zpl", "language": "tspl" } or { "agent", "folder", "base64", "fileName": "label.tspl" }Stores the job with its extension in an agent watch folder; the agent prints oldest-first. The folder's pattern must include the extension. Agent v1.2.26+.
jq -Rs '{zpl: ., language: "tspl", dpi: 300, compress: true}' label.zpl \
  | curl -X POST https://api.zplcloud.com/v1/remote-printers/4/raw \
      -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" --data-binary @-

{ "ok": true, "error": null, "bytes": 9842, "language": "TSPL", "labels": 1 }

ok is false with an error when the agent could not deliver the job (printer unreachable, outdated agent); 409 when no agent is online. A watch folder can also convert by itself: "convert": { "language": "tspl" } in the agent config turns every ZPL file into TSPL before printing - see watch folders.

The jobs follow the manufacturers' programming manuals and are checked by decoding them back to the bitmap. Firmware differs between models - print one test label before rolling a language out.

ZPL to TSPL

POST /v1/tools/zpl-to-tspl · website tool. SIZE in mm (TSC's 8/12/24 dots per mm, so older firmware without SIZE … dot gets the exact dot count), CLS, BITMAP 0,0,<bytes>,<height>,0,<data> with 0 = black, PRINT 1,1. GAP, BLINE and DIRECTION are not sent - the printer keeps its calibration. With compress the label goes to RAM as a 1-bit PCX (DOWNLOAD), is printed with PUTPCX and deleted with KILL.

ZPL to EPL2

POST /v1/tools/zpl-to-epl2 · website tool. Per label N, q<width>, GW0,0,<bytes>,<height>,<data> (0 = black) and P1, lines end with LF. No compression: EPL2 stores PCX graphics only in flash (GM), which would wear it out label by label.

ZPL to DPL

POST /v1/tools/zpl-to-dpl · website tool. <SOH>D (switches off immediate commands on older Datamax printers), then per label <STX>IDPZPLCLOUD with the label as a 1-bit PCX into RAM (module D), a label format <STX>L, D11, 1Y1100000000000ZPLCLOUD, Q0001, E and <STX>xDGZPLCLOUD to delete it. DPL always uses the compressed PCX path.

ZPL to SBPL

POST /v1/tools/zpl-to-sbpl · website tool. <ESC>A<ESC>A1 with the label size, then per label <ESC>A, <ESC>V0001<ESC>H0001, <ESC>GB (binary) or <ESC>GH (hex) with bytes per row and 8-dot blocks - the bitmap is padded to multiples of 8 dots, 1 = black -, <ESC>Q1<ESC>Z. With compress: <ESC>GP with a PCX, as long as it fits the 5-digit size field (99,999 bytes); larger labels fall back to GB.

ZPL to CPCL

POST /v1/tools/zpl-to-cpcl · website tool. Per label ! 0 200 200 <height> 1, PAGE-WIDTH, then bands of up to 128 non-blank rows as CG (binary) or EG (hex), 1 = black - blank rows cost nothing -, FORM and PRINT. With compress: PCX 0 0 followed by the label as a 1-bit PCX. For continuous receipt paper remove FORM.

ZPL to ESC/POS

POST /v1/tools/zpl-to-escpos · website tool. ESC @, ESC a 0, the label as GS v 0 raster bands of 256 rows (small bands keep the receive buffer of mobile models free), then GS V 66 0 (feed and cut) when cut is true. dpi 203 for most 80 mm printers (576 dots print width), 180 for the Epson TM-T88 series (512 dots).

ZPL to Brother raster

POST /v1/tools/zpl-to-brother · website tool. Brother raster mode: invalidate bytes, ESC @, per label ESC i a 01, ESC i z, ESC i M/A/K (cut), ESC i d (feed), M 02 with compress, one raster line per dot row across the full head width - mirrored, as the printer expects - and 0x0C between labels, 0x1A at the end. The label is centred on the narrowest media width of the model that fits it, using the margins from Brother's command reference. The model sets the dpi:

modelPrintersdpiHeadTIFF
ql-820QL-580N, QL-710W, QL-720NW, QL-810W, QL-820NWB300720 dotsyes
ql-800QL-570, QL-700, QL-800300720 dotsno
ql-1100QL-1050, QL-1060N, QL-1100, QL-1110NWB, QL-1115NWB3001296 dotsyes
td-4-203TD-4210D, TD-4410D, TD-4420DN203832 dotsyes
td-4-300TD-4510D, TD-4520DN, TD-4550DNWB3001280 dotsyes
pt-p750wPT-E550W, PT-P750W, PT-P710BT (tape up to 24 mm)180128 dotsyes
pt-p900PT-P900, PT-P900W, PT-P950NW, PT-P910BT (tape up to 36 mm)360560 dotsyes

media: continuous (the label length comes from the job) or diecut (the label size must match the loaded labels). P-touch tapes are always continuous and print across the tape: the label width is the printable tape width.

ZPL to PCL

POST /v1/tools/zpl-to-pcl · website tool. PJL ENTER LANGUAGE = PCL, ESC E, paper size (paper), portrait, top margin 0, unit and raster resolution = dpi; one page per label with the label at its original size 10 mm from the top left corner, rows as ESC*b#W (trailing zero bytes dropped, compress = mode 2 TIFF PackBits), blank rows as ESC*b#Y, ESC*rB and a form feed. 400 if the label does not fit the paper with a 10 mm margin.

ZPL to Easy Plug

POST /v1/tools/zpl-to-easyplug · website tool. Per label #!A1, #IMSR<width>/<length> in mm, #ERN, #T0#J0, the bitmap with #YIB<rows>/<bytes per row>/<data> (1 = black, bottom row first) and #Q1/. With compress: #YIR run-length data (pairs of white and black run lengths, identical rows with FF nn), which shrinks typical labels by about 90 %. Printers with 12 dots/mm have 305 dpi - render at 300.

ZPL to TPCL

POST /v1/tools/zpl-to-tpcl · website tool. {D<pitch>,<width>,<length>|} in 0.1 mm (pitch = length + 3 mm gap), then per label {C|}, {SG;0000,0000,<width>,<height>,1,<data>|} (1 = black) and {XS;I,0001,0002C3000|} (transmissive sensor, batch mode, no ribbon - use …C3020 for thermal transfer). With compress: graphic type 3, Toshiba's TOPIX compression, in blocks below 64 KB with the start row in dots.

ZPL to JScript

POST /v1/tools/zpl-to-jscript · website tool. Per label d BMP;ZPLCLOUD uploads the label as a 1-bit BMP to RAM (transfer between ESC . and ESC ., every ESC in the data doubled), then m m, J, S l1;0,0,<height>,<height + 3>,<width> (gap labels), I 0,0,0;ZPLCLOUD and A 1. With compress the image is a PCX (d PCX).

Barcodes & GS1

Barcode to ZPL

POST /v1/tools/barcode-to-zpl · website tool. Generates a label with one barcode, placed with a 5 mm margin.

FieldTypeDefaultNotes
symbologystringCode128Name from the table below (not case-sensitive).
datastringrequiredContent; max 128 characters for linear codes, 4,096 for QRCode, DataMatrix, Pdf417, AztecCode and MaxiCode.
dpiint203152, 203, 300 or 600.
widthMm, heightMmnumberpresetLabel size in mm (max 400); default is the preset of the symbology.
invertboolfalseWhite code on black label (^LRY).
SymbologyPreset (mm)Data rule
Code12856 × 28-
Code3956 × 28-
Code9346 × 28-
Code1156 × 28digits only
Codabar46 × 28digits and A-D
Msi40 × 28digits only
Plessey38 × 28digits only
Industrial2of553 × 28digits only
Interleaved2of554 × 28digits only, even count
Telepen40 × 28-
Pzn34 × 286 to 8 digits
Ean1344 × 3012 or 13 digits
Ean842 × 307 or 8 digits
UpcA44 × 3011 or 12 digits
UpcE48 × 306 to 8 digits
Isbn53 × 3010 or 13 digits
EanUpcAddOn2, EanUpcAddOn550 × 24-
Ean128 (GS1-128)66 × 28-
UccEan12850 × 24-
GS1DataBarExpanded34 × 28-
GS1DataBarExpandedStacked50 × 24-
Postnet52 × 22digits only
Planet60 × 22digits only
QRCode36 × 36-
DataMatrix29 × 29-
AztecCode28 × 28-
MaxiCode38 × 38-
Pdf41750 × 34-
MicroPdf41730 × 34-
CompactPdf41738 × 30-
CodablockF116 × 34digits only
Code16k69 × 30-
Code4974 × 30digits only
curl -X POST https://api.zplcloud.com/v1/tools/barcode-to-zpl \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"symbology":"Ean13","data":"400638133393","dpi":203}'

{ "zpl": "^XA…^XZ", "symbology": "Ean13", "widthMm": 44, "heightMm": 30, "dpi": 203, "zplBytes": 187 }

Renders: 1. Summary: { tool, symbology, widthMm, heightMm, dpi, zplBytes }. Errors: Unknown symbology. Known: …, data is required., data rule violations, data too long, Label size must not exceed 400 × 400 mm.

QR code to ZPL

POST /v1/tools/qr-code-to-zpl · website tool. Builds the QR content for a type from its fields and returns a square label.

FieldTypeDefaultNotes
typestringurlQR type from the table below.
fieldsobject-Field values as strings (keys not case-sensitive), max 2,000 characters each.
sizeMmnumber25Edge length of the square label, 1 to 400 mm.
dpiint203152, 203, 300 or 600.
modestringnativenative (^BQ command) or image (^GFA bitmap).
errorCorrectionstring-L, M, Q or H (native mode).
magnificationint-1 to 10 (native mode).
typefieldsEncoded content
urlurlthe URL
texttextthe text
wifissid (required), password, security (WPA default, WEP, nopass), hidden (true/1/on)WIFI:T:WPA;S:…;P:…;;
emailto, subject, bodymailto:…?subject=…&body=…
phonephonetel:…
whatsappphone, messagehttps://wa.me/<digits>?text=…
signalphonehttps://signal.me/#p/<phone>
telegramusername, messagehttps://t.me/<username>?text=…
locationlat, lnggeo:lat,lng
vcardname, phone, email, orgvCard 3.0
instagramusernamehttps://instagram.com/<username>
tiktokusernamehttps://www.tiktok.com/@<username>
snapchatusernamehttps://snapchat.com/add/<username>
facebookurl (page path)https://facebook.com/<url>
curl -X POST https://api.zplcloud.com/v1/tools/qr-code-to-zpl \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"type":"wifi","fields":{"ssid":"Warehouse","password":"Pallet-2026"},"sizeMm":30,"errorCorrection":"M"}'

{ "zpl": "^XA…^BQN,2,…^XZ", "data": "WIFI:T:WPA;S:Warehouse;P:Pallet-2026;;", "type": "wifi", "mode": "native", "sizeMm": 30, "dpi": 203, "zplBytes": 96 }

Renders: 1. Summary: { tool, type, mode, sizeMm, dpi, zplBytes }. Errors: Unknown type. Known: …, The fields for this QR type are empty. Required fields: …, sizeMm must be between 1 and 400., mode must be native or image., errorCorrection must be L, M, Q or H., magnification must be between 1 and 10., field or content too long.

GS1-128 from application identifiers

POST /v1/tools/gs1-ai-128-to-zpl · website tool. Validates GS1 application identifiers in bracket notation and generates a GS1-128 barcode. The four GS1 tools share fields, validation and errors:

FieldTypeDefaultNotes
aistringrequiredAIs in bracket notation, e.g. (01)04006381333931(17)271231(10)L-2026-0417; max 4,096 characters.
dpiint203152, 203, 300 or 600.
widthMmnumberauto / presetGS1-128 and DataBar: wide enough for the content, at least the preset (66 mm / 34 mm). 2D: preset.
heightMmnumberpresetStacked DataBar: calculated from rows and text lines.
domainstringid.gs1.orgOnly gs1-ai-qr-code-to-zpl: Digital Link domain.
variantstringsingleOnly gs1-ai-databar-to-zpl: stacked for the two-row form.
curl -X POST https://api.zplcloud.com/v1/tools/gs1-ai-128-to-zpl \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"ai":"(01)04006381333931(10)L-2026-0417"}'

{
  "zpl": "^XA…^XZ",
  "symbology": "Ean128",
  "widthMm": 66,
  "heightMm": 28,
  "dpi": 203,
  "zplBytes": 214,
  "content": "(01)04006381333931(10)L-2026-0417",
  "brackets": "(01)04006381333931(10)L-2026-0417",
  "elements": [
    { "ai": "01", "value": "04006381333931", "title": "GTIN" },
    { "ai": "10", "value": "L-2026-0417", "title": "BATCH/LOT" }
  ]
}

Every AI is checked against the GS1 catalogue: unknown AIs, duplicates, digits-only and character set 82, fixed and maximum lengths, month and day of dates, check digits. With any issue nothing is generated and the response is 400 (the error text joins the first four messages):

HTTP/1.1 400 Bad Request

{
  "error": "Check digit does not match: expected 1, found 2.",
  "tool": "gs1-ai-128-to-zpl",
  "issues": [
    { "code": "checkDigit", "ai": "01", "title": "GTIN", "message": "Check digit does not match: expected 1, found 2." }
  ],
  "requestId": "3f0c9a7e-5b1d-4c2e-9a41-7d0e6b2f8c13"
}

Issue codes: unknownAi, duplicate, empty, numeric, charset82, fixedLength, maxLength, month, day, checkDigit. Other errors: ai is required …, no AI found in the string, dpi must be 152, 203, 300 or 600. Renders: 1. Summary: { tool, symbology, widthMm, heightMm, dpi, zplBytes }.

GS1 DataMatrix from application identifiers

POST /v1/tools/gs1-ai-datamatrix-to-zpl · website tool. Same fields and validation as gs1-ai-128-to-zpl; generates a GS1 DataMatrix with FNC1 and GS separators. symbology is DataMatrix, preset 29 × 29 mm; content shows the encoded string with <GS> for the separator.

curl -X POST https://api.zplcloud.com/v1/tools/gs1-ai-datamatrix-to-zpl \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"ai":"(01)04006381333931(10)L-2026-0417(17)271231","dpi":300}' | jq -r .zpl

GS1 QR code (Digital Link) from application identifiers

POST /v1/tools/gs1-ai-qr-code-to-zpl · website tool. Same fields and validation as gs1-ai-128-to-zpl; encodes a GS1 Digital Link URL in a QR code. Optional domain (default id.gs1.org). The AIs need a primary key such as (01) GTIN, otherwise 400. symbology is QRCode, preset 36 × 36 mm; content is the URL.

curl -X POST https://api.zplcloud.com/v1/tools/gs1-ai-qr-code-to-zpl \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"ai":"(01)04006381333931(10)L-2026-0417","domain":"example.com"}' | jq -r .content

GS1 DataBar from application identifiers

POST /v1/tools/gs1-ai-databar-to-zpl · website tool. Same fields and validation as gs1-ai-128-to-zpl; generates GS1 DataBar Expanded. "variant": "stacked" (lowercase) produces the two-row form for narrow labels with the text lines set below; any other value gives the single-row form. symbology is GS1DataBarExpanded or GS1DataBarExpandedStacked.

curl -X POST https://api.zplcloud.com/v1/tools/gs1-ai-databar-to-zpl \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"ai":"(01)04006381333931(3103)001250(15)261231","variant":"stacked"}' | jq -r .zpl

Helpers

DPI calculator

POST /v1/tools/dpi-calculator · website tool. Converts between millimetres, inches, dots and points at a printer resolution. All fields are optional; the response contains only the blocks you asked for, plus a reference table.

FieldTypeDefaultResponse block
dpiint20372 to 2400; dpi, dotsPerMm, dotsPerInch
lengthMm or lengthInnumber-length { mm, inch, dots } (lengthMm wins)
dotsnumber-dots { dots, mm, inch }
labelWidthMm, labelHeightMmnumber-label { widthMm, heightMm, widthDots, heightDots }
fontPtnumber-fontPt { pt, dots }
fontDotsnumber-fontDots { dots, pt }
moduleMmnumber-moduleMm { mm, dots } (barcode module, at least 1 dot)
moduleDotsnumber-moduleDots { dots, mm }
curl -X POST https://api.zplcloud.com/v1/tools/dpi-calculator \
  -H "X-API-Key: sk_zplcloud_…" -H "Content-Type: application/json" \
  -d '{"dpi":300,"lengthMm":100,"fontPt":12,"moduleMm":0.33}'

{
  "dpi": 300,
  "dotsPerMm": 11.811,
  "dotsPerInch": 300,
  "length": { "mm": 100, "inch": 3.937, "dots": 1181 },
  "fontPt": { "pt": 12, "dots": 50 },
  "moduleMm": { "mm": 0.33, "dots": 4 },
  "reference": [
    { "dpi": 203, "dotsPerMm": 7.99, "label100x60mmDots": "799 × 480" },
    { "dpi": 300, "dotsPerMm": 11.81, "label100x60mmDots": "1181 × 709" },
    { "dpi": 600, "dotsPerMm": 23.62, "label100x60mmDots": "2362 × 1417" }
  ]
}

Renders: 1. Summary: { tool, dpi }. Errors: dpi must be between 72 and 2400.