Generating Shipping Labels and Barcodes via API — TongoRender Blog
Back to Blog
tutorialsshippingbarcodeecommerce

Generating Shipping Labels and Barcodes via API

Learn how to generate shipping labels with barcodes using HTML templates and a PDF API. Covers barcode generation, label design, and e-commerce integration.

TongoRender TeamJanuary 22, 202610 min

Shipping labels are the backbone of e-commerce logistics. Every package needs a printed label with the destination address, return address, tracking barcode, and carrier information. While most shipping carriers provide their own label generation, many businesses need custom labels — for branded unboxing experiences, multi-carrier setups, warehouse management, or international shipments with customs declarations.

Anatomy of a Shipping Label

A standard shipping label contains:

  • Sender information — Company name, return address
  • Recipient information — Name, address, phone number
  • Tracking barcode — Code 128, Code 39, or QR code
  • Service type — Priority, Express, Ground, etc.
  • Weight and dimensions — Package weight and size
  • Routing code — ZIP or postal code barcode for automated sorting

Generating Barcodes in HTML

For HTML-based labels, we can generate barcodes using the JsBarcode library or encode them as SVG/PNG data URIs. Here is a server-side approach using the bwip-js library:

const bwipjs = require('bwip-js');

async function generateBarcode(text, type = 'code128') {
  const png = await bwipjs.toBuffer({
    bcid: type,
    text: text,
    scale: 3,
    height: 15,
    includetext: true,
    textxalign: 'center',
    textsize: 10,
  });

  return `data:image/png;base64,${png.toString('base64')}`;
}

// Generate different barcode types
const trackingBarcode = await generateBarcode('1Z999AA10123456784', 'code128');
const zipBarcode = await generateBarcode('94102', 'postnet');
const qrCode = await generateBarcode('https://track.example.com/1Z999AA10123456784', 'qrcode');

Designing the Label Template

Shipping labels are typically 4x6 inches (101.6mm x 152.4mm). Here is a complete label template:

function shippingLabelHTML(order, barcodes) {
  return `
  <!DOCTYPE html>
  <html>
  <head>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { width: 101.6mm; height: 152.4mm; font-family: Arial, sans-serif; font-size: 10pt; }
      .label { width: 100%; height: 100%; border: 2px solid #000; padding: 3mm; display: flex; flex-direction: column; }
      .section { border-bottom: 1px solid #000; padding: 2mm 0; }
      .section:last-child { border-bottom: none; flex: 1; }
      .from { font-size: 8pt; color: #333; }
      .to { font-size: 14pt; font-weight: bold; padding: 3mm 0; }
      .to .name { font-size: 16pt; }
      .service-badge {
        display: inline-block; background: #000; color: #fff;
        padding: 2px 8px; font-weight: bold; font-size: 12pt;
        margin-bottom: 2mm;
      }
      .barcode-section { text-align: center; padding: 3mm 0; }
      .barcode-section img { max-width: 100%; }
      .tracking-number { font-family: monospace; font-size: 12pt; letter-spacing: 1px; text-align: center; margin-top: 2mm; }
      .weight-dims { display: flex; justify-content: space-between; font-size: 9pt; }
    </style>
  </head>
  <body>
    <div class="label">
      <div class="section from">
        <strong>FROM:</strong> ${order.sender.name}<br>
        ${order.sender.address}<br>
        ${order.sender.city}, ${order.sender.state} ${order.sender.zip}
      </div>

      <div class="section">
        <span class="service-badge">${order.serviceType}</span>
        <div class="to">
          <div class="name">${order.recipient.name}</div>
          <div>${order.recipient.address}</div>
          <div>${order.recipient.city}, ${order.recipient.state} ${order.recipient.zip}</div>
          <div>${order.recipient.country}</div>
        </div>
      </div>

      <div class="section barcode-section">
        <img src="${barcodes.tracking}" alt="Tracking barcode">
        <div class="tracking-number">${order.trackingNumber}</div>
      </div>

      <div class="section">
        <div class="weight-dims">
          <span>Weight: ${order.weight} lbs</span>
          <span>Dims: ${order.dimensions}</span>
          <span>Pkg: ${order.packageCount} of ${order.totalPackages}</span>
        </div>
      </div>
    </div>
  </body>
  </html>`;
}

Generating the Label PDF

async function generateShippingLabel(order) {
  const barcodes = {
    tracking: await generateBarcode(order.trackingNumber, 'code128'),
    zip: await generateBarcode(order.recipient.zip, 'postnet'),
  };

  const html = shippingLabelHTML(order, barcodes);

  const response = await fetch('https://api.tongorender.io/v1/pdf', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': process.env.TONGORENDER_API_KEY,
    },
    body: JSON.stringify({
      html,
      width: '101.6mm',
      height: '152.4mm',
      margin: { top: '0mm', bottom: '0mm', left: '0mm', right: '0mm' },
      printBackground: true,
    }),
  });

  if (!response.ok) throw new Error(`Label generation failed: ${response.statusText}`);
  return Buffer.from(await response.arrayBuffer());
}

Batch Label Printing

For warehouses processing hundreds of orders, generate labels in batch and combine them into a single multi-page PDF for continuous printing:

const PDFMerger = require('pdf-merger-js');

async function batchGenerateLabels(orders) {
  const merger = new PDFMerger();

  for (const order of orders) {
    const labelPdf = await generateShippingLabel(order);
    await merger.add(labelPdf);
  }

  const mergedPdf = await merger.saveAsBuffer();
  fs.writeFileSync('batch-labels.pdf', mergedPdf);
  console.log(`Generated ${orders.length} labels in batch-labels.pdf`);
}

E-Commerce Platform Integration

Connect your label generator to Shopify, WooCommerce, or any e-commerce platform:

// Shopify webhook handler for new orders
app.post('/webhooks/orders/create', async (req, res) => {
  const order = req.body;

  const labelData = {
    trackingNumber: await getTrackingNumber(order), // from your carrier API
    sender: { name: 'My Store', address: '123 Warehouse St', city: 'Austin', state: 'TX', zip: '73301' },
    recipient: {
      name: order.shipping_address.name,
      address: order.shipping_address.address1,
      city: order.shipping_address.city,
      state: order.shipping_address.province_code,
      zip: order.shipping_address.zip,
      country: order.shipping_address.country,
    },
    serviceType: 'PRIORITY',
    weight: calculateWeight(order.line_items),
    dimensions: '12x8x4 in',
    packageCount: 1,
    totalPackages: 1,
  };

  const labelPdf = await generateShippingLabel(labelData);
  await uploadToS3(labelPdf, `labels/${order.id}.pdf`);

  res.status(200).json({ success: true });
});

Tips for Production Labels

  • Use thermal printer dimensions — Most thermal printers use 4x6 inch labels. Set the PDF page size to match exactly.
  • Test barcode scannability — Print sample labels and scan them with a barcode reader before going live.
  • Handle international addresses — Address formats vary by country. Use a library like i18n-postal for correct formatting.
  • Include customs info — International shipments require customs declarations with item descriptions, values, and HS codes.
  • High DPI rendering — Barcodes need sharp edges. Generate them at 300 DPI minimum for reliable scanning.

TongoRender's custom page size support makes it perfect for shipping labels. Set exact dimensions, zero margins, and print backgrounds for labels that are ready for thermal printing.

Generate shipping labels with TongoRender — 100 free renders per month, no credit card required.

Share this articleShare on Twitter