npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

gs1-barcode-parser-mod

v1.2.1

Published

The barcode parser is a library for handling the contents of GS1 barcodes.

Downloads

21,972

Readme

JavaScript GS1 barcode parser CI

Why this fork exists

Forked from upstream, whose master has had no commit since February 2015 and whose pull requests have been open since 2018. This fork is where the library is still maintained.

Published as gs1-barcode-parser-mod.

Changes from upstream:

  • Covers 226 application identifiers against upstream's 143; the 41x, 43x, 70xx, 71x, 72xx, 725x, 80xx and 82xx families were added since the fork point.
  • Reads the person related identifiers used in healthcare (7250-7259), whose dates carry a four digit year rather than the two digit year of the older date elements.
  • Resolves a two digit year with the sliding window from section 7.1.2 of the GS1 General Specifications, relative to the current year, instead of upstream's fixed "51-99 belongs to the 20th century" rule.
  • Exports parseBarcode as a CommonJS module rather than leaving it a browser global, so it can be required.
  • Adds a raw property to every parsed element, holding the untouched substring it was read from.
  • Strips only the first group separator when normalising a scanned code, which fixes parsing of remedy QR codes.
  • Handles a date whose day part is 00, turning it into the last day of that month.
  • Moves the library from scripts/ to src/ and adds a spec suite that parses every supported application identifier.

https://www.gs1.org/docs/barcodes/GS1_DataMatrix_Guideline.pdf

Table of Contents

Purpose

The barcode parser is a library for handling the contents of GS1 barcodes. GS1 barcodes are used for several purposes, from a humble barcode on a product you buy to complex barcodes describing the contents of a whole pallet. Especially the two dimensional barcodes can hold a lot of information.

The barcode parser makes it easier to access it.

The barcode parser contains a single function for parsing GS1-barcodes, yielding the single elements in a format processable by JavaScript.

The barcode parser is meant to be used in JavaScript applications which

  • take data from a barcode scanning device or a barcode reading application
  • process the data and
  • perform some action based on the contents of the barcode

Disclaimer

The library is my own humble interpretation of the GS1 specification. Neither is it endorsed, supported, approved or recommended by GS1, nor do I have any affiliations with GS1.

The Specification

The full "GS1 General Specifications" can be found on http://www.gs1.org/genspecs. It's a 478 pages document. The barcode parser is based on the Version 14, Issue 1, Jan 2014 of this specification.

About GS1 barcodes

GS1 barcodes are able to contain information about a product: its GTIN ("Global Trade Item Number", formerly known as UPC or EAN), the weight or dimensions of the item, its price, the lot/batch code, the date when it was fabricated and so on.

About the structure of GS1 barcodes

A GS1 barcode is a concatenation of data elements. Each single element starts with an application identifier ("AI"), a two to four digits number. The number is followed by the actual information.

A data element is delimited either by

  • the end of the whole barcode,
  • a specification that states that this information has a fixed count of characters or digits
  • a special character (named FNC1)

The application identifiers and their properties are described in the third chapter of the "GS1 General Specifications" (see below).

The GS1 barcode is started by a symbology identifier; a three character sequence denoting the type of barcode used. The symbology identifier is followed by an arbitrary number of data elements, thus the whole barcode represents a long string of digits, letters and some interspersed "FNC1"s.

The BarcodeParser takes this string and decomposes it into its single elements.

The human readable form

The same elements are printed underneath the barcode with their AIs wrapped in parentheses instead of being separated by FNC1s:

(01)04012345678901(17)261230(10)ABC123

That's the "human readable interpretation" of the code. parseBarcode() takes it as well and returns the same elements it returns for the scanned form. It is recognised by the very beginning of the string: an opening parenthesis, two to four digits, a closing parenthesis. Data which merely happens to contain a parenthesis is parsed as before.

A symbology identifier may precede it, e.g. ]C1(01)04012345678901. Both are then applied: the parentheses are resolved and the symbology identifier still sets codeName, because it names the symbology the data came from, while the parentheses only say how it was written down. Without a symbology identifier codeName becomes "GS1 Element String (HRI)".

Note that a parenthesis within the data can't be told apart from one enclosing an AI. A data content of "(01)" is read as an AI, whatever the standard says about the character set. That's a property of the printed form itself, not of this parser.

Use case

You have a JavaScript application which takes barcodes in one of the GS1-formats. The conversion barcode → string has been made by a barcode scanning device or some other application. You got a string looking somehow like that:

]C101040123456789011715012910ABC1233932978471131030005253922471142127649716

You want to extract some data out of the scanned code, e.g. the lot/batch number or the Best Before Date, and process it. The library takes the string and dissects it to an array of single elements:

|AI | Title | Contents | Unit/Currency | |:-- |:-----|:-------|:--------------| |01 |GTIN | 04012345678901 | | |17 |USE BY OR EXPIRY | Thu Jan 29 2015 00:00:00 GMT+0100 (CET) | | |10 |BATCH/LOT | ABC123 | | |3932 |PRICE | 47.11 | 978 | |3103 |NET WEIGHT (kg) | 0.525 | KGM | |3922 |PRICE | 47.11 | | |421 |SHIP TO POST | 49716 | 276 |

How to use it

The library is located in the src directory in its uncompressed form. npm run build writes a minified version to the dist directory, which is not checked in.

Load the library into your application:

<script src="./src/BarcodeParser.js"></script>

and use the single one function parseBarcode() of the library, handling over the barcode string:

try {
        var barcode = document.getElementById("barcode").value,
            answer = parseBarcode(barcode);
        // handle the answer ...    
} catch (e) {
    alert(e);
}

The function returns an object containing two elements:

  • codeName: a barcode type identifier (a simple string denoting the type of barcode) and
  • parsedCodeItems: an array of objects, each with these attributes:
  • ai: the application identifier
  • dataTitle: the title of the element, i.e. a short description
  • data: the contents, either a string, a number or a date
  • unit: the unit of measurement, a country code, a currency; denoted in ISO codes.
  • raw: the untouched substring the contents were read from
  • isoDate: for a date element, its date as text, e.g. "2025-06-30"; empty on every other kind of element

A date without a time of day cannot be carried unambiguously in a Javascript Date: reading one back means knowing whether to use the local getters or the UTC ones, and either choice shifts the day for somebody. parseBarcode("]C117250630") serialised with toISOString() from Auckland gives the 29th of June. That is what isoDate is for — it says the day the barcode says, wherever the reader sits. An element carrying a time of day puts that there too: "1985-06-30T14:35".

From the example above: parseBarcode() will return an object with "GS1-128" in its attribute codeName, the fourth element of parsedCodeItems is an object which has the attributes

  • "3932" as ai,
  • "PRICE" as dataTitle,
  • "47.11" as data (a floating point number) and
  • "978" as unit (the ISO code for €)

Some remarks about how the function works can be found in README_scripts.md within the src folder.

Limitations

The parseBarcode() function doesn't do any checks for plausibility. If the code you handle over to the function contains e.g. an invalid GTIN or some invalid ISO code the function will happily return this invalid content.

A simple scanning application as example

The directory Example contains an example using the barcode parser. It has three components:

  • a HTML page with
  • a form for input and
  • a (empty) <table> for the output,
  • some JavaScript code for
  • accessing the input,
  • calling the parseBarcode() function and
  • filling the table using the returned object
  • some CSS for styling the page

If you have no scanning device at hand, you can use the string in "ScannedBarcode.txt" to copy & paste it into the input field of the example.

About barcode scanning devices

GS1 barcodes are usually scanned using a barcode scanning device. If you use GS1 barcodes with a web application, you'll probably have a setup where the barcode scanner behaves as a keyboard ("HID").

This works fine for most characters, but has one big drawback: the FNC1.

The FNC1

The FNC1 is a non-printable control character used to delimit GS1 Element Strings of variable length.

The barcode types GS1 DataMatrix and GS1 QR Code use the ASCII group separator ("GS", ASCII 29, 0x1D; Unicode U+001D) as FNC1.

This non-printable character won't be found on any keyboard. So the scanner sends a Ctrl-sequence as a replacement. The canonical sequence for GS is "Ctrl"+"]".

So if you use a <input> field in your website the browser will receive the control sequence "Ctrl" + "]". Depending on your setup the browser will react in some way to this control sequence.

Things get messy when you use a non-english keyboard. For example: on german keyboards the key left beside the enter key is used for the "+" sign. On an english keyboard there is the "]". If the scanner is operated as a HID and configured to behave like a german keyboard, the scanner sends "Ctrl" + "+", which causes most browsers to increase their zoom factor.

So you have two things to do:

  • identify the sequence your scanner sends to the browser when a group separator is scanned
  • catch these keyboard events and transform them into a group separator within the input field

The BarcodeParserUsageExample.js does the latter part for a scanner which sends (emulating a german keyboard) a "Ctrl" + "+" if it encounters a group separator in the barcode.

Key Press Detecting

The directory KeypressDetecting contains a simple HTML page to explore what kind of control sequence your scanner sends. It has an input field and logs the values (keyCode, charCode and which) of the keypresses to the console.

The Barcodes

As an example the directory Barcodes contains five barcodes, three of them containing the same data:

  • a GS1-128-Code,
  • a GS1-DataMatrix-Code and
  • a GS1-QR-Code.

The other two just contain three characters: "1", the "<GS>" group separator and "3". They can be used to find out what your scanner sends when it encounters a "<GS>" in a barcode.

You can print them using the "ExamplesForBarcode.pdf".

Changes

What changed in each release is in CHANGELOG.md, including the behaviour changes worth reading before you upgrade.

Development

npm install
npm test          # lint, then the spec suite
npm run build     # minified build into dist/

spec/ApplicationIdentifiersSpec.js holds a table of 208 application identifiers and checks each one comes back under its own AI. Identifiers whose last digit only says how many decimals follow, 310x and its like, are represented by one entry rather than all ten, which is why the table is shorter than the 226 the parser accepts. The parser is a single large nested switch, where a missing break makes an identifier throw, return undefined, or silently parse as its neighbour — so an identifier added without being wired up correctly fails the suite rather than shipping.

Coverage

npm run coverage   # the suite, plus a coverage report in coverage/

c8 reads V8's own coverage, so the source is measured as it runs, unmodified. The thresholds live in .c8rc.json and are enforced: a change which adds a branch nothing exercises fails rather than passing quietly.

coverage/index.html is a browsable line-by-line report, and coverage/lcov.info is there for editors and other tools. Neither is checked in. Every CI run prints the table in its job summary and attaches the HTML report as an artifact.

The suite covers 100% of statements, branches, functions and lines, and the thresholds are set there, so anything less fails the build.

Two guards are held out of that figure with c8 ignore, each with a comment saying why: the default arm of the element type switch, and the default arm of the message switch. Neither can be reached — every caller passes a known type, and every code the parser throws has an arm of its own — and both are worth keeping as guards. They are excluded rather than deleted, which would have been flattering the number at the cost of the code.

CI runs the same commands on every push and pull request. A push to master whose package.json version is not yet on the registry is published to npm through Trusted Publishing; a push that does not change the version is a no-op.

License

Copyright (c) 2014-2019 Peter Brockfeld. See the LICENSE.md file for license rights and limitations (MIT).