Here's the short version, because this one gets muddled constantly: every GS1-128 is a Code 128. Not every Code 128 is a GS1-128. GS1-128 is a rulebook layered on top of Code 128 - same barcode, same scanners, same ink on paper. What changes is what the numbers mean and how a receiving system is allowed to parse them.
If you're printing shipping cartons for a retailer, a 3PL, or a regulated supply chain, you almost certainly want GS1-128. If you're printing an internal asset tag, a work-order ticket, or anything that stays inside your four walls, plain Code 128 is fine.
The actual difference
| Code 128 | GS1-128 | |
|---|---|---|
| Symbology | Code 128 | Code 128 (identical bars) |
| Data format | Anything you want | GS1 Application Identifiers (AIs) |
| Start character | Start A, B, or C | Always starts with FNC1 |
| Who validates it | Nobody | GS1 standards + trading partner |
| Typical use | Internal labels, tickets, asset tags | Shipping cartons, pharma, foodservice, retail logistics |
| Generator | Code 128 | GS1-128 |
What the FNC1 start character actually does
A GS1-128 begins with a hidden control character called FNC1. It's not printed as a human-readable digit, but every compliant scanner recognizes it. FNC1 is the signal that says: "the data after this is structured, and it follows GS1 Application Identifiers." Without FNC1, a scanner reading the same bars just hands your software a raw string and shrugs.
That single control character is the entire line between "Code 128 with numbers on it" and "GS1-128." No FNC1, no GS1-128 - full stop. If your generator doesn't prepend FNC1 automatically, it isn't producing a real GS1-128, and any serious receiving system will reject it.
Application Identifiers, briefly
GS1 AIs are two-to-four digit prefixes that tell the scanner what the following data represents. A few you'll see constantly:
(00)- SSCC (Serial Shipping Container Code), 18 digits. The universal pallet/carton license plate.(01)- GTIN (the 14-digit product identifier). Same number system as your UPC, zero-padded.(10)- Batch / lot number, variable length.(17)- Expiration date, YYMMDD.(21)- Serial number, variable length.(310n)- Net weight in kilograms.
A pallet label encoded as GS1-128 might read (01)10614141999996(17)260601(10)LOT-4421(21)000001. One barcode, four pieces of structured data, parsed automatically by the receiving WMS. That's the point. That's what you're buying with the extra complexity.
When you must use GS1-128
If any of these apply, you don't get to choose:
- Shipping to major retailers. Walmart, Target, Costco, Kroger, Home Depot, and essentially every grocery chain require GS1-128 carton labels. An SSCC-18 inside an
(00)AI is table stakes for an advance ship notice. - Pharmaceutical distribution (DSCSA). Unit-of-sale traceability under the US Drug Supply Chain Security Act uses GS1 Application Identifiers.
- Foodservice to large distributors. Sysco, US Foods, and Performance Food Group all publish GS1-128 labeling specs.
- Healthcare devices (UDI). The FDA's Unique Device Identification rule accepts GS1 as an issuing agency.
- Anything that needs to move across a GS1-compliant supply chain without human re-keying.
If none of the above applies, and the label only needs to scan inside a system you control, use Code 128. Don't pay the overhead of GS1 compliance for a barcode that never leaves your building.
The mistakes I see most often
Encoding GS1 AIs in a plain Code 128 symbol. You can type (01)10614141999996 into a Code 128 generator and it will happily render it. It will scan. The receiving system won't parse it as structured data because there's no FNC1. It's just a string with parentheses in it. This fails silently at the worst possible time - on a Walmart dock.
Printing the parentheses as part of the barcode data. Parentheses in AI notation are a human-readable convention. They never get encoded in the bars. A correct GS1-128 generator takes (01)10614141999996 as input and encodes 0110614141999996 - AI plus value, no brackets. Use a real GS1-128 generator and let it handle the encoding rules.
Assuming your SSCC is yours to invent. The SSCC is 18 digits with a specific structure: extension digit, GS1 Company Prefix (which you must own through a GS1 membership), a serial reference you assign, and a check digit. Making up numbers gets you duplicate SSCCs in the retailer's system, which gets your ASN rejected, which gets you chargebacks.
Variable-length AIs without a separator. Some AIs (like (10) batch number) are variable length. When a variable-length AI is followed by another AI in the same barcode, you need an FNC1 separator character between them. Skip the separator and the scanner reads everything as one giant batch number. Again - use a generator that enforces the rules.
So which do you print?
Internal ticket, asset tag, a quick scannable label for something on your own shelves? Code 128. Done. Need to print a lot of them? Batch generator.
Carton label for a trading partner, an SSCC, anything that encodes a GTIN plus a lot number or expiration? GS1-128. And if you're printing pallet license plates at volume, use the GS1-128 batch generator - typing SSCCs by hand is how duplicates happen.
One more thing worth saying out loud: if a supplier asks you for "a Code 128 barcode" on a shipping carton destined for a big-box retailer, they mean GS1-128. They just don't know the right name for it. Print the right thing anyway.