Every barcode, read and verified
You already scanned it.
You kept a twelfth.
barcoding.dev reads every barcode a scanner can — GS1, VIN, ISBN, UDI, NDC, SSCC, tracking numbers — checks it from the digits alone, and splits what it said: the product code to the register, the expiry, lot and serial out the other side as named fields. On your machine, no key.
what it said
(01)09506000134352(17)261231(10)ABC123(21)1234
check mod10 pass — computed from the digits
the register takes this
the price lookup, exactly as it happens today
and drops these
the floor
Why does anyone want a barcode?
A barcode was wrapped around your wrist minutes after you were born. It gave you a name a stranger could read without waking you. That is the whole idea, before a single acronym, and it is everywhere in the room you are standing in right now.
-
The story
Six things in a room, drawn wearing their real barcodes, and what each one means: a kind, or this one.
-
The periodic table of visibility
Nine barcode formats, the things they name, and the door in the family that owns each part, on one plate.
Fork the scan
From December 2027 the register reads the whole square, and keeps the part it already had.
GS1's Sunrise 2027 program expects retail point of sale to read 2D barcodes by the end of December 2027 and take the GTIN from them. That is the whole obligation; the six things it is claimed to require are on the blog, each against its source.
When a brand encodes lot, expiry and serial, all of it arrives in the same square on the same scan. Every US prescription-drug package already carries exactly that. The register takes the GTIN for the price lookup and drops the rest, because a sale record is item, price, basket.
So fork it. The GTIN goes to the register untouched. Lot, expiry and serial go out the other side as named fields, checked from the digits alone. No new step for a cashier, no new hardware: an imager that clears the 2027 date already reads the whole square.
What happened, where and who did it becomes an event at epcis.dev; rolled up across stores and docks, it is visibility.cloud. barcoding.dev holds no history.
Eight verbs, on your machine.
--json on every verb, typed errors on stderr, exit codes 0, 1 and 2. The same engine runs behind npx barcoding.dev and the hosted doors here; four of them are listed as MCP tools — resolve, verify, generate, pins — all readOnlyHint: true; the rest are reachable on the CLI door only.
Four movements, in order: read a barcode, draw one, create an identifier for a thing that has none, and say what it means.
| verb | what it does | network | exit-1 verdict |
|---|---|---|---|
| decode | a frame or a photo → what the barcode actually says. Runs on the hosted door and, unchanged, in the browser at /scan — frames are decoded in memory and discarded, never stored, never logged | pure · local | nothing decodable in the frame |
| resolve | any identifier-bearing string — what a scanner read, bare GTIN-8/12/13/14, EPC URN, GS1 element string, GS1 Digital Link URI, VIN, ISBN, SSCC, tracking number — to canonical identity: scheme, canonical form, parsed AIs and fields | pure · local | unrecognized / unparseable |
| verify | check digit + structure + prefix legitimacy (GS1 prefix ranges → issuing MO; WMI → manufacturer; ISBN group), from pinned tables | pure · local | fails validation |
| generate | the write-side twin of resolve: id + AI map → element string, Digital Link URI, rendered symbol (QR / DataMatrix / GS1-128 / ITF-14). resolve(generate(x)) === x is the round-trip law | pure · local | unencodable input |
| serialize | nothing → one serial, derived from the request with no stored counter, on a GS1 AI(21)-safe alphabet. Free and transparent: the response states, in the response, exactly what the serial discloses | pure · local | — |
| pins | print the pinned artifact and data-source-manifest digests | pure · local | — |
| version | package, engine-core and pin-set versions | pure · local | — |
| mcp | the agent door on stdio: the tarball's verbs as MCP tools, generated from the same table, readOnly-hinted | — | — |
The thing that has no barcode.
A model can read a label, judge the damage on a carton and count the cases on a pallet. It cannot tell which one it is. Either the thing says so, or nobody knows.
Most of what moves in a building has no identifier at all: totes, bins, returnable crates, a pallet built forty minutes ago, a dock door, a rack position. serialize gives one of them a number, with no license to buy, no membership, no key and no account. One curl, and the number is yours.
The identifier is derived from the request, not a counter, so there is no range to run out of. Serials that must reveal nothing are a different, paid class.
$ curl -sX POST https://api.barcoding.dev/serialize
{
"serial": "Gs21hefO3IX74Lfk",
"profile": "T1 compact",
"alphabet": "tsp-1",
"decodes_to": { "issued_at": "2026-08-05T11:12:52.000Z", "entropy_bits": 48 },
"discloses": ["issuance time (1 s precision)"],
"honesty": "This serial decodes publicly to: issuance time (1 s precision). A collection of our serials therefore reveals issuance volume and cadence, business hours and timezone. That is the disclosed cost of free + stateless + transparent. If serials must reveal nothing, that is the opaque class."
}
The provenance envelope.
Per attribute, not per record — because real records are mosaics: nutrition may be public-domain USDA while the category is ODbL Open Facts. The license class travels with the value, so a downstream agent can filter by what it is allowed to do with each field.
{
"attribute": "servingSize",
"value": "30 g",
"source": {
"id": "usda-fdc",
"record": "https://fdc.nal.usda.gov/…",
"dataset_version": "FDC 2026-04 full download",
"digest": "sha256:…"
},
"license": "public-domain",
"fetched_at": "2026-07-31T18:20:11Z",
"confidence": 1.0
}
The barcode registry.
One pinned row per identifier family: the grammar, the check digit, the canonical form, the barcode types it rides, the enrichment sources with their license class, and the join into the event record. GS1 is the largest family in it, not the boundary.
| scheme | validation rail | enrichment rail | license class |
|---|---|---|---|
| GTIN / GLN / SSCC | GS1 GenSpecs mod-10, prefix ranges | food: USDA FDC (CC0) + Open Facts (ODbL, segregated) | public-domain · share-alike-odbl |
| VIN | 49 CFR 565.15 — transliteration, weights, mod-11 | NHTSA vPIC (public domain); auto.dev as the owned rail | public-domain · first-party |
| UDI (GS1 / HIBCC / ICCBBA) | FDA UDI formats doc | AccessGUDID / openFDA (CC0; GMDN fields stripped) | public-domain |
| NDC | structural (no check digit) | openFDA drug/ndc, updated daily (CC0) | public-domain |
| ISBN (978/979 — a valid GTIN-13) | free ISBN Users' Manual | routed to book enrichment | open · confirm-before-redistribution |
| USPS IMpb | Pub 199 MOD10, worked example public | identity open; tracking status per-caller | identity: open · status: per-caller |
| DL/ID PDF417 (AAMVA) | parse and verify only | none — statutory | no_retention, hard flag |
Seven laws, not seven features.
The parts that cannot be renegotiated later.
-
01
No bare value anywhere.
A resolve answer says what was computed from the digits and what was looked up, and every enriched attribute travels in a provenance envelope: source, license class, fetched-at, digest.
-
02
Identity is free. It stays free.
resolve, verify and generate are pure and local: no network, no account, no key. The validation layer of the physical world is public regulation and royalty-free standards.
-
03
License-clean rails only.
USDA FoodData Central (CC0), openFDA (CC0), NHTSA vPIC (public domain), the Open Facts family (ODbL, as a segregated layer). No scraped aggregator, ever.
-
04
Sources are pinned like schemas.
Each source's manifest records the license text, its retrieval date and its sha256; an upstream license change is a failed pin, not a silent drift. pins prints the digests.
-
05
Conformant to the standard; explicit beyond it.
For GS1 keys the /01/* door serves the GS1-Conformant Resolver surface, RFC 9264 linksets and /.well-known/gs1resolver, as a delegating door: resolution is id.org.ai's. Every other family gets the same contract, labeled as an extension.
-
06
One door for people and for agents.
The same verb set over MCP; resolve and verify ship readOnlyHint: true with complete tool descriptions. Refusals are typed errors, never fabricated answers.
-
07
Joined, not adjacent.
A serialized 2D scan constructs a valid EPCIS 2.0 ObjectEvent, validated against epcis.dev's pinned schema; its bizTransactionList carries the PO/ASN context via transactions.dev; the attested observer rides in id.org.ai terms.
Get an API key.
The local verbs run from npx barcoding.dev today with no key. A key opens the network half of the verb set.