If you ship more than 5 orders a day, you know the pain: manually creating labels one by one. Each label needs the same info — return address, weight class, service type — just with different recipient addresses.
I built a tool that takes a CSV of addresses and generates all your labels at once.
The Problem
Small e-commerce sellers often use:
- Manual entry: Copy-paste addresses into carrier websites one by one
- Spreadsheets: Track orders but can't generate labels
- Expensive software: $50+/month tools that are overkill for < 50 orders/day
There's a gap between "completely manual" and "enterprise TMS." I wanted to fill it.
CSV Format
The tool accepts a simple CSV:
name,address_line_1,address_line_2,city,state,zip,country,weight_oz
John Doe,123 Main St,,Portland,OR,97201,US,8
Jane Smith,456 Oak Ave,Apt 2B,Seattle,WA,98101,US,12
Minimal required fields:
-
name— recipient name -
address_line_1— street address -
city,state,zip— location -
weight_oz— package weight in ounces
Implementation
1. CSV Parsing
I use PapaParse for robust CSV handling (handles quoted fields, commas in addresses, etc.):
import Papa from 'papaparse';
function parseCSV(file) {
return new Promise((resolve, reject) => {
Papa.parse(file, {
header: true,
skipEmptyLines: true,
complete: (results) => {
const labels = results.data.map((row, index) => ({
id: index + 1,
recipient: row.name,
address: formatAddress(row),
weight: row.weight_oz,
service: 'USPS First Class'
}));
resolve(labels);
},
error: reject
});
});
}
2. Label Generation
Each label is rendered as a print-ready format:
function generateLabelHTML(labels) {
return labels.map(label => `
<div class="label" style="page-break-after: always;">
<div class="from">
<strong>Return:</strong><br>
${RETURN_ADDRESS.name}<br>
${RETURN_ADDRESS.line1}<br>
${RETURN_ADDRESS.city}, ${RETURN_ADDRESS.state} ${RETURN_ADDRESS.zip}
</div>
<div class="to">
<strong>Ship to:</strong><br>
${label.recipient}<br>
${label.address}<br>
Weight: ${label.weight} oz
</div>
<div class="barcode">
<!-- USPS tracking barcode placeholder -->
</div>
</div>
`).join('');
}
3. Print-to-PDF
The tool generates HTML formatted for standard 4×6 shipping labels. Users print directly from the browser:
function printLabels(html) {
const printWindow = window.open('', '_blank');
printWindow.document.write(`
<html>
<head>
<title>Shipping Labels</title>
<style>
@page { size: 4in 6in; margin: 0.125in; }
.label { font-family: 'Courier New', monospace; font-size: 10pt; }
/* ... more styles ... */
</style>
</head>
<body>${html}</body>
</html>
`);
printWindow.document.close();
printWindow.print();
}
What Makes This Different
- Free — No monthly subscription
- No account — Upload CSV, get labels, done
- Client-side — Data never leaves the browser (privacy)
- Works offline — After loading, no internet needed
- Customizable return address — Save your return address in localStorage
Future Plans
- Integration with USPS API for real tracking numbers
- Support for UPS/FedEx label formats
- CSV templates for different carriers
- Batch address validation
FTC Disclosure: I built this tool. Free to use, no affiliate links.
How do you handle batch label generation? What tools do you use? Let me know in the comments.
Top comments (0)