Skip to content
UtilHQ
developer

How to Generate Barcodes (Code 128, EAN-13, QR)

Learn how to generate barcodes programmatically in JavaScript, Python, and SQL. Compare Code 128, EAN-13, UPC-A, and QR formats. Avoid common printing mistakes.

By UtilHQ Team
Ad Space

Barcodes are everywhere: product packaging, shipping labels, inventory systems, event tickets. They encode data into a visual pattern that scanners can read in milliseconds.

But not all barcodes are created equal. Pick the wrong format, and scanners will reject it. Print at the wrong size, and it becomes unscannable. Forget the quiet zone, and your inventory system grinds to a halt.

This guide covers how to generate barcodes programmatically, when to use each format, and how to avoid the mistakes that break scanning systems.

Understanding Barcode Formats

Barcodes fall into two categories: 1D (linear) and 2D (matrix).

1D Barcodes (Linear)

These are the traditional “bar and space” patterns you see on retail products.

FormatLengthUse CaseExample
Code 128VariableShipping labels, inventorySHIP12345
EAN-1313 digitsEuropean retail products5901234123457
UPC-A12 digitsNorth American retail012345678905
Code 39VariableIndustrial, healthcare*ABC123*

Code 128 is the workhorse. It’s compact, supports alphanumeric characters, and works in most scanning environments. Use it for internal systems where you control the data format.

EAN-13/UPC-A are retail standards. If you’re selling products in stores, you need a registered barcode from GS1. You can’t make these up - each number is tied to a company prefix.

2D Barcodes (Matrix)

These encode data in both horizontal and vertical patterns, packing more information into less space.

FormatCapacityUse Case
QR Code4,296 alphanumericURLs, contact cards, payments
Data Matrix2,335 alphanumericSmall parts, electronics
PDF4171,850 alphanumericDriver’s licenses, boarding passes

QR codes dominate mobile scanning. They’re forgiving (work even when partially damaged), encode URLs directly, and every smartphone can read them.

Data Matrix is for tight spaces. It can be as small as 2mm x 2mm while remaining scannable - perfect for circuit boards and medical devices.

How to Generate Barcodes in Code

JavaScript (Browser/Node)

The JsBarcode library handles most 1D formats:

import JsBarcode from 'jsbarcode';

// Generate Code 128 barcode
const canvas = document.createElement('canvas');
JsBarcode(canvas, 'SHIP12345', {
  format: 'CODE128',
  width: 2,
  height: 100,
  displayValue: true
});

// Generate EAN-13 (requires valid checksum)
JsBarcode(canvas, '5901234123457', {
  format: 'EAN13',
  width: 2,
  height: 100
});

For QR codes, use qrcode.js:

import QRCode from 'qrcode';

// Generate QR code as data URL
const qrDataUrl = await QRCode.toDataURL('https://example.com');

// Or to canvas
const canvas = document.getElementById('qr-canvas');
QRCode.toCanvas(canvas, 'https://example.com', {
  width: 256,
  margin: 2,
  errorCorrectionLevel: 'H'
});

Python

The python-barcode library covers standard formats:

from barcode import Code128
from barcode.writer import ImageWriter

# Generate Code 128
code = Code128('SHIP12345', writer=ImageWriter())
code.save('barcode')  # Saves as barcode.png

# Generate EAN-13
from barcode import EAN13
ean = EAN13('5901234123457', writer=ImageWriter())
ean.save('product')

For QR codes, use qrcode:

import qrcode

qr = qrcode.QRCode(
    version=1,
    error_correction=qrcode.constants.ERROR_CORRECT_H,
    box_size=10,
    border=4,
)
qr.add_data('https://example.com')
qr.make(fit=True)

img = qr.make_image(fill_color="black", back_color="white")
img.save('qr.png')

SQL (Database Storage)

Most databases don’t generate barcodes natively, but you can store sequential numbers and generate barcodes in your application layer.

PostgreSQL (with custom function):

-- Store barcode data
CREATE TABLE products (
  id SERIAL PRIMARY KEY,
  sku VARCHAR(50) UNIQUE NOT NULL,
  barcode_data VARCHAR(100) GENERATED ALWAYS AS ('PROD-' || LPAD(id::TEXT, 8, '0')) STORED
);

-- Retrieve for barcode generation
SELECT barcode_data FROM products WHERE id = 123;
-- Result: "PROD-00000123"

The actual barcode image is generated in your app using the barcode_data field.

Barcode Anatomy and Structure

Every barcode has critical components that scanners rely on:

Quiet Zone (Critical)

The empty white space before and after the barcode. This isn’t optional.

Scanners need this buffer to detect where the barcode starts and ends. The minimum is typically 10x the width of the narrowest bar (X-dimension).

Bad:

|Text right next to bars|||||||||

Good:

        |||||||||||

If you print barcodes on labels and the edges are cut too close, scanners will fail. Always test with a real scanner after printing.

Check Digits

Many formats (EAN-13, UPC-A) include a check digit to validate correctness.

EAN-13 check digit calculation:

  1. Take the first 12 digits: 590123412345
  2. Sum odd positions (1st, 3rd, 5th…): 5+0+2+4+2+4 = 17
  3. Sum even positions × 3: (9+1+3+1+3+5) × 3 = 66
  4. Total: 17 + 66 = 83
  5. Check digit: (10 - (83 % 10)) % 10 = 7
  6. Full barcode: 5901234123457

Most libraries calculate this automatically, but if you’re building from scratch or validating input, you need this logic.

X-Dimension (Bar Width)

The width of the narrowest bar in the barcode. Common values:

X-DimensionUse Case
0.33mmMinimum for retail (UPC/EAN)
0.50mmStandard for shipping labels
1.00mmIndustrial/warehouse scanners

Rule: Larger is more forgiving. If scanning distance increases, increase X-dimension proportionally.

When to Use Which Barcode Format

Code 128: Internal Inventory

Pros:

  • Compact (higher data density than Code 39)
  • Supports full ASCII character set
  • Variable length
  • Fast scanning

Cons:

  • Not a retail standard (won’t work at checkout)

Use when:

  • Tracking internal shipments
  • Labeling warehouse bins
  • Serial numbers for equipment
  • Any alphanumeric identifier you control

EAN-13/UPC-A: Retail Products

Pros:

  • Global standard (works at any retail POS)
  • Registered with GS1 (prevents duplicates)
  • High scanner compatibility

Cons:

  • Requires purchasing company prefix from GS1 ($250-$10,000/year)
  • Fixed length (no flexibility)
  • Numeric only

Use when:

  • Selling products in physical stores
  • Listing on Amazon/eBay (UPC required)
  • Distribution through retail channels

Do NOT use for: Internal systems where you don’t need GS1 registration.

QR Code: Mobile & Marketing

Pros:

  • High data capacity (4,296 characters)
  • Error correction (works when damaged)
  • Every smartphone can scan
  • Can encode URLs directly

Cons:

  • Larger physical size than 1D barcodes
  • Slower to scan than linear barcodes with dedicated scanners

Use when:

  • Linking to websites (menus, product info)
  • Storing contact information (vCards)
  • Mobile payment systems
  • Event ticketing (self-service scanning)

Common Mistakes to Avoid

Printing Too Small

Barcodes have minimum size requirements based on scanner distance.

Handheld scanner (< 6 inches): Minimum 0.33mm X-dimension Fixed scanner (conveyor belt): Minimum 0.50mm X-dimension Long-range scanner (> 2 feet): Minimum 1.00mm X-dimension

If you scale a barcode below these thresholds, even perfect printers will produce unscannable results.

Test: Print your barcode and scan it with the actual hardware you’ll use. Don’t assume “it looks fine” on screen.

Ignoring Quiet Zones

The white space around a barcode is part of the specification.

Minimum quiet zones:

  • Code 128: 10x X-dimension on each side
  • EAN-13: 11 modules (about 3.63mm)
  • QR Code: 4 modules (the width of 4 squares)

Common error: Placing barcodes in tight boxes or near other graphics. The scanner sees the extra lines as part of the barcode and rejects it.

Using Low-Resolution Printers

Thermal printers are the standard for barcode labels because they produce sharp edges. Inkjet/laser printers can work, but they require higher DPI settings.

Minimum DPI:

  • Thermal printer: 203 DPI (acceptable), 300 DPI (better)
  • Inkjet/Laser: 600 DPI minimum

Avoid: Printing barcodes on home printers at default settings (often 150-300 DPI). The edges blur, and scanners misread bars.

Making Up EAN-13/UPC Codes

You can’t just generate random 13-digit numbers for retail barcodes. Each number block is assigned by GS1 to a specific company.

Wrong:

const fakeUpc = Math.floor(Math.random() * 1e12); // Will fail at checkout

Right:

  1. Buy a GS1 company prefix (https://www.gs1.org/)
  2. Generate product codes within your assigned range
  3. Calculate the check digit
  4. Print with the full barcode

Exception: For internal testing, you can use the GS1 test prefix 021000000000-021099999999, but these will never work in real retail systems.

Forgetting Error Correction in QR Codes

QR codes have four error correction levels:

LevelRecovery CapacityUse Case
L7%Clean environments
M15%General use (default)
Q25%Outdoor/printed materials
H30%Labels on curved surfaces, stickers

Mistake: Using level L for QR codes on product packaging that gets scratched or bent. Use level H for physical durability.

Pro Tips

Test with Multiple Scanners

Different scanners have different capabilities. A $50 USB handheld might read what a $5,000 conveyor-mounted scanner rejects (or vice versa).

Before printing 10,000 labels:

  1. Print 10 test samples
  2. Scan with your actual hardware
  3. Test at different angles (0°, 45°, 90°)
  4. Test under your actual lighting conditions

Add Human-Readable Text

Always print the encoded data below the barcode. When scanners fail, humans need to type it manually.

JsBarcode(canvas, 'SHIP12345', {
  format: 'CODE128',
  displayValue: true,  // Shows "SHIP12345" below bars
  fontSize: 14,
  textMargin: 2
});

Use SVG for Print

Raster images (PNG/JPG) lose quality when scaled. SVG stays sharp at any size.

// Generate SVG instead of canvas
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
JsBarcode(svg, 'SHIP12345', { format: 'CODE128' });

Then export the SVG for print layout software (Adobe Illustrator, InDesign).

Encode URLs in QR Codes Carefully

Long URLs make QR codes denser (more squares = harder to scan).

Before:

https://example.com/products/category/subcategory/item?utm_source=print&utm_medium=label

After (use URL shortener):

https://ex.co/p/123

The second version produces a simpler QR code that scans faster and works from farther distances.

Batch Generation for Inventory

When creating thousands of barcodes, generate them in batches and store as files (not in database BLOBs).

# Generate 1000 sequential barcodes
for i in range(1, 1001):
    code = Code128(f'ITEM-{i:06d}', writer=ImageWriter())
    code.save(f'barcodes/item_{i:06d}')

Then reference the file path in your database. This keeps your database lean and makes regeneration easy if you change label sizes.

Real-World Use Cases

Retail Product Labeling

Scenario: You’re launching a new product line and need UPC codes for 50 SKUs.

Steps:

  1. Purchase GS1 company prefix (10-digit range)
  2. Assign unique product codes (e.g., 0123456001 to 0123456050)
  3. Calculate check digits programmatically
  4. Generate EAN-13 barcodes as vector files
  5. Send to packaging designer for integration

Critical: Never reuse UPC codes. Once assigned to a product, that number is permanent in retail databases.

Warehouse Inventory Tracking

Scenario: You have 10,000 storage bins that need unique identifiers for a scanning system.

Format: Code 128 (alphanumeric, variable length)

Implementation:

# Generate bin labels
from barcode import Code128
from barcode.writer import ImageWriter

for row in ['A', 'B', 'C', 'D']:
    for col in range(1, 2501):
        bin_id = f'BIN-{row}{col:04d}'
        code = Code128(bin_id, writer=ImageWriter())
        code.save(f'labels/{bin_id}')

Print on thermal labels (4” x 6”), scan during putaway/picking operations.

Shipping Label Integration

Scenario: Your order fulfillment system needs to print tracking numbers as barcodes.

Format: Code 128 (USPS, FedEx, UPS all use variants)

Example:

// Generate tracking barcode for shipping API
const trackingNumber = '1Z999AA10123456784'; // UPS format

JsBarcode(shippingLabelCanvas, trackingNumber, {
  format: 'CODE128',
  width: 2,
  height: 50,
  displayValue: true
});

Carriers scan these at every checkpoint. If the barcode fails, your package gets stuck in “pending scan” status.

Event Ticketing

Scenario: You’re running a conference with 500 attendees and need scannable tickets.

Format: QR Code (encodes attendee ID + validation hash)

Implementation:

import QRCode from 'qrcode';

// Generate ticket with validation
const ticketData = JSON.stringify({
  attendeeId: 'ATT-12345',
  eventId: 'CONF-2026',
  hash: sha256('ATT-12345|CONF-2026|SECRET_KEY')
});

const qrImage = await QRCode.toDataURL(ticketData, {
  errorCorrectionLevel: 'H',  // High - survives printing on paper
  width: 300
});

At the entrance, scan the QR code, parse JSON, verify hash. Prevents duplicate entries with fake tickets.

Frequently Asked Questions

Can I use barcode generators to create UPC codes for Amazon listings?

Only if you purchased legitimate UPC codes from GS1. Amazon verifies UPCs against the GS1 database. Third-party “UPC resellers” often sell invalid or recycled codes that Amazon will reject.

What is the difference between Code 128A, 128B, and 128C?

These are subsets of Code 128. 128A covers uppercase letters, numbers, and control characters. 128B covers upper and lowercase letters plus numbers and is the most common. 128C handles numeric pairs and is the most compact for all-digit codes. Most libraries auto-select the optimal subset. For SHIP12345, it uses 128B. For 123456789, it uses 128C.

How do I generate a barcode that works in both the US and Europe?

Use EAN-13 instead of UPC-A. UPC-A is a subset of EAN-13 (it’s EAN-13 with a leading zero). All modern scanners read both formats.

Why does my QR code work on iPhone but not Android?

Likely an error correction issue. If your QR code is too complex (lots of data) and you used low error correction (L or M), damaged pixels cause failures. Regenerate with error correction level H.

Can I change the colors of a barcode?

Yes, but follow strict rules. High contrast is required, and black on white is safest. Dark blue, brown, or green on white are acceptable. Never use red on white (red scanners can’t see red) or white on black (inverts polarity). Test extensively before production printing.

What is the maximum data a Code 128 barcode can hold?

Technically unlimited, but practical limits exist. Most scanners handle up to 80 characters reliably. Beyond that, the barcode becomes too wide to fit on standard labels, and scanning accuracy drops.

Do I need a special font to print barcodes?

No. Modern barcode generation uses graphics (canvas, SVG, image files), not fonts. Barcode fonts exist but are error-prone because they don’t calculate check digits or enforce quiet zones.

Use the Online Generator

Need barcodes for product labels, inventory, or shipping?

Use our Free Barcode Generator. It supports Code 128, EAN-13, UPC-A, and QR codes. Generate single barcodes or bulk batches with sequential numbering. Download as PNG or SVG for print-ready labels. Perfect for small businesses, warehouse management, or product launches.

Share this article

Have suggestions for this article?