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.
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
cEANandcEANTribfields. - 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
0000000for 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.lengthslimits 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.getInfoto 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.
| Parameter | Type | Required |
|---|---|---|
value | string | yes |
options | IsValidGtinOptions | no |
options.lengths | GtinLength[] | no |
| returns | boolean |
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
cEANandcEANTrib: GTIN-8, GTIN-12 (UPC), GTIN-13 (EAN) and GTIN-14 (DUN-14). - Options (
IsValidGtinOptions):lengthsaccepts 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
0000000for 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
cEANagainst lists them as valid; usegetGtinInfoto 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)Try it with JavaScript isValidGtin
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-13orGTIN-14) andlengthdescribe the value as written. A GTIN-14 that starts with 0 is reported asGTIN-14.prefixis 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. So10000078912349has prefix789, the prefix of a GTIN-12 starts with 0, and a GTIN-14 has the prefix of the GTIN it packs.isBrazilianistruefor the prefixes 789 and 790 (GS1 Brasil, as the SEFAZ rules name them).isRestrictedCirculationistruefor 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.checkDigitis 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.
| Parameter | Type | Required |
|---|---|---|
value | string | yes |
| returns | GtinInfo | null |
Parse a GTIN into its fields, as a GtinInfo.
- Returns
nullwhen the value is not a valid GTIN, under the same rules asisValidGtin. - 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.
| Field | Description |
|---|---|
type | 'GTIN-8', 'GTIN-12', 'GTIN-13' or 'GTIN-14' (GtinType), from the length the value was written with |
length | 8, 12, 13 or 14 (GtinLength) |
prefix | The 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 |
isBrazilian | true when the prefix is one of GS1 Brasil, 789 or 790, what NT 2021.003 calls "prefixo do Brasil" |
isRestrictedCirculation | true 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 |
checkDigit | The 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/javascriptTry it with JavaScript getGtinInfo
Shared test cases (35) and the result in each library gtin.getInfo
Official sources
Last updated on
