How to Validate a GTIN / EAN-13 Barcode Check Digit (GS1 Mod-10, explained)
If you have ever uploaded a product feed to Amazon, Google Merchant Center or Shopify and been rejected with "invalid GTIN," the culprit is almost always the check digit - the last digit of the barcode. It is not random: it is calculated from all the other digits, and if it does not match, the platform rejects the code. Here is exactly how the check digit works, with a worked example you can follow by hand.
What is a GTIN check digit?
GTIN (Global Trade Item Number) is the umbrella term for the barcodes on products: GTIN-8, UPC-A (12 digits), EAN-13 (13 digits) and GTIN-14. The final digit of every one of them is a check digit computed with the GS1 Mod-10 algorithm. Its job is to catch typos: change one digit and the check digit almost always stops matching.
The GS1 Mod-10 algorithm, step by step
Take all the digits except the last (the check digit), then:
- Starting from the rightmost of those digits, multiply every second digit by 3 and the rest by 1.
- Add up all the results.
- Find what you must add to reach the next multiple of 10. That number (0-9) is the check digit.
Formally: check = (10 − (sum mod 10)) mod 10.
A worked example - EAN-13 400638133393?
The first 12 digits are 4 0 0 6 3 8 1 3 3 3 9 3. Working right to left, alternate the weights ×3 and ×1:
| digit | 4 | 0 | 0 | 6 | 3 | 8 | 1 | 3 | 3 | 3 | 9 | 3 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| weight | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 |
| product | 4 | 0 | 0 | 18 | 3 | 24 | 1 | 9 | 3 | 9 | 9 | 9 |
Sum = 4+0+0+18+3+24+1+9+3+9+9+9 = 89.
89 mod 10 = 9, so check = (10 − 9) mod 10 = 1.
The full valid barcode is therefore 4006381333931. If a feed lists 4006381333930, it is wrong - and that is exactly the kind of error that gets a listing rejected.
In code (Python)
def gtin_check_digit(body: str) -> int:
total = 0
for i, ch in enumerate(reversed(body)):
total += int(ch) * (3 if i % 2 == 0 else 1)
return (10 - total % 10) % 10
print(gtin_check_digit("400638133393")) # -> 1
The same algorithm works for UPC-A (12), EAN-13 (13), GTIN-8 and GTIN-14 - only the length changes.
Two things that trip people up
- Excel eats leading zeros. A UPC like
036000291452becomes36000291452the moment Excel treats the cell as a number, which changes the length and breaks validation. Format the column as Text before pasting. - Wrong length. UPC-A is 12 digits, EAN-13 is 13. Padding a UPC with a leading zero turns it into a valid EAN-13 - that is normal, not an error.
The fast way (no math)
If you just need to check or generate a check digit right now, paste the code into a free GTIN / UPC / EAN check-digit calculator - it validates GTIN-8 / UPC-A / EAN-13 / GTIN-14 in the browser and tells you the correct digit when it is wrong.
For bulk work - validating a whole product feed, or wiring this into your own app - there is a deterministic JSON API that checks up to 100 codes per call (and also handles IBAN, EU VAT, VIN, ISIN and more). Same input, same output, every time - no AI guessing.
Comments
No comments yet. Start the discussion.