<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: labelixa</title>
    <description>The latest articles on DEV Community by labelixa (@labelixa).</description>
    <link>https://dev.to/labelixa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4139568%2Ffed16e0e-f15d-4e34-b743-5f7cb53ee156.png</url>
      <title>DEV Community: labelixa</title>
      <link>https://dev.to/labelixa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/labelixa"/>
    <language>en</language>
    <item>
      <title>Your ZPL label printed wrong. It's almost always one of these 5 things</title>
      <dc:creator>labelixa</dc:creator>
      <pubDate>Wed, 23 Sep 2026 13:34:31 +0000</pubDate>
      <link>https://dev.to/labelixa/your-zpl-label-printed-wrong-its-almost-always-one-of-these-5-things-4d41</link>
      <guid>https://dev.to/labelixa/your-zpl-label-printed-wrong-its-almost-always-one-of-these-5-things-4d41</guid>
      <description>&lt;p&gt;A ZPL printer almost never reports an error — it prints &lt;em&gt;something&lt;/em&gt;, and&lt;br&gt;
the something is wrong. That silence is why label bugs feel mysterious.&lt;br&gt;
In practice most wrong labels come down to one of five causes, and each&lt;br&gt;
leaves a recognisable fingerprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. It prints too small or too large
&lt;/h2&gt;

&lt;p&gt;ZPL coordinates are &lt;strong&gt;dots&lt;/strong&gt;, and a dot's physical size depends on the&lt;br&gt;
printer's density. Code written for an 8 dpmm (203 dpi) printer covers&lt;br&gt;
only two-thirds of the space on a 12 dpmm (300 dpi) one. Nothing is&lt;br&gt;
"broken" — the same numbers simply mean fewer millimetres. Check the&lt;br&gt;
printer's density and preview at that same density.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Fields run into each other, half the label is gone
&lt;/h2&gt;

&lt;p&gt;The classic cause is a missing &lt;code&gt;^FS&lt;/code&gt;. The field never closes, so the&lt;br&gt;
commands that follow are treated as its continuation, and everything&lt;br&gt;
after the gap collapses into one broken field. A linter points at the&lt;br&gt;
exact line; on paper you only see the aftermath.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Content disappears near the edges
&lt;/h2&gt;

&lt;p&gt;A field positioned beyond the label bounds — an &lt;code&gt;^FO&lt;/code&gt; past &lt;code&gt;^PW&lt;/code&gt;&lt;br&gt;
(width) or &lt;code&gt;^LL&lt;/code&gt; (length) — is clipped &lt;strong&gt;without any warning&lt;/strong&gt;. This&lt;br&gt;
typically appears after reusing a template on a smaller label. The fix&lt;br&gt;
is not nudging coordinates until it looks right: set &lt;code&gt;^PW&lt;/code&gt;/&lt;code&gt;^LL&lt;/code&gt; to the&lt;br&gt;
real label size and check what overflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The layout drifts from label to label
&lt;/h2&gt;

&lt;p&gt;If &lt;code&gt;^PW&lt;/code&gt; and &lt;code&gt;^LL&lt;/code&gt; are missing entirely, the printer falls back to&lt;br&gt;
whatever it was last configured for — so the same file prints&lt;br&gt;
differently on different machines, or even on the same machine after&lt;br&gt;
someone else's job. Always declare both.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Special characters print as garbage
&lt;/h2&gt;

&lt;p&gt;Accented and non-Latin characters (ü, ğ, ß…) need a character-set&lt;br&gt;
declaration. Without it the printer may interpret the bytes with a&lt;br&gt;
legacy code page. Declare UTF-8 with &lt;code&gt;^CI28&lt;/code&gt; at the start of the&lt;br&gt;
format; for characters that cannot travel safely in the data stream,&lt;br&gt;
use &lt;code&gt;^FH&lt;/code&gt; hex escapes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Find the cause without wasting labels
&lt;/h2&gt;

&lt;p&gt;Every one of these is visible &lt;strong&gt;before&lt;/strong&gt; printing: render the file at&lt;br&gt;
your printer's density, at the real label size, and read the&lt;br&gt;
diagnostics. I use &lt;a href="https://labelixa.com/tools/zpl-preview" rel="noopener noreferrer"&gt;Labelixa's viewer&lt;/a&gt;&lt;br&gt;
(disclosure: I work on it) — paste the ZPL, pick the density, and the&lt;br&gt;
linter flags the missing &lt;code&gt;^FS&lt;/code&gt; and clipped fields for you. One screen&lt;br&gt;
check replaces a strip of test labels.&lt;/p&gt;

</description>
      <category>zpl</category>
      <category>debugging</category>
      <category>barcode</category>
      <category>printing</category>
    </item>
    <item>
      <title>Send raw ZPL to a Zebra printer with zero drivers (port 9100)</title>
      <dc:creator>labelixa</dc:creator>
      <pubDate>Wed, 23 Sep 2026 13:34:14 +0000</pubDate>
      <link>https://dev.to/labelixa/send-raw-zpl-to-a-zebra-printer-with-zero-drivers-port-9100-5fi7</link>
      <guid>https://dev.to/labelixa/send-raw-zpl-to-a-zebra-printer-with-zero-drivers-port-9100-5fi7</guid>
      <description>&lt;p&gt;A ZPL file does not need a driver to be printed. Most networked thermal&lt;br&gt;
printers listen on &lt;strong&gt;TCP port 9100&lt;/strong&gt; ("raw" / "JetDirect" printing) and&lt;br&gt;
treat everything that arrives there as printer commands. Printing a&lt;br&gt;
label is just moving bytes to a socket.&lt;/p&gt;
&lt;h2&gt;
  
  
  Linux / macOS
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc 192.168.1.50 9100 &amp;lt; label.zpl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's it. netcat, no CUPS queue, nothing to configure.&lt;/p&gt;
&lt;h2&gt;
  
  
  Windows
&lt;/h2&gt;

&lt;p&gt;PowerShell opens the same socket without extra tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;New-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Net.Sockets.TcpClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'192.168.1.50'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;IO.File&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;ReadAllBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'label.zpl'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetStream&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  From code
&lt;/h2&gt;

&lt;p&gt;Any language with TCP sockets can print. Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;192.168.1.50&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;label.zpl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The catch: 9100 gives you no feedback
&lt;/h2&gt;

&lt;p&gt;There is no response protocol in the simple case. The socket closing&lt;br&gt;
without an error means the printer &lt;strong&gt;accepted the bytes&lt;/strong&gt; — not that&lt;br&gt;
the label printed correctly. Density mismatches and layout bugs are&lt;br&gt;
invisible here. So preview first: paste the ZPL into an&lt;br&gt;
&lt;a href="https://labelixa.com/tools/zpl-preview" rel="noopener noreferrer"&gt;online viewer&lt;/a&gt; (disclosure: I&lt;br&gt;
work on Labelixa) and catch the missing &lt;code&gt;^FS&lt;/code&gt; before the printer does.&lt;br&gt;
Port 9100 has no undo; every mistake costs a label and ribbon.&lt;/p&gt;

&lt;h2&gt;
  
  
  When nothing prints, in order
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;ping&lt;/code&gt; the printer — if that fails it's a network problem, not ZPL.&lt;/li&gt;
&lt;li&gt;Is 9100 open? Some printers ship with raw printing disabled or on
another port — check the printer's network config page.&lt;/li&gt;
&lt;li&gt;Paused or in an error state? A blinking light means the job is
queued inside the printer, not lost.&lt;/li&gt;
&lt;li&gt;Is the ZPL actually a label? Everything must sit between &lt;code&gt;^XA&lt;/code&gt; and
&lt;code&gt;^XZ&lt;/code&gt; — a file without that frame is &lt;strong&gt;silently ignored&lt;/strong&gt; (the #1
"it does nothing" cause).&lt;/li&gt;
&lt;li&gt;Prints, but wrongly? Different problem class — that one is about
density, &lt;code&gt;^FS&lt;/code&gt; and clipping.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>zpl</category>
      <category>printing</category>
      <category>networking</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
