ZPL Label Generatorv1.1.0
Renders imported or pasted ZPL II code, including .zplii files with ^GF graphics, ^FV fields, and ISO 16023 MaxiCode symbols, at one pixel per printer dot at 152 to 600 dpi, then exports ZPL, EPL, PNG, or PDF. Placeholders such as {#} substitute CSV or Excel data and carton numbering, printing a write-in blank where no value exists. Saved templates drive bulk runs from spreadsheet rows.
Everything you enter is processed on your device. This tool loads a code library from cdnjs.cloudflare.com, which sees your IP address but never what you type.
Documentation
Inputs sit in the Design column on the left, results in the Preview column on the right. The engine draws every label at one pixel per printer dot, so the preview is what a Zebra printer produces at the selected density.
- Pick a mode. Designer builds a label from stacked text lines: type the text, set its height in printer dots, toggle bold, and pick left, center, or right alignment. ZPL Code opens an existing .zpl, .zplii, .zpl2, .prn, or .txt file or accepts pasted code, so labels from other systems render unchanged where the command subset allows.
- Carrier and WMS files render with their full ZPL II command set: ^FV behaves as ^FD, ^FH turns _1E style escapes back into bytes, ^GF draws ASCII hex graphics including the run-length codes that repeat digits, fill a row, or repeat the row above, and ^LR flips the default field color. Printer setup commands such as ^MN, ^MF, ^MC, ^CV, and ^DN leave no mark on paper, so Checks lists them once as passed through instead of flagging each as a problem.
- A file that states no ^PW or ^LL is measured, not guessed: the label sizes to the marks the format makes, snapped to the nearest quarter inch, so a 4 by 6 inch shipping label comes in at 812 by 1218 dots at 203 dpi instead of being cut to whatever the Designer last held. Width and Height in Settings follow the code in this mode, keeping the dimensions line, the PDF page, and the print sheet at the raster's physical size; type over them to override. Any field still past the edge is reported in Checks with its exact overshoot in dots.
- Reorder lines with Up and Down; the ZPL and the preview follow list order. Tick Same row to place a line beside the one above rather than below: lines sharing a row split the usable width into equal columns, each keeping its own size, bold, and alignment. The first line ignores the checkbox, having nothing to sit beside. Mixed sizes in a row share a baseline, so a small country-of-origin note aligns with the bottom of a large carton number rather than its top.
- Text wider than its column wraps onto extra rows automatically and the lines below shift down. Each wrapped block emits one ^FB field whose maximum-line count matches the wrap, so the printer reflows exactly as the preview does. The Text Lines list still shows one entry per line however many rows it occupies.
- The two modes keep separate work. Code you type or open in the ZPL Code box is never touched by the Designer, and switching modes or reloading the page leaves both intact. To carry a design over for hand-editing, click Insert Generated ZPL above the box: it writes the current design as one label with its variable placeholders left intact, so {#} and named variables keep substituting after you edit. Replacing a box that already has code in it takes a second click.
- Click Generate or wait 500 milliseconds after typing for the debounced auto-render, then read Checks for anything unsupported or defaulted.
- Open Settings for the label size. A preset such as 4 x 2 in fills Width and Height, and editing either switches the preset to Custom. Both accept decimals, fractions such as 1/2, and mixed numbers such as 4 1/4, in inches or millimeters. Print density defaults to 203 dpi, Print quality chooses grayscale or bitonal, and Orientation rotates 90, 180, or 270 degrees, with 180 emitted as ^POI. Settings and each of its sections, Variables, Templates, and Bulk, reopen on your next visit exactly as you left them.
- Define variables under Settings, Variables. Names wrapped in the configurable delimiters (default { and }) substitute into designer lines and raw ZPL in real time. A CSV or Excel file populates the list: headers become names, the first data row becomes values.
- Set Step # and # of labels to number a run, as in the default Carton #{#} of {total}, and Save ZPL emits one ^XA block per label. Leave either empty and the placeholder prints as blank space sized by Write-in blank (8 spaces by default), so the number can be written on the label by hand. Any variable with an empty value behaves the same way, typed or from a CSV cell. Set Write-in blank to 0 to close those gaps.
- Line spacing multiplies the gap between rows and between wrapped rows inside one line, and is written into the ZPL as the ^FB line-spacing parameter so the printer matches the preview. 1.0 sets lines solid, 1.5 is the default, and 3.0 spreads a short label out.
- Center all lines vertically as one group is ticked by default: the whole stack moves together and keeps its spacing rather than each line centering on its own, which matters most on a label carrying only a line or two. Untick it to pin the first line to the top margin. Checks reports the dot range the text occupies and warns with the exact overshoot when it runs past the bottom edge.
- Hover the preview for exact ZPL dot coordinates; in code mode a click inserts ^FO with them at the cursor. The view buttons (Fit, 100%, Zoom In, Zoom Out, Rotate View, Reset View), the scroll wheel, and dragging to pan change the view only, never the label. Reset returns the design to defaults and refits the preview.
- Open Generated ZPL to read the exact code the exports contain, variables substituted and every numbered label included. A run too large to display holds the first label and says so underneath; the exports still carry the whole sequence. Copy Shown ZPL under the box copies exactly what is displayed, where Copy ZPL in the export row always copies the whole run.
- Every file input shows a spinner while it reads, and any export of more than one label reports Rendered label 45 of 300 under the export buttons with the buttons disabled until the file is handed over, so a long run never looks like nothing happened. Exports render one label at a time and hand the browser back between them, keeping the page responsive. PDF pages are compressed, so a 300 label run lands near 12 MB rather than several hundred.
- Save the design as a named template, reload or delete it later, and use Export Templates and Import to share the JSON. A template holds the layout, label size, density, quality, orientation, font, spacing, and delimiters, but not the variable values, Step #, or # of labels, which stay with the current run. Saving over an existing name and deleting both take a second click, since neither can be undone. An import lists what it added, what it replaced by name, and anything in the file it could not read, and an entry that is not a readable template is refused rather than stored.
- Run a batch from Bulk Multi-Label Generation. Load a CSV or Excel file whose header row names the variables and whose every following row is one label. Only the first worksheet is read, the first non-empty row is the header, and quoted fields containing commas parse correctly. A header repeated in the same row is reported, and the leftmost copy is the one that prints. Ticked templates keep their ticks while you save, delete, or import other templates.
- Columns bind to placeholders by exact match on the header text, letter case included: a column named SKU does not fill {sku}. Leading and trailing spaces are trimmed, so " sku " still binds, but an inner space is not, so a column named unit price needs {unit price}. Empty headers are ignored, and changing the delimiters changes the placeholder while the header stays the plain word. Loading the file reports the binding in the status line beneath it, before a run rather than after: which columns feed the label, any name differing only by case, any placeholder with no column, and any column the design never uses. Generate Bulk repeats that report against whichever templates are ticked, since two templates can want different columns from one file.
- Precedence runs column, then typed variable, then write-in blank; the file wins where both supply a name, and {#} and {total} always come from Step # and # of labels rather than a column. So a file of sku, desc, price against a design reading {sku}, {desc}, and Made in {origin} reports sku and desc feeding the label, price unused, and {origin} with no column: fill {origin} once under Variables to apply it to every row, add an origin column to vary it per row, or leave it for a write-in blank. An empty cell behaves as a missing column, so a partly filled spreadsheet still produces usable labels.
- Tick templates in the bulk list to render each row through more than one layout, which is how a shipping label and a contents label come off one row of data. Leave every box unticked to use the current design. Numbering multiplies the run again: 3 rows through 2 templates with # of labels 2 produces 12 labels, capped at 2000 per run.
- Choose the bulk output: one ZPL file with an ^XA block per label for sending straight to a printer, a ZIP of PNGs named by template and row, or a multi-page PDF at the exact label size. The status line reports the file name and the count, and every export leads with an unpunctuated date stamp such as 20260806 so a folder of runs sorts chronologically.
- Export the current label with Save ZPL, Save EPL (designer mode), Save PNG, Save PDF, Print, or Copy ZPL.
The rendering engine supports ^XA, ^XZ, ^PW, ^LL, ^LH, ^FO, ^FT, ^A, ^CF, ^FD, ^FV, ^FH, ^FS, ^FB, ^GB, ^GF in the ASCII hex format, ^BY, ^BC (Code 128 with a computed checksum), ^BD (MaxiCode), ^FR, ^LR, ^FW, ^CI, ^FX, ^PQ, and ^POI. ^BD is encoded for real per ISO/IEC 16023 at the true 1.11 by 1.05 inch symbol size with full Reed-Solomon error correction: modes 2 and 3 read the structured carrier block from the first 15 characters of the field data, class of service (3), country code (3), postal code (9), the layout UPS labels use, dropping to mode 3 automatically when the postal code is not numeric, while modes 4, 5, and 6 encode the whole field. Every symbol generated during development, including this page's own PNG exports, decoded byte for byte under an independent ISO 16023 reader across 1,200 randomized messages; scan a printed label before a production run all the same. Field data that cannot be encoded falls back to a block captioned MAXICODE PLACEHOLDER with an Error in Checks naming the reason, and reversing a MaxiCode with ^FR draws faithfully but Checks warns that no reader decodes white-on-black. Z64 and B64 compressed ^GF payloads need a deflate decoder the preview does not carry and are left blank. Any other command is listed in Checks rather than silently dropped, and printer-configuration commands are grouped into one line instead of one warning each.
Thermal label work spans one-off cartons, numbered case packs, and thousand-row warehouse runs. The generator covers each of these because the same design drives the ZPL text, the raster preview, and every export format, and because saved templates plus variable substitution separate the layout from the data that fills it.
- Carton Shipping Labels: Build a 4 x 2 in carton label with From, To, address, PO#, and DEPT# lines, then add Carton {#} of {total} with Step # 1 and # of labels 24 to number a full pallet in one Save ZPL pass.
- Existing ZPL Maintenance: Open a .zpl file exported from a WMS, preview it at 203 dpi without a physical printer, hover to read the dot position of a misplaced field, and click to insert a corrected ^FO at the cursor.
- Carrier Label Proofing: Open the .zplii a UPS or FedEx system produced for a shipment and read it back without burning a label. The ^FV address and reference fields, the ^GF service mark, the Code 128 tracking barcode, and the ISO 16023 MaxiCode are all reproduced for real, with Checks reporting the postal code, country, and class of service it parsed out of the carrier block, and because the file states no ^LL the label sizes itself to 4 by 6 inches instead of showing only the top third. Checks names the exact overshoot when the ^LH offset pushes a footer line past the media edge.
- Retail Shelf and Product Labels: Design a 2.25 x 1.25 in product label with {sku}, {desc}, and {price} variables, save it as a template, and let a CSV of 500 rows drive a ZIP of PNGs for the labeling line.
- Multi-Format Compliance Runs: Some trading partners want a shipping label and a content label per carton. Check both saved templates in Bulk so each data row renders through every checked layout with the same details.
- Printer Fleet Differences: Preview the same design at 203 dpi for a ZT230 and at 300 dpi for a ZD621 by switching Print density; dot dimensions in the Final dimensions line update so field positions can be verified per fleet.
- Driverless Printing: Copy ZPL puts raw code on the clipboard for lpr, netcat to port 9100, or a print utility, while Save PDF produces a page at the exact physical label size for driver-based printing.
- Label Archival and Sharing: Export Templates writes every saved layout to one JSON file for version control or a coworker, and Import merges the file on any machine, since inputs also persist locally between sessions.
- Proofing Before Production: Switch Print quality to bitonal to see the pure black and white output a thermal head produces, catching gray antialiased edges that would dither or vanish on real media.
Always verify a generated label by scanning a printed one before you commit to a run. The preview and the PNG, PDF, and print exports are a software simulation of what a thermal printer puts on media; they are not a print quality grade. Every barcode and MaxiCode symbol is built to its published specification and machine-checked here, but that verifies the encoded data, not the printed result. Printer model, print head wear, darkness setting, ribbon, label stock, and scale all decide whether a symbol reads on the line even when the data underneath it is correct. Re-scan whenever any of those change, whenever a label design changes, and on the first label of a new batch. Where a carrier or trading partner requires a graded label, use a barcode verifier that reports an ISO/IEC 15416 or 15415 grade rather than relying on this tool or on a single successful scan.
Inputs, outputs, and what the ZPL Label Generator computes
The form above accepts the following inputs and produces the outputs listed below. This summary is rendered in the page so the parameters are visible to crawlers, assistive tech, and indexing agents that don't fetch the embedded tool frame.
Inputs
- Designer (text lines) · default: designer
- ZPL Code (open existing file) · default: code
- Step # (numeric input) · minimum: 0
- # of labels (numeric input) · minimum: 1
- Write-in blank (spaces) (numeric input) · default: 8 · range: 0 to 40
- Or paste ZPL code (variables in delimiters substitute in real time)
- Size preset · default: 4 x 2 in (shipping)
- Width (text input) · default: 4
- Height (text input) · default: 2
- Inches · default: in
- Millimeters · default: mm
- Print density · default: 203 dpi (8 dpmm)
- Grayscale (smooth preview) · default: grayscale
- Bitonal (pure black and white, thermal simulation) · default: bitonal
- Orientation · default: Normal
- Preview font · default: Helvetica (sans-serif, closest to Zebra CG Triumvirate)
- Line spacing (numeric input) · default: 1.5 · range: 1 to 4
- Center all lines vertically as one group
- Delimiter start (text input) · default: {
- Delimiter end (text input) · default: }
- Template name (text input)
- Saved templates
- Output · default: Single ZPL file (one ^XA block per label)
- ZPL sent to exports (variables substituted)
Controls
Generate · Reset · Export Templates (JSON) · Generate Bulk · Reset View · Copy Shown ZPL · Copy ZPL
Worked example
Click Generate or wait 500 milliseconds after typing for the debounced auto-render, then read Checks for anything unsupported or defaulted.