GTIN (EAN/UPC)

Global Trade Item Number, the number under an EAN/UPC barcode: GTIN-8, GTIN-12, GTIN-13 and GTIN-14, ending in a GS1 modulus 10 check digit. The NF-e carries it in the cEAN and cEANTrib fields.

  • Parity matrix

Validate

Validates a GTIN: 8, 12, 13 or 14 digits and the GS1 modulus 10 check digit.

  • Check digit: the other digits weighted 3 and 1 alternately from the right. The check digit brings the sum to the next multiple of 10. This is what NF-e rules I03-10 and I12-10 check in the cEAN and cEANTrib fields.
  • Only a string of digits is read; whitespace around the value is ignored. A mask, a space inside the value and a letter are rejected. A number is also rejected, because the leading zeros define the length.
  • A value of zeros only is rejected at any length, although its check digit is valid. This is a rule of the library, not of the NF-e or GS1: rejection 611 is only the check digit, and GS1 reserves the prefix 0000000 for Restricted Circulation Numbers within a company instead of forbidding it. Zeros are rejected as the usual placeholder for a missing GTIN.
  • SEM GTIN, the text the NF-e uses for a product without a GTIN, is rejected.
  • options.lengths limits the accepted lengths, for example { lengths: [13] }. An empty list accepts nothing. When it is missing or is not a list, the four lengths are accepted.
  • The prefix does not change the result: Restricted Circulation Numbers and the ISBN, ISSN and coupon ranges share the structure and are valid. Use gtin.getInfo to read the prefix.
  • The prefix is not checked against a list. SEFAZ also checks it against its own "Tabela Prefixo GS1" (rules I03-20 and I12-20), which the library does not carry. Registration with GS1 (the Cadastro Centralizado de GTIN) cannot be checked offline.
ParameterTypeRequired
valuestringyes
optionsIsValidGtinOptionsno
options.lengthsGtinLength[]no
returnsboolean

Check if a GTIN (Global Trade Item Number, the number under an EAN/UPC barcode) is valid.

  • Covers the four structures of the GS1 General Specifications, the same four the NF-e accepts in cEAN and cEANTrib: GTIN-8, GTIN-12 (UPC), GTIN-13 (EAN) and GTIN-14 (DUN-14).
  • Options (IsValidGtinOptions): lengths accepts only some of the four lengths, and defaults to all four.
  • The value must be a string of 8, 12, 13 or 14 digits, surrounding whitespace aside, whose last digit is the GS1 modulo 10 check digit: weights 3 and 1 alternating from the right, the sum subtracted from the nearest equal or higher multiple of ten. That is what rules I03-10 and I12-10 of SEFAZ Nota Técnica 2021.003 check (rejections 611 and 612).
  • Leading zeros count, so a number is never accepted, and a masked value ('7 890000 000017') is rejected instead of having its digits picked out.
  • The 'SEM GTIN' literal the NF-e uses for a product without a GTIN is not a GTIN, so it is not valid here: test for it before calling.
  • A value of zeros only is rejected, although its check digit is valid. That is a rule of this library, not of the NF-e or GS1: rejection 611 is only the check digit, and the GS1 General Specifications (release 26.0, table 1-4) reserve the GS1 Prefix 0000000 for Restricted Circulation Numbers within a company rather than forbid it. Zeros are rejected as the usual placeholder for a missing GTIN.
  • The prefix does not change the verdict. Restricted Circulation Numbers (prefixes 02, 04 and 20 to 29, the codes a shop prints on its own scale labels) and the ISSN, ISBN and coupon ranges share the structure and the check digit, and the "Tabela Prefixo GS1" SEFAZ validates cEAN against lists them as valid; use getGtinInfo to tell them apart.
  • The prefix is not checked against the list of GS1 Member Organisations either: GS1 keeps assigning ranges, so a copy of that list would turn down valid numbers as it ages. Whether the number is registered (the Cadastro Centralizado de GTIN lookup SEFAZ runs for the 789 and 790 prefixes) cannot be checked offline.
import { isValidGtin } from '@brazilian-utils/brazilian-utils';

isValidGtin('7890000000017'); // true (GTIN-13, GS1 Brasil prefix)
isValidGtin('6291041500213'); // true (the example of the GS1 check digit page)
isValidGtin('78912342'); // true (GTIN-8)
isValidGtin('061414112345'); // true (GTIN-12)
isValidGtin('17890000000014'); // true (GTIN-14)
isValidGtin('7890000000018'); // false (wrong check digit)
isValidGtin('17890000000014', { lengths: [8, 12, 13] }); // false (GTIN-14 not accepted)
isValidGtin('7 890000 000017'); // false (digits only)
isValidGtin('SEM GTIN'); // false
isValidGtin('0000000000000'); // false (zeros only, a rule of this library)
Code: brazilian-utils/javascript
Try it with JavaScript isValidGtin
The inputs start with the first shared case. Change one to see the new result.

Runs @brazilian-utils/brazilian-utils 2.5.0 in your browser.

Shared test cases (36) and the result in each library gtin.isValid

Decode

Reads the fields of a GTIN: structure, length, GS1 prefix, whether the prefix is Brazilian or a restricted range, and the check digit. Accepts the same input as gtin.isValid without options and returns null exactly when gtin.isValid is false.

  • type (GTIN-8, GTIN-12, GTIN-13 or GTIN-14) and length describe the value as written. A GTIN-14 that starts with 0 is reported as GTIN-14.
  • prefix is read from the 14-digit form (the value left-padded with zeros): positions 7 to 9 when positions 2 to 6 are zeros (a GS1-8 prefix, as in every GTIN-8), positions 2 to 4 otherwise. The first digit, a padding zero or the indicator digit, is never part of the prefix. So 10000078912349 has prefix 789, the prefix of a GTIN-12 starts with 0, and a GTIN-14 has the prefix of the GTIN it packs.
  • isBrazilian is true for the prefixes 789 and 790 (GS1 Brasil, as the SEFAZ rules name them).
  • isRestrictedCirculation is true for the Restricted Circulation Number ranges of the GS1 General Specifications: GS1 prefixes 02, 04, 20 to 29 and 0000000, and GS1-8 prefixes 000 to 099 and 200 to 299. A restricted range does not make the code invalid. It is only reported.
  • checkDigit is the last digit, as a number.
  • The prefix is not checked against the list of GS1 Member Organisations, and no country name is returned. The prefix names the GS1 organisation that licensed the number, not the country of origin.
  • Returns a new object on every call.
ParameterTypeRequired
valuestringyes
returnsGtinInfo | null

Parse a GTIN into its fields, as a GtinInfo.

  • Returns null when the value is not a valid GTIN, under the same rules as isValidGtin.
  • The prefix is read as the GS1 General Specifications (tables 1-4, 1-5 and 1-9) lay the numbers out: the value is left padded with zeros to 14 digits, and the prefix is positions 7 to 9 when positions 2 to 6 are zeros (a GTIN-8, or a GTIN-14 that packs one) and positions 2 to 4 otherwise. The first digit, the padding zero or the indicator digit, is never part of the prefix, so a GTIN-12 has a prefix that starts with 0, and a GTIN-14 has the prefix of the GTIN it packs.
FieldDescription
type'GTIN-8', 'GTIN-12', 'GTIN-13' or 'GTIN-14' (GtinType), from the length the value was written with
length8, 12, 13 or 14 (GtinLength)
prefixThe three digit GS1 Prefix, or a GS1-8 Prefix when positions 2 to 6 of the 14 digit form are zeros, which covers every GTIN-8, a GTIN-14 that packs one and the GS1 Prefix 0000000. It names the GS1 Member Organisation that licensed the number, not the country of origin
isBraziliantrue when the prefix is one of GS1 Brasil, 789 or 790, what NT 2021.003 calls "prefixo do Brasil"
isRestrictedCirculationtrue when the prefix is in a range GS1 sets aside for Restricted Circulation Numbers (GS1 Prefixes 02, 04 and 20 to 29; GS1-8 Prefixes 000 to 099 and 200 to 299, which is also where the GS1 Prefix 0000000 lands, since its 14 digit form starts with six zeros), so the number is only unique inside a company or region
checkDigitThe modulo 10 check digit, the last digit
import { getGtinInfo } from '@brazilian-utils/brazilian-utils';

getGtinInfo('7890000000017');
// { type: 'GTIN-13', length: 13, prefix: '789', isBrazilian: true,
//   isRestrictedCirculation: false, checkDigit: 7 }

getGtinInfo('17890000000014');
// { type: 'GTIN-14', length: 14, prefix: '789', isBrazilian: true,
//   isRestrictedCirculation: false, checkDigit: 4 }

getGtinInfo('061414112345');
// { type: 'GTIN-12', length: 12, prefix: '006', isBrazilian: false,
//   isRestrictedCirculation: false, checkDigit: 5 }

getGtinInfo('2000000000015')?.isRestrictedCirculation; // true (in-store number)
getGtinInfo('7890000000018'); // null (wrong check digit)

Source: GS1 General Specifications, GS1 check digit calculator, SEFAZ Nota Técnica 2021.003 and the Tabela Prefixo GS1 of the Portal da NF-e.

Code: brazilian-utils/javascript
Try it with JavaScript getGtinInfo
The inputs start with the first shared case. Change one to see the new result.

Runs @brazilian-utils/brazilian-utils 2.5.0 in your browser.

Shared test cases (35) and the result in each library gtin.getInfo

Official sources

See also ISBN, NCM, CEST

Last updated on

On this page