GS1-128 Application Identifiers (AI) Directory & Parsing Rules: FNC1 Syntax & Variable-Length Fields

The developer and logistics engineer's complete guide to GS1-128 barcodes. Master FNC1 delimiter mechanics, understand fixed versus variable length fields, and implement deterministic state-machine parsing algorithms.

GS1-128 MULTI-ATTRIBUTE BARCODE ANATOMY & FNC1 SYNTAX (01) 00890103001234 (17) 281031 (10) BATCH-994 (21) SER-8812 AI (01): GTIN-14 Fixed Length: 14 Digits AI (17): EXPIRY Fixed: YYMMDD (6 Digits) AI (10): BATCH / LOT Variable + FNC1 Delimiter AI (21): SERIAL Ends at Stop Character Start Char + FNC1 (First Position) Flags barcode as GS1 Standard System In-Stream FNC1 (ASCII 29 / <GS>) Terminates variable-length fields before next AI
Figure 67.1: Anatomy of a multi-attribute GS1-128 barcode showing the initial FNC1 GS1 flag, fixed-length elements, variable fields, and in-stream FNC1 delimiters.

1. What Are GS1 Application Identifiers (AIs)?

In basic retail barcoding, a UPC-A or EAN-13 barcode encodes a single, static product identifier (the GTIN). However, modern warehouse logistics, food traceability, and pharmaceutical distribution require encoding multiple dynamic data attributes simultaneously: product batch number, expiry date, serial number, gross weight, and customer purchase order number.

Encoding raw concatenated numbers like 008901030012342810319948812 would create complete chaos; a receiving computer would have no way of knowing where the product ID ends and where the expiration date begins.

The GS1 system solves this using Application Identifiers (AIs): two-, three-, or four-digit standardized numeric prefixes that explicitly define the format, data type, and semantic meaning of the field that immediately follows.

GS1-128 STRING PARSING STATE-MACHINE LOGIC STATE: READ AI Match 2, 3, or 4 digits against table Fixed Length? YES (e.g. AI 01, 17) EXTRACT FIXED Read exact N bytes No FNC1 delimiter NO (e.g. AI 10, 21) READ UNTIL FNC1 Scan for ASCII 29 / <GS> or end of barcode MORE BYTES? Loop back or return JSON Deterministic O(N) Linear Time Parser Guaranteeing Complete Payload Recovery
Figure 67.2: Finite state machine parsing flow chart distinguishing fixed-length attributes from variable fields terminated by FNC1 delimiters.

2. The Dual Role of the FNC1 Character

In Code 128 symbology, the FNC1 (Function 1) code is a special non-printable character. In GS1-128, it performs two distinct and vital functions depending on where it appears in the symbol:

A. The Leading FNC1 (GS1 System Flag)

Every compliant GS1-128 barcode must begin with the Start Character (Start A, B, or C) immediately followed by FNC1. This first-position FNC1 instructs optical scanners that the symbol adheres to GS1 formatting rules rather than internal proprietary company tracking. Scanners configured for GS1 output transmit an identification prefix (such as ]C1) to the host computer.

B. In-Stream FNC1 (Variable Field Delimiter)

When a variable-length data field (such as a batch number or serial number) is followed by another Application Identifier, an in-stream FNC1 character must be inserted immediately following the last character of the variable data.

Because the length of the batch string is unknown to the parser, this in-stream FNC1 acts as an invisible stop sign, telling the decoding software: "The variable batch string has ended; the next digits represent a new Application Identifier." When a scanner decodes an in-stream FNC1, it outputs an ASCII 29 character (<GS> - Group Separator) to the host application.

3. Master Directory of Key Application Identifiers

The GS1 General Specifications define over 150 Application Identifiers. Below is the reference directory of the most critical AIs utilized in manufacturing and logistics:

AI Data Field Name Length & Type FNC1 Required? Standard Format
00 SSCC (Logistics Pallet) Fixed: 18 Digits No 00 + 18 digits
01 GTIN (Trade Item Number) Fixed: 14 Digits No 01 + 14 digits
02 Content GTIN (Packaged) Fixed: 14 Digits No 02 + 14 digits
10 Batch / Lot Number Variable: 1 - 20 Alphanumeric Yes (if followed by AI) 10 + string + <FNC1>
11 Production Date Fixed: 6 Digits (YYMMDD) No 11 + YYMMDD
15 Best Before Date Fixed: 6 Digits (YYMMDD) No 15 + YYMMDD
17 Expiration Date Fixed: 6 Digits (YYMMDD) No 17 + YYMMDD
21 Serial Number Variable: 1 - 20 Alphanumeric Yes (if followed by AI) 21 + string + <FNC1>
310n Net Weight (Kilograms) Fixed: 6 Digits (n = decimal pos) No 3102 + 012550 (125.50 kg)
37 Trade Item Count Variable: 1 - 8 Digits Yes (if followed by AI) 37 + count + <FNC1>
400 Customer PO Number Variable: 1 - 30 Alphanumeric Yes (if followed by AI) 400 + PO# + <FNC1>
420 Ship-to Postal Code Variable: 1 - 20 Alphanumeric Yes (if followed by AI) 420 + Postal + <FNC1>
FATAL GS1-128 ENCODING & PREPRESS ERRORS TO AVOID ERROR 1: ENCODING PARENTHESES ✗ Literal: "(01)00890103..." Encoding '(' and ')' into bars corrupts Code 128 Subset C ✓ Correct Rule: Parentheses are visual only. Encode raw digits: "010089..." ERROR 2: MISSING IN-STREAM FNC1 ✗ AI 10 Batch bleeds into AI 21 Scanner reads batch as "99421" Loses serial number completely ✓ Correct Rule: Always append <FNC1> after variable fields unless last field. ERROR 3: INVALID DATE SYNTAX ✗ Using DDMMYY or YYYYMMDD Violates GS1 6-digit rule Fails ISO verifier check ✓ Correct Rule: Strictly YYMMDD (6 digits). End of month encoded as '00'.
Figure 67.3: Common fatal encoding errors: encoding literal parentheses into bars, omitting in-stream FNC1 delimiters, and invalid date formats.

4. State-Machine Parsing Algorithm Architecture

When a raw barcode scanner transmits a decoded GS1 string over USB HID, RS-232, or WebSocket, a robust software parser must decode the string into structured key-value JSON.

Here is the reference algorithmic state-machine implementation in Python:

def parse_gs1_128(raw_data):
    # FNC1 delimiter transmitted as ASCII 29 (\x1d)
    FNC1 = '\x1d'
    
    # Table of Fixed-Length AIs (AI -> Data Length in characters)
    FIXED_AIS = {
        '00': 18, '01': 14, '02': 14, '03': 14, '04': 16,
        '11': 6,  '12': 6,  '13': 6,  '14': 6,  '15': 6,
        '16': 6,  '17': 6,  '18': 6,  '19': 6,  '20': 2,
        '310': 6, '311': 6, '312': 6, '313': 6, '314': 6
    }
    
    parsed = {}
    i = 0
    n = len(raw_data)
    
    while i < n:
        # Match 2-digit, 3-digit, or 4-digit AI
        matched_ai = None
        for ai_len in [2, 3, 4]:
            candidate = raw_data[i:i+ai_len]
            if candidate in FIXED_AIS or candidate in ['10', '21', '37', '400', '420']:
                matched_ai = candidate
                i += ai_len
                break
        
        if not matched_ai:
            break # Invalid or unsupported AI
            
        # Check if Fixed Length
        if matched_ai in FIXED_AIS:
            length = FIXED_AIS[matched_ai]
            val = raw_data[i:i+length]
            parsed[matched_ai] = val
            i += length
        else:
            # Variable length: read until FNC1 (\x1d) or end of string
            fnc_pos = raw_data.find(FNC1, i)
            if fnc_pos != -1:
                val = raw_data[i:fnc_pos]
                parsed[matched_ai] = val
                i = fnc_pos + 1
            else:
                val = raw_data[i:]
                parsed[matched_ai] = val
                i = n
                
    return parsed

5. Fatal Prepress & Encoding Errors to Avoid

Avoid these critical errors when generating packaging barcode files:

  • Encoding Literal Parentheses: Software designers mistakenly type (01)00890103001234(10)ABC directly into barcode generator inputs. The generator creates literal ASCII characters for '(' and ')', which invalidates Code 128 Subset C compression and makes the barcode unreadable by GS1 scanners. Input raw digits: 010089010300123410ABC.
  • Placing Variable Fields First Without FNC1: If you must encode AI (10) Batch and AI (01) GTIN, placing the fixed-length AI (01) first is optimal. If AI (10) is placed first, an in-stream FNC1 is legally mandatory before AI (01).
  • Exceeding 48 Characters: If total payload exceeds 48 characters, do not attempt to shrink the X-dimension below 10 mil to fit. Split the data into two separate stacked GS1-128 barcodes or upgrade to a 2D GS1 DataMatrix code.
Developer Sponsor: Client-Side GS1-128 & 2D DataMatrix Validation Engines

6. Frequently Asked Questions

What is the role of the FNC1 character in GS1-128 barcodes?

The FNC1 character serves two functions: (1) When placed in the first character position, it flags the barcode as conforming to the GS1 standard system rather than proprietary Code 128. (2) When placed within the data stream, it acts as an invisible separator terminating variable-length fields before the next Application Identifier begins.

Are the parentheses around Application Identifiers encoded in the barcode bars?

No. Parentheses like (01) or (17) are strictly for human-readable visual display beneath the barcode. They must never be encoded into the barcode bars. Encoding parentheses violates GS1 standards and causes verification scanners to reject the symbol.

How does a software parser know when an Application Identifier field ends?

Fixed-length fields (such as AI 01 GTIN with 14 digits) end automatically after their predefined character count. Variable-length fields (such as AI 10 Batch or AI 21 Serial) end either upon encountering an FNC1 delimiter (ASCII 29) or when the barcode symbol ends.

What is the maximum character capacity of a single GS1-128 barcode?

A single GS1-128 barcode cannot exceed 48 alphanumeric characters (including all AIs and FNC1 separators), and its printed physical length cannot exceed 165 mm (6.5 inches) including quiet zones. Data exceeding 48 characters must be split across two stacked barcodes or encoded in a 2D GS1 DataMatrix.