@bobfrankston/dymo-print
v0.1.12
Published
API and CLI for printing labels on DYMO LabelWriter printers
Maintainers
Readme
@bobfrankston/dymo-print
Print labels to DYMO LabelWriter printers from Node.js. Supports text, HTML, images, QR codes, and clipboard input. Built on the shared @bobfrankston/label-core so the API matches @bobfrankston/brother-label.
Highlights
- Native Windows DYMO driver support (no external SDK required)
- Clipboard input —
dymo-print -clipprints whatever's on the clipboard (image or text) - Postal barcodes — IMb (Intelligent Mail Barcode), POSTNET, and any 1D format via bwip-js
- Address-with-barcode layout — combine
-textand-imbfor the standard DYMO Label app layout (text on top, IMb below) - Graceful offline handling — DYMO wireless printers go to sleep often; by default
print()waits for the printer to come back online and tells you about other DYMO printers that are online right now - Curated catalog of common label part-numbers (30252 Address, 30334 Multipurpose, 30330 Return Address, etc.) with sane defaults
- Text/HTML/QR/image rendering at 300 DPI
Installation
npm install @bobfrankston/dymo-printRequires Windows + a DYMO LabelWriter installed via the official DYMO Connect / DYMO Label Software driver.
CLI
Print text
dymo-print "Hello World"
dymo-print "Line 1\nLine 2" # multi-linePrint a QR code (with optional text label)
dymo-print -qr "https://example.com"
dymo-print -text "My site" -qr "https://example.com"Print HTML
dymo-print label.html
dymo-print label.html -l 30334 # specify label part-numberInline QR codes inside HTML — use <img qr="data">:
<img qr="https://example.com" style="width:10mm; height:10mm">Print an image
dymo-print photo.pngPrint clipboard contents
dymo-print -clip # auto-detects: image if present, else textMulti-segment labels
Combine -text and -qr repeatedly to compose side-by-side segments:
dymo-print -text "Hello" -qr "https://example.com" -text "More"Postal barcodes
# Intelligent Mail Barcode (USPS standard, 31-digit format ideal):
dymo-print -text "Bob Frankston\n278 Lake Ave\nNewton MA 02461" -imb 02461123412
# Combined with -text → DYMO-style stacked layout (text on top, IMb at bottom):
dymo-print -text "addr lines" -imb <data>
# Standalone barcode, no text:
dymo-print -imb 02461123412
# Legacy POSTNET (USPS deprecated 2013, but still supported by some scanners):
dymo-print -text "addr" -postnet 024611234
# Generic 1D barcodes via bwip-js — type:data syntax:
dymo-print -barcode code128:HELLO123
dymo-print -barcode ean13:0123456789012
dymo-print -text "Product" -barcode code39:SKU-001Supported barcode types include imb, postnet, planet, code128, code39, ean13, upca, qrcode, and any bwip-js bcid passed verbatim.
Save to file instead of printing
dymo-print "Test" -o test.pngList printers and labels
dymo-print list # DYMO printers + their online status
dymo-print labels # known label part-numbers + aliases
dymo-print -l # same as `labels` (short form)
dymo-print status # default printer's status
dymo-print status -p "DymoBlack" # specific printer
dymo-print diag # probe driver: page sizes, printable areas,
# hard margins per label (debug aid)
dymo-print diag -l 30252 # just one labelLabel presets (shortcuts for -l <name>)
dymo-print -address "Bob Frankston" # 30252 — also the default
dymo-print -return "123 Main St" # 30330 return-address
dymo-print -shipping "Big Box" # 30256 shipping
dymo-print -large-address "Office" # 30321
dymo-print -folder "Q4 Reports" # 30327 file folder
dymo-print -badge "Hello" # 30364 name badgeYou can also use the alias name with -l: dymo-print -l shipping "Big Box".
Configuration
dymo-print config # show current config
dymo-print config -l 30252 # set default label
dymo-print config -p "DymoBlack" # set default printerOptions reference
| Option | Description |
|--------|-------------|
| -l, -label [id] | Label part-number (e.g. 30252), alias (e.g. address), or full DYMO paper name. With no value, lists known labels. |
| -address, -return, -shipping, -large-address, -folder, -badge | Preset shortcuts equivalent to -l <name> |
| -p, -printer <name> | Printer queue name (default: first DYMO found) |
| -o, -output <file> | Save PNG to file instead of printing |
| -a, -aspect <r> | Aspect ratio width:height for HTML (e.g. 4:1) |
| -ht, -height <s> | Text height: 12mm, .5in, 50% of label height |
| -s, -space <s> | Space between segments |
| -t, -text | Force input as literal text |
| -qr <data> | QR code segment |
| -w, -html | Force input as HTML file path |
| -i, -image | Force input as image file path |
| -c, -clip | Read content from clipboard (image preferred, then text) |
| -imb <data> | USPS Intelligent Mail Barcode (combine with -text for stacked address+IMb) |
| -postnet <data> | Legacy USPS POSTNET (deprecated 2013) |
| -barcode <type>:<data> | Generic 1D barcode (code128, code39, ean13, upca, etc.) |
| -no-wait | Fail immediately if printer is offline (default: wait) |
| -timeout <secs> | Max wait time when printer is offline (default: unlimited) |
| -interval <secs> | Polling interval while waiting (default: 2) |
All flags are case-insensitive; pick distinct letters rather than relying on case.
Single quotes can wrap arguments: '7"', 'line 1\nline 2'.
API
Basic print
import { print } from "@bobfrankston/dymo-print";
await print({ text: "Hello World" });
await print({ text: "Hello", media: "30334" }); // 30334 multipurpose label
await print({ qr: "https://example.com" });
await print({ html: "<div style='font-size:24px'>Hi</div>" });
await print({ imagePath: "photo.png" });
await print({ clip: true }); // clipboard
// Postal barcodes:
await print({ imb: "02461123412" });
await print({ text: "Bob\n278 Lake Ave", imb: "02461123412" }); // stacked layout
await print({ barcode: "code128:HELLO123" });Render without printing
import { render } from "@bobfrankston/dymo-print";
import * as fs from "fs";
const buffer = await render({ text: "Hello" });
fs.writeFileSync("label.png", buffer);Multi-segment labels
import { printSegments } from "@bobfrankston/dymo-print";
await printSegments([
{ type: "text", value: "WiFi" },
{ type: "qr", value: "WIFI:T:WPA;S:MySSID;P:secret;;" },
]);Offline handling
By default, print() waits for the printer to come online if it's asleep. Provide an onWaiting callback to surface progress:
await print({
text: "Hello",
onWaiting: (status, elapsedMs, alternatives) => {
console.log(`waiting on ${status.name} (${Math.floor(elapsedMs/1000)}s)`);
if (alternatives.length) {
console.log(`other DYMOs online now: ${alternatives.map(a => a.name).join(", ")}`);
}
},
waitTimeoutMs: 60_000, // max 60s
waitIntervalMs: 2_000, // poll every 2s
});
// Or fail immediately:
await print({ text: "Hello", wait: false });Cross-driver code
The dymoPrinter singleton implements LabelPrinter from @bobfrankston/label-core:
import type { LabelPrinter } from "@bobfrankston/label-core";
import { dymoPrinter } from "@bobfrankston/dymo-print";
import { brotherPrinter } from "@bobfrankston/brother-label";
async function printOn(p: LabelPrinter, text: string) {
await p.print({ text });
}
await printOn(dymoPrinter, "Hi");
await printOn(brotherPrinter, "Hi");Configuration
import { getConfig, setConfig, listMedia } from "@bobfrankston/dymo-print";
console.log(getConfig()); // { defaultPrinter, defaultMedia }
setConfig({ defaultMedia: "30252", defaultPrinter: "DymoBlack" });
listMedia().forEach(m => console.log(m.id, m.name));Known labels (curated)
| ID | Description | |---|---| | 30252 | Address (28×89 mm) — default | | 30320 | Address | | 30321 | Large Address | | 30330 | Return Address | | 30256 | Shipping | | 30334 | Multi-purpose 2.25×1.25 in | | 30336 | Multi-purpose 1×2.125 in | | 30332 | Square 1×1 in | | 30327 | File Folder | | 30364 | Name Badge | | 99010, 99012, 99014 | LW-series equivalents of 30252/30321/30256 |
For a label not in this list, pass its full DYMO paper name as -l "<name>". The driver dispatch path will look it up in the printer's registered PaperSizes.
Debugging
If a print comes out blank, distorted, or wrongly positioned:
dymo-print diag # tabular driver probe (paper sizes, printable areas, margins)
set DYMO_PRINT_DEBUG=1 # adds a stderr line with image vs page dimensions
dymo-print -qr hello # the diagnostic line appears during the printThe diagnostic line shows what PageSettings.PrintableArea, PageBounds, and the rendered image's pixel dimensions actually are at print time, which tells you whether the driver is reporting reasonable values for the loaded label.
Requirements
- Windows
- Node.js 24+ (for native
.tsexecution andimport.metafeatures) - DYMO LabelWriter installed via DYMO Connect / DYMO Label Software
License
MIT
