The Labelary ZPL rendering engine is available as an online service, and can be invoked via a simple, easy-to-use RESTful API:
GET http://api.labelary.com/v1/printers/{dpmm}/labels/{width}x{height}/{index}/{zpl}
By default the service returns PNG images, but a variety of output formats are available:
POST http://api.labelary.com/v1/printers/{dpmm}/labels/{width}x{height}/{index}
You can also use POST instead of GET by moving the ZPL out of the URL and into the POST request body. When using POST, the request Content-Type may be either:
See below for examples of both approaches.
The POST HTTP method is useful when:
As a shared service, the Labelary API incorporates a number of usage limits which ensure that no single user can negatively impact the workloads of other users:
The image conversion service (image → ZPL) also has the following limits:
The font conversion service (TTF font → ZPL) also has the following limits:
Note that these limits may be changed as needed in order to ensure smooth operation of the service for all users.
If these limits are too restrictive for your intended use, you may want to consider licensing Labelary for private on-premise use.
The code snippets and examples below are intended to help you start consuming the Labelary API quickly, regardless of your client-side technology stack. If you have a code sample that uses a different technology stack, and you'd like to share it with other Labelary users, feel free to email us.
Some live examples that use GET requests to convert the ZPL encoded in the URLs into PNG images:
Using the GET method:
curl --get http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/ --data-urlencode "^xa^cfa,50^fo100,100^fdHello World^fs^xz" > label.png
Using the POST method (with application/x-www-form-urlencoded content):
curl --request POST http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/ --data "^xa^cfa,50^fo100,100^fdHello World^fs^xz" > label.png
Using the POST method (with multipart/form-data content):
curl --request POST http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/ --form file=@label.zpl > label.png
Using the POST method (with multipart/form-data content), requesting a PDF file instead of a PNG image:
curl --request POST http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/ --form file=@label.zpl --header "Accept: application/pdf" > label.pdf
You can also test the Labelary API by importing this request collection into Postman and running any of the requests therein.
Using the POST method (with application/x-www-form-urlencoded content) to request a PNG image:
Invoke-RestMethod `
-Method Post `
-Uri http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/ `
-ContentType "application/x-www-form-urlencoded" `
-InFile label.zpl `
-OutFile label.png
Using the POST method (with application/x-www-form-urlencoded content) to request a PDF file:
Invoke-RestMethod `
-Method Post `
-Uri http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/ `
-ContentType "application/x-www-form-urlencoded" `
-Headers @{"Accept" = "application/pdf"} `
-InFile label.zpl `
-OutFile label.pdf
A Java example that uses the Java 11 HttpClient API to send a POST request to convert a ZPL string to a PDF file:
var zpl = "^xa^cfa,50^fo100,100^fdHello World^fs^xz";
// adjust print density (8dpmm), label width (4 inches), label height (6 inches), and label index (0) as necessary
var uri = URI.create("http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/");
var request = HttpRequest.newBuilder(uri)
.header("Accept", "application/pdf") // omit this line to get PNG images back
.POST(BodyPublishers.ofString(zpl))
.build();
var client = HttpClient.newHttpClient();
var response = client.send(request, BodyHandlers.ofByteArray());
var body = response.body();
if (response.statusCode() == 200) {
var file = new File("label.pdf"); // change file name for PNG images
Files.write(file.toPath(), body);
} else {
var errorMessage = new String(body, StandardCharsets.UTF_8);
System.out.println(errorMessage);
}
A Python example that uses the Requests library to send a POST request to convert a ZPL string to a PDF file:
import requests
import shutil
zpl = '^xa^cfa,50^fo100,100^fdHello World^fs^xz'
# adjust print density (8dpmm), label width (4 inches), label height (6 inches), and label index (0) as necessary
url = 'http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/'
files = {'file' : zpl}
headers = {'Accept' : 'application/pdf'} # omit this line to get PNG images back
response = requests.post(url, headers = headers, files = files, stream = True)
if response.status_code == 200:
response.raw.decode_content = True
with open('label.pdf', 'wb') as out_file: # change file name for PNG images
shutil.copyfileobj(response.raw, out_file)
else:
print('Error: ' + response.text)
A Ruby example that uses a POST request to convert a ZPL string to a PDF file (courtesy Robert Coleman):
require 'net/http'
zpl = '^xa^cfa,50^fo100,100^fdHello World^fs^xz'
# adjust print density (8dpmm), label width (4 inches), label height (6 inches), and label index (0) as necessary
uri = URI 'http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/'
http = Net::HTTP.new uri.host, uri.port
request = Net::HTTP::Post.new uri.request_uri
request.body = zpl
request['Accept'] = 'application/pdf' # omit this line to get PNG images back
response = http.request request
case response
when Net::HTTPSuccess then
File.open 'label.pdf', 'wb' do |f| # change file name for PNG images
f.write response.body
end
else
puts "Error: #{response.body}"
end
A Node.js example that uses a POST request to convert a ZPL string to a PDF file (courtesy Katy LaVallee):
var fs = require('fs');
var request = require('request');
var zpl = "^xa^cfa,50^fo100,100^fdHello World^fs^xz";
var options = {
encoding: null,
formData: { file: zpl },
// omit this line to get PNG images back
headers: { 'Accept': 'application/pdf' },
// adjust print density (8dpmm), label width (4 inches), label height (6 inches), and label index (0) as necessary
url: 'http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/'
};
request.post(options, function(err, resp, body) {
if (err) {
return console.log(err);
}
var filename = 'label.pdf'; // change file name for PNG images
fs.writeFile(filename, body, function(err) {
if (err) {
console.log(err);
}
});
});
A D language example that uses a POST request to convert a ZPL string to a PDF file (courtesy Andrea Freschi):
import std.stdio;
import std.net.curl;
// adjust print density (8dpmm), label width (4 inches), label height (6 inches), and label index (0) as necessary
auto url = "http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/";
auto zpl = "^xa^cfa,50^fo100,100^fdHello World^fs^xz";
void main() {
auto conn = HTTP();
conn.addRequestHeader("Accept", "application/pdf"); // omit this line to get PNG images back
auto label = url.post!ubyte(zpl, conn);
if (conn.statusLine.code == 200) {
label.toFile("label.pdf"); // change file name for PNG images
} else {
writeln(conn.statusLine.toString());
}
}
A C# example that uses a POST request to convert a ZPL string to a PDF file:
byte[] zpl = Encoding.UTF8.GetBytes("^xa^cfa,50^fo100,100^fdHello World^fs^xz");
// adjust print density (8dpmm), label width (4 inches), label height (6 inches), and label index (0) as necessary
var request = (HttpWebRequest) WebRequest.Create("http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/");
request.Method = "POST";
request.Accept = "application/pdf"; // omit this line to get PNG images back
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = zpl.Length;
var requestStream = request.GetRequestStream();
requestStream.Write(zpl, 0, zpl.Length);
requestStream.Close();
try {
var response = (HttpWebResponse) request.GetResponse();
var responseStream = response.GetResponseStream();
var fileStream = File.Create("label.pdf"); // change file name for PNG images
responseStream.CopyTo(fileStream);
responseStream.Close();
fileStream.Close();
} catch (WebException e) {
Console.WriteLine("Error: {0}", e.Status);
}
A VB.NET example that uses a POST request to convert a ZPL string to a PDF file:
Dim zpl() As Byte = Encoding.UTF8.GetBytes("^xa^cfa,50^fo100,100^fdHello World^fs^xz")
' adjust print density (8dpmm), label width (4 inches), label height (6 inches), and label index (0) as necessary
Dim request As HttpWebRequest = WebRequest.Create("http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/")
request.Method = "POST"
request.Accept = "application/pdf" ' omit this line to get PNG images back
request.ContentType = "application/x-www-form-urlencoded"
request.ContentLength = zpl.Length
Dim requestStream As Stream = request.GetRequestStream()
requestStream.Write(zpl, 0, zpl.Length)
requestStream.Close()
Try
Dim response As HttpWebResponse = request.GetResponse()
Dim responseStream As Stream = response.GetResponseStream()
Dim fileStream As Stream = File.Create("label.pdf") ' change file name for PNG images
responseStream.CopyTo(fileStream)
responseStream.Close()
fileStream.Close()
Catch e As WebException
Console.WriteLine("Error: {0}", e.Status)
End Try
A ColdFusion example that uses a POST request to convert a ZPL string to a PDF file:
<cfoutput>
<cfset zpl="^xa^cfa,50^fo100,100^fdHello World^fs^xz">
<!-- change type to "image/png" to get PNG images -->
<cfset type="application/pdf">
<!-- adjust print density (8dpmm), label width (4 inches), label height (6 inches), and label index (0) as necessary -->
<cfhttp url="http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/" method="post" result="result">
<cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded">
<cfhttpparam type="header" name="Accept" value="#type#">
<cfhttpparam type="body" value="#zpl#">
</cfhttp>
<cfcontent variable="#result.Filecontent#" type="#type#" reset="true" />
</cfoutput>
A PHP example that uses a POST request to convert a ZPL string to a PDF file:
<?php
$zpl = "^xa^cfa,50^fo100,100^fdHello World^fs^xz";
$curl = curl_init();
// adjust print density (8dpmm), label width (4 inches), label height (6 inches), and label index (0) as necessary
curl_setopt($curl, CURLOPT_URL, "http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/");
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $zpl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Accept: application/pdf")); // omit this line to get PNG images back
$result = curl_exec($curl);
if (curl_getinfo($curl, CURLINFO_HTTP_CODE) == 200) {
$file = fopen("label.pdf", "w"); // change file name for PNG images
fwrite($file, $result);
fclose($file);
} else {
print_r("Error: $result");
}
curl_close($curl);
?>
A Rust example that uses Reqwest to send a POST request to convert a ZPL string to a PDF file:
use reqwest::Client;
use std::io::Cursor;
use std::fs::File;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let zpl = "^xa^cfa,50^fo100,100^fdHello World^fs^xz";
// adjust print density (8dpmm), label width (4 inches), label height (6 inches), and label index (0) as necessary
let url = "http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/";
let response = Client::new()
.post(url)
.body(zpl)
.header("Accept", "application/pdf") // omit this line to get PNG images back
.send().await?;
if response.status().is_success() {
let mut file = File::create("label.pdf")?; // change file name for PNG images
let mut content = Cursor::new(response.bytes().await?);
std::io::copy(&mut content, &mut file)?;
} else {
let error_message = response.text().await?;
eprintln!("{}", error_message);
}
Ok(())
}
A Go language example that uses a POST request to convert a ZPL string to a PDF file:
package main
import (
"os"
"io"
"io/ioutil"
"log"
"bytes"
"net/http"
)
func main() {
zpl := []byte("^xa^cfa,50^fo100,100^fdHello World^fs^xz")
// adjust print density (8dpmm), label width (4 inches), label height (6 inches), and label index (0) as necessary
req, err := http.NewRequest("POST", "http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/", bytes.NewBuffer(zpl))
if err != nil {
log.Fatalln(err)
}
req.Header.Set("Accept", "application/pdf") // omit this line to get PNG images back
client := &http.Client{}
response, err := client.Do(req)
if err != nil {
log.Fatalln(err)
}
defer response.Body.Close()
if response.StatusCode == http.StatusOK {
file, err := os.Create("label.pdf") // change file name for PNG images
if err != nil {
log.Fatalln(err)
}
defer file.Close()
io.Copy(file, response.Body)
} else {
body, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatalln(err)
}
log.Fatalln(string(body))
}
}
An Excel VBA example that converts all ZPL templates in column A into PNG label images, and adds the images to column B:
Sub Convert()
'adjust print density (8dpmm), label width (4 inches), label height (6 inches), and label index (0) as necessary
u = "http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/"
tempFile = Environ("Temp") & "\excel-label-temp.png"
Set ws = ActiveWorkbook.Sheets("Sheet1")
Set http = CreateObject("MSXML2.ServerXMLHTTP")
Set stream = CreateObject("ADODB.Stream")
stream.Type = 1 'adTypeBinary
For Each rw In ws.UsedRange.Rows
zpl = ws.Cells(rw.Row, 1).Value
http.Open "POST", u, False
http.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
http.Send zpl
If http.Status = 200 Then
stream.Open
stream.Write http.responseBody
stream.SaveToFile tempFile, 2 'adSaveCreateOverWrite
stream.Close
rw.RowHeight = 200
Set pic = ws.Shapes.AddPicture(tempFile, False, True, 1, 1, 1, 1)
pic.Left = ws.Cells(rw.Row, 2).Left
pic.Top = ws.Cells(rw.Row, 2).Top
pic.Width = ws.Cells(rw.Row, 2).Width
pic.Height = ws.Cells(rw.Row, 2).Height
Else
ws.Cells(rw.Row, 2).Value = http.ResponseText
End If
Next rw
End Sub
Some advanced features provided by the Labelary API:
Your ZPL template already defines a label rotation / orientation. Sometimes, however, the label orientation that is most suitable for your printer is not the orientation that you'd like to use during format conversion.
If this is the case, you can ask Labelary to rotate the label image by adding a X-Rotation HTTP header to the request. The value of this header should be the number of degrees to rotate the label clockwise, and may be one of 0, 90, 180 or 270.
When requesting a PNG image, you can only get one label back at a time, even if your ZPL defines multiple labels. However, PDF files can contain more than one label. If you are requesting a PDF file and you would like it to contain all of the labels defined in your ZPL template, simply omit the index parameter from the request URL.
For example, instead of sending your request to this URL, which returns the label at index 0 (the first label):
http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/
You can omit the index and instead send your request to this URL:
http://api.labelary.com/v1/printers/8dpmm/labels/4x6/
Note that this option is only available for PDF requests.
By default, Labelary generates PDFs whose page size matches the label size. However, you may want to generate PDFs with a different page size. If this is the case, you can add the X-Page-Size and X-Page-Orientation HTTP headers to your request.
The X-Page-Size HTTP header tells Labelary to use a specific PDF page size. Valid values are Letter, Legal, A4, A5 and A6.
The X-Page-Orientation HTTP header tells Labelary to use a specific orientation of the specified page size. Valid values are Portrait and Landscape.
Note that these headers can only be used with PDF requests.
If you customize the PDF page size, you may also want to include multiple labels on each page. If this is the case, you can add the X-Page-Layout, X-Page-Align and X-Page-Vertical-Align HTTP headers to your request.
The X-Page-Layout HTTP header tells Labelary to lay out the labels on the PDF pages in a tabular format. The header value must be in the form <columns>x<rows>. For example, a value of 2x3 would generate a PDF file with 6 labels per page, arranged in 2 columns and 3 rows.
The X-Page-Align HTTP header tells Labelary how to align the labels horizontally. Valid values are Left, Right, Center and Justify. The default value is Justify, which distributes extra horizontal whitespace evenly across the page.
The X-Page-Vertical-Align HTTP header tells Labelary how to align the labels vertically. Valid values are Top, Bottom, Center and Justify. The default value is Justify, which distributes extra vertical whitespace evenly across the page.
Note that these headers can only be used with PDF requests.
Sometimes your ZPL code may define multiple labels. If you want to know how many labels were generated by your ZPL, you can read the value of the X-Total-Count HTTP response header returned by Labelary. The value of this header will be accurate regardless of whether you requested that a single label be rendered (as in a PNG conversion) or you requested that all labels be rendered (as in some PDF conversions).
By default, Labelary generates 8-bit grayscale PNG images optimized for electronic viewing. However, you can add the X-Quality HTTP header to your request in order to customize the quality of the output images. Valid values are Grayscale and Bitonal.
Grayscale generates 8-bit grayscale images suitable for electronic viewing and printing on high-density printers. This is the default setting.
Bitonal generates 1-bit monochrome images suitable for printing on low-density printers. It also generates smaller files (useful when file size is more important than output quality).
This header is only available for PNG requests.
It is possible to ask Labelary to check your ZPL for potential errors while rendering the ZPL. This process is known as linting. You can enable the Labelary linter by adding the X-Linter HTTP header to your request. Valid values are On (to enable the linter), and Off (to disable the linter). The linter is disabled by default.
Once the linter is enabled, warnings will be returned in the X-Warnings HTTP response header. The maximum number of warnings that will be returned is 20. Additional warnings (if any) will not be returned. Warnings will be returned in pipe-delimited format, and each warning will include 5 attributes:
As an example, the following HTTP response header indicates that the submitted ZPL generated 2 warnings:
X-Warnings: 303|1|^GB|2|Value 1 is less than minimum value 3; used 3 instead|591|3|||Ignored unrecognized content
The first warning, starting at byte index 303 and extending for 1 byte, indicates that the second parameter of the ^GB command used a value that was too small. The second warning, starting at byte index 591 and extending for 3 bytes, indicates that some unrecognized content was found between ZPL commands. The command name and parameter number for the second warning are empty, since the warning was not generated inside any specific ZPL command.
EXPERIMENTAL: This option is experimental and may be removed or significantly changed based on feedback.
In some cases you may wish to extract data from your ZPL for further processing. In these scenarios it is possible to ask Labelary to provide a list of output labels and data fields in JSON format by simply sending an Accept: application/json HTTP request header.
The resultant JSON will contain all text displayed on the labels. It will not contain information about lines, rectangles, circles, or other graphics. The output JSON will contain the human-readable text for any barcodes, but will not contain the actual data encoded in the barcode symbols. Barcodes without human-readable text above or below the barcode will therefore not be included in the generated JSON. The order of the data fields in the output JSON will always match the field definition order in the ZPL.
Specific data fields can be found based on:
Below is an example input ZPL template which defines two labels, each of which contains two data fields, and the corresponding output JSON:
^XA
^FT50,50^A0,50^FDField 1^FS
^FT50,150^A0,50^FDField 2^FS
^XZ
^XA
^FT50,50^A0,50^FDField 3^FS
^FT50,150^A0,50^FDField 4^FS
^XZ
{
"labels": [
{ "fields": [ { "x": 50, "y": 50, "data": "Field 1" }, { "x": 50, "y": 150, "data": "Field 2" } ] },
{ "fields": [ { "x": 50, "y": 50, "data": "Field 3" }, { "x": 50, "y": 150, "data": "Field 4" } ] }
]
}
In addition to conversion from ZPL to other file formats, the Labelary API also provides a few other useful endpoints:
You can convert images to ZPL graphics by using the following API endpoint:
POST http://api.labelary.com/v1/graphics
The submitted Content-Type must be multipart/form-data, with a file parameter containing the image to be converted.
By default, this endpoint returns ZPL, but the following output formats are available:
The following sample curl command converts a local file named image.png to ZPL graphics:
curl --request POST http://api.labelary.com/v1/graphics --form file=@image.png > image.zpl
The following sample curl command converts a local file named image.png to EPL format:
curl --request POST http://api.labelary.com/v1/graphics --form file=@image.png --header "Accept: application/epl" > image.epl
You can convert TrueType font files to ZPL font commands by using the following API endpoint:
POST http://api.labelary.com/v1/fonts
The submitted Content-Type must be multipart/form-data, with the following parameters:
If no path is provided, a printer path is chosen for you automatically. If no name is provided, a shorthand font name is not associated with the font.
The chars parameter allows you to subset the font. Subsetting is the process of limiting the number of characters that the font is able to render in order to reduce its size. For example, if you plan to use your custom font to print only numbers, then setting chars to 0123456789 will subset the font accordingly, yielding a much smaller ZPL snippet. Note that some fonts do not allow subsetting. If you try to subset a font which does not allow it, you will receive an error.
IMPORTANT: Always check your font license to make sure that your intended use falls within the terms of the license.
The following sample curl command converts a local font file named Montserrat-Bold.ttf to ZPL font format:
curl --request POST http://api.labelary.com/v1/fonts --form file=@Montserrat-Bold.ttf > font.zpl
The following sample curl command converts a local font file named Montserrat-Bold.ttf to ZPL font format, configures a shorthand font name for the font, and subsets the font to be able to print only uppercase letters:
curl --request POST http://api.labelary.com/v1/fonts --form file=@Montserrat-Bold.ttf --form name=Z --form chars=ABCDEFGHIJKLMNOPQRSTUVWXYZ > font.zpl