GS1 GTIN Check Digit and UDI Element String Python Generator
UDI labels built on GS1 carry a device identifier (the GTIN) and production identifiers (lot, expiry, serial) in application identifier format. This generator produces a small Python script that calculates the GTIN check digit and assembles the human readable and encoded strings.
Fill in
Indicator digit plus company prefix plus item reference, 13 digits in total
gtin_udi.py
# GS1 GTIN-14 check digit and UDI element string builder
# Application identifiers: 01 GTIN, 17 expiry (YYMMDD), 10 lot, 21 serial
GTIN_BASE = "0123456789012"
EXPIRY = "281031"
LOT = "LOT24A017"
SERIAL = "[Serial number (blank if lot controlled)]"
FNC1 = "\x1d" # group separator used between variable length elements in the encoded data
def gs1_check_digit(digits):
"""Return the GS1 mod 10 check digit for a string of digits.
Weights alternate 3, 1, 3, 1 starting from the rightmost digit of the input."""
if not digits.isdigit():
raise ValueError("GTIN base must contain digits only")
total = 0
for position, char in enumerate(reversed(digits)):
weight = 3 if position % 2 == 0 else 1
total += int(char) * weight
return (10 - total % 10) % 10
def build_gtin(base):
if len(base) != 13:
raise ValueError("GTIN base must be 13 digits to make a GTIN-14")
return base + str(gs1_check_digit(base))
def build_strings(gtin, expiry, lot, serial):
parts_hri = ["(01)" + gtin]
parts_data = ["01" + gtin]
if expiry:
parts_hri.append("(17)" + expiry)
parts_data.append("17" + expiry)
if lot:
parts_hri.append("(10)" + lot)
parts_data.append("10" + lot)
if serial:
if lot:
parts_data[-1] = parts_data[-1] + FNC1
parts_hri.append("(21)" + serial)
parts_data.append("21" + serial)
return "".join(parts_hri), "".join(parts_data)
if __name__ == "__main__":
gtin = build_gtin(GTIN_BASE)
hri, data = build_strings(gtin, EXPIRY, LOT, SERIAL)
print("GTIN-14 :", gtin)
print("Human readable:", hri)
print("Encoded data :", data.replace(FNC1, "<GS>"))Variable length elements such as lot (10) and serial (21) need a separator after them when another element follows. Fixed length elements (01, 17) do not. Element order and symbology are set by your labeler and the issuing agency rules, so check the GS1 General Specifications and your UDI issuing agency requirements. The GUDID device identifier is the GTIN, the production identifiers are lot, expiry and serial.
Optional UDI data flow review
We can look at how UDI data moves from your ERP item master to labels and GUDID submissions.
Optional. The tool and every export work without this. No spam.
How to use it
Enter the first 13 digits of your GTIN-14, an expiry date in YYMMDD, the lot number and optionally a serial number. Copy the script into a file and run it with Python 3. It prints the full GTIN-14, the human readable string with parentheses, and the encoded string with a visible group separator marker. Feed the encoded value to your barcode printing software or label system.
- 13 digit GTIN base, no check digit
- Expiry in YYMMDD, blank to omit
- Serial blank for lot controlled products
- Run with Python 3, no external libraries
The check digit method
GS1 check digits use modulo 10. Starting from the rightmost digit of the data, multiply digits alternately by 3 and 1, add the products, and subtract the sum from the next multiple of ten. For base 0123456789012 the weighted sum is 3 times (2+0+8+6+4+2) plus 1 times (1+9+7+5+3+1) which equals 66 + 26 = 92, so the check digit is 8. The script automates this and rejects non digit input.
Element string rules
In the human readable form, application identifiers are shown in parentheses. In the encoded form no parentheses are used, and variable length elements that are not last are followed by a separator character (FNC1 in the barcode, shown as group separator code 29 in text). Fixed length elements such as the GTIN and expiry need none. Many UDI regulations require both a human readable and an automatic identification form on the label.
Common mistakes
Typical errors are including the check digit in the base so the result is 15 digits, using a four digit year in the expiry, putting the serial before the lot when the label standard specifies another order, and leaving out the separator after lot. Validate printed barcodes with a verifier or scanner and check them against the GUDID record.
Frequently Asked Questions
Is the GTIN the same as the UDI?
The UDI has two parts. The device identifier (UDI-DI) is the GTIN, and the production identifier (UDI-PI) is the lot, expiry, serial or manufacture date. Together they form the UDI carried on the label.
Does this support GS1 DataMatrix?
It builds the data string that goes into a GS1 DataMatrix or GS1-128 symbol. You still need barcode software or a font to draw the symbol, and a leading symbology identifier is added by the encoder.
Which date format should I use?
GS1 element 17 uses YYMMDD. A day of 00 can be used where a day is not applicable in GS1 rules, but check what your regulator and GUDID submission expect.
Can I use this for HIBC or ICCBBA?
No. This generates GS1 strings only. HIBC and ICCBBA use different data structures and check character schemes.
If your ERP master data should generate compliant UDI strings automatically at pack-out, Netray can discuss how to connect that to your label system.
Related Tools
Device Lot Genealogy and Traceability SQL Generator
Build recursive lot genealogy queries for backward trace (finished device to components) and forward trace (component lot to shipped devices) using your own table and column names.
Compliance & ContractsFDA 21 CFR 820 to ISO 13485 Clause Crosswalk
Map each 21 CFR 820 quality system topic to the corresponding ISO 13485 clause to speed up QMSR gap assessments and procedure rewrites.
Compliance & ContractsMedical Device Standards Reference Table (ISO, IEC, ASTM)
A searchable lookup of the standards that medical device manufacturers cite in the QMS, design file and technical documentation, with area and typical use.
Compliance & ContractsEU MDR Annex VIII Classification Rules Reference
A searchable summary of the 22 classification rules in Annex VIII of Regulation (EU) 2017/745 with the class each rule typically leads to.
More Developer Tools tools
See all- SAP Sales Order ABAP SELECT Generator (VBAK, VBAP, VBFA)
- SAP Sales Order Create BAPI ABAP Generator (BAPI_SALESORDER_CREATEFROMDAT2)
- SAP ABAP Open Items SELECT Generator
- SAP ACDOCA SQL Query Generator
- SAP QM Inspection Lot ABAP SELECT Generator
- SAP Quality Notification Pareto SQL Query Generator
- SAP QM Usage Decision BAPI Skeleton
- ABAP Custom Exception Class Generator
- ABAP Unit Test Class Generator