Code 39 vs Code 93 vs Code 128: The 1D Showdown

Three industrial 1D symbologies, one usually wins. Density, character set, check digits, and when to actually pick each.

Short version: pick Code 128. That's the right answer almost every time. Code 39 and Code 93 exist for reasons, but those reasons are narrow and getting narrower. Here's the full picture, and when the other two are actually worth using.

We already covered Code 128 vs Code 39 as a head-to-head. This piece adds Code 93, which completes the trio and settles some common "but what about..." questions.

The one-table comparison

Code 39Code 93Code 128
Character set43 (uppercase only)47 (+ full ASCII via shifts)Full 128 ASCII
Width per character13-16 modules9 modules11 modules (5.5 for numeric pairs in Set C)
Check digitOptional mod-43Two mandatory (C + K)One mandatory mod-103
Best numeric densityWorst~25% better than 39~20 cpi in Code Set C (double-density)
Scanner supportUniversal (every 1D scanner ever)Common but not universalUniversal on modern scanners
Typical 2026 useLegacy + LOGMARSNear-noneEverything new
GenerateCode 39Code 93Code 128

Why Code 128 usually wins

Three reasons.

  1. It encodes everything. Full 128-character ASCII including lowercase and control characters. No shift pairs, no workarounds. Code 39 is uppercase-only and anything else doubles the width.
  2. Code Set C doubles numeric density. Two digits per symbol character. At the same X-dimension, a 12-digit UPC in Code 128-C is about half the width of the same 12 digits in Code 39.
  3. Mandatory check digit. Every Code 128 has a mod-103 checksum. Transcription errors get caught. Code 39 without its optional check digit is the weakest of the three.

Every modern standard picked Code 128 as the base: GS1-128 for supply chain, HIBC for healthcare, shipping labels, pharma serialization. If you don't have a specific reason to pick something else, this is the answer.

When Code 39 still makes sense

Code 39 has one superpower: every 1D scanner on Earth can read it. That includes decade-old USB wedges, embedded line scanners in old POS terminals, and the cheapest Chinese handhelds on Amazon. If your deployment target is "whatever the customer already has," Code 39 maximizes compatibility.

Legitimate use cases in 2026:

  • US DoD LOGMARS (MIL-STD-1189B) - military-issued barcodes are Code 39 with the mod-43 check digit. Not negotiable.
  • Some state DMV / VIN workflows - older forms still read Code 39 only.
  • Legacy library and healthcare systems pre-dating HIBC.
  • Write-only asset tags where you control the printer but not the reader - Code 39 is the safest bet for unknown future scanners.
  • When human readability of the encoded string matters and the data is uppercase alphanumeric. The readable text below a Code 39 barcode is exactly the encoded string.

When Code 93 makes sense

Basically never. That's the honest answer.

Code 93 is genuinely well-designed - 9-module characters (denser than Code 39), two mandatory check digits (stronger than Code 128), full ASCII via shifts. On paper it looks like a winner. In practice Code 128 does all of the same things better and with far more tooling, scanner, and printer support.

The one real use case: a legacy downstream system was wired to Code 93 decades ago and nobody is budgeting a migration. Canada Post used Code 93 internally for package handling. A handful of retail inventory systems use it. If that's your constraint, print Code 93. Otherwise, move on.

Density, with real numbers

Encode the 12-digit string 012345678905:

  • Code 39: 12 chars x 13 modules + 2 start/stop + 11 inter-char gaps = ~169 modules wide.
  • Code 93: 12 chars x 9 modules + 2 start/stop + 2 check digits + 1 termination = ~144 modules wide. About 15% narrower.
  • Code 128 Set C: 6 symbol chars (numeric pairs) x 11 modules + start + check + stop = ~91 modules wide. About 45% narrower than Code 39.

For pure-numeric payloads, Code 128 in Code Set C isn't close - it's a completely different class of density. For alphanumeric payloads, Code 93 beats Code 39 but loses to Code 128 with lowercase content.

Just pick one