DEVELOPERS / C# / ZPL
Print ZPL Labels From C# and .NET
Two ways to print labels from C#: raw ZPL over TcpClient to port 9100, or the LabelInn .NET SDK — print to any printer from any server, with queueing, status and templates.
using System.Net.Sockets;
using System.Text;
var zpl = "^XA^FO50,50^A0N,40,40^FDHello from LabelInn^FS^XZ";
using var tcp = new TcpClient();
await tcp.ConnectAsync("192.168.1.50", 9100);
await tcp.GetStream().WriteAsync(Encoding.UTF8.GetBytes(zpl));THE PROBLEM
You need C# code to put a label on a thermal printer: a shipping label when an order is paid, a product label when a batch is finished. There are two ways to do it. This page shows both, with code you can paste.
01 / C#
The quick way: raw ZPL to port 9100
Zebra printers, and most printers that emulate ZPL, accept raw ZPL on TCP port 9100. If your code runs on the same network as the printer, this is all it takes:
using System.Net.Sockets;
using System.Text;
var zpl = "^XA^FO50,50^A0N,40,40^FDHello from LabelInn^FS^XZ";
using var tcp = new TcpClient();
await tcp.ConnectAsync("192.168.1.50", 9100);
await tcp.GetStream().WriteAsync(Encoding.UTF8.GetBytes(zpl));02 / ZPL
Why not just open a socket?
Writing ZPL to port 9100 works on the bench. In production it leaves you with problems the printer will not solve for you:
- Your server has to reach the printer. A cloud-hosted C# app cannot open a socket to a printer on a warehouse LAN without a VPN or port forwarding.
- Nothing tells you it printed. Port 9100 accepts the bytes whether or not the ribbon is out or the head is open.
- Nothing queues. If the printer is off, the job is gone.
- One language per printer. ZPL works on Zebra; TSC wants TSPL, Toshiba wants TPCL.
LabelInn puts a small runtime next to the printer that connects out to the cloud. Your code calls one HTTPS API from anywhere; the job is queued, delivered in the printer's own language, and its status comes back.
📦 dotnet add package LabelInn, one API key, and your C# code prints to any registered printer, anywhere. Get a key →
03 / ZEBRA
Install the SDK
dotnet add package LabelInn04 / API
Find the printer
Register the printer once in the LabelInn app on the computer it is connected to. Then list your printers to get the id:
using LabelInn;
using var client = new LabelInnClient("sk_live_...");
foreach (var p in await client.Fleet.ListAsync())
Console.WriteLine($"{p.Id} {p.Name} {p.Status}");05 / C#
Print ZPL
var job = await client.Print.CreateAsync(new CreateJobRequest
{
PrinterId = "prt_abc123",
PayloadType = "zpl",
PayloadData = "^XA^FO50,50^A0N,40,40^FDHello from LabelInn^FS^XZ",
});
Console.WriteLine($"{job.Id} {job.Status}");06 / ZPL
Print a designed label with data
Raw ZPL means your code owns the layout. With a template, the label is designed visually in LabelInn and your code sends only the data. Fields fill by name, and LabelInn converts the design to ZPL, TSPL or TPCL for whichever printer you choose.
var job = await client.Print.CreateAsync(new CreateJobRequest
{
PrinterId = "prt_abc123",
PayloadType = "template",
DesignId = "dsg_shipping",
Data = new { order_id = "ORD-9876", customer = "Jane Doe", barcode = "TR123456789" },
Copies = 2,
});07 / ZEBRA
Print many labels in one call
Batch up to 100 jobs per request. Each job is accepted or rejected on its own, so one bad row does not sink the rest.
var skus = new[] { "A-1001", "A-1002", "A-1003" };
var result = await client.Print.BatchAsync(skus.Select(sku => new CreateJobRequest
{
PrinterId = "prt_abc123",
PayloadType = "template",
DesignId = "dsg_product",
Data = new { sku },
}));
Console.WriteLine($"{result.Succeeded} of {result.Total} accepted");08 / API
Never print the same label twice
Retries happen: a timeout, a redeploy, a queue redelivery. Send an idempotency key and a repeated call returns the original job instead of printing again.
var job = await client.Print.CreateAsync(new CreateJobRequest
{
PrinterId = "prt_abc123",
PayloadType = "template",
DesignId = "dsg_shipping",
Data = new { order_id = "ORD-9876" },
}, idempotencyKey: "order-ORD-9876-label");Printing through the API is part of the Pro plan, and the free trial includes it. Keys that start with sk_test_ run against a sandbox that never prints, so you can build and test before going live. See pricing.
09 / C#
Same thing, other languages
QUESTIONS / FAQ
Frequently asked questions
How do I print a ZPL label from C#?
On the same network, write the ZPL to the printer's TCP port 9100. From anywhere else, install the LabelInn SDK, register the printer once, and call print.create with payload_type "zpl" and the printer id.
Can my cloud-hosted C# app print to a printer in a warehouse?
Yes. The LabelInn runtime next to the printer connects out to LabelInn, so your server calls an HTTPS API and never needs network access to the printer itself.
Does it only work with Zebra printers?
No. Raw ZPL needs a ZPL printer, but templates are converted to the printer's own language, including TSPL for TSC and TPCL for Toshiba.
How do I avoid printing duplicates when a request is retried?
Send an idempotency key with the job. Repeating the call with the same key returns the original job instead of printing again.
KEEP GOING
Related
NEXT STEP / LABELINN
Print from C# without touching a printer driver
Get an API key, register a printer, and send your first label in minutes. · Official SDK · ZPL or visual templates · Queue, status and retries handled