Blog/Ecommerce
12 min read

UPC Lookup by API: Two Databases, and One Barcode Neither Had

A soda barcode returned ingredients and a nutrition grade. A book came from another database. A phone cable came back not found, and still billed.

UPC Lookup by API: Two Databases, and One Barcode Neither Had

Copy this line to your agent to turn a barcode into a product record.

set up https://monid.ai/SKILL.md and use api.strale.io /x402/v2/barcode-lookup with a barcode

A UPC lookup is one call with one parameter, and what comes back depends entirely on what kind of thing the barcode is attached to. We looked up three barcodes on 2026-09-21 through one endpoint. A soda came back with its full ingredient list and a nutrition grade. A book came back from an entirely different database. A phone cable came back not found, with no database named at all. One endpoint, two upstream sources, and a whole category of goods that neither of them holds. This guide runs through Monid, the OpenRouter for agent tools.

What does searching for a UPC actually return?

A product record keyed on the number printed under the bars, with a field telling you which database answered.

The call is as simple as it gets

One parameter. barcode, as a string. No country, no marketplace, no key per retailer. Every response comes back in the same envelope regardless of which source filled it: barcode, found, source, product_name, brand, categories, quantity, ingredients, three grade fields, image_url, countries, allergens, nutrition, and a _meta block.

What a good hit looks like

Barcode 049000028911, 3.6 seconds:

{ "barcode": "049000028911", "found": true,
  "source": "open_food_facts",
  "product_name": "Diet Coke Soft Drink", "brand": "Coke",
  "categories": "Diet beverages, Sodas",
  "quantity": "144 fl oz",
  "ingredients": "CARBONATED WATER, CARAMEL COLOR, ASPARTAME…",
  "nutriscore_grade": "b", "nova_group": 4,
  "ecoscore_grade": "not-applicable" }

Ingredients, allergens, a nutrition object and three separate grading systems. That is more than a retailer's product page usually exposes, and it is the giveaway about where this data comes from.

The field that matters most is not the product

source. On this call it read open_food_facts, an open food database. That single field predicts everything about what else is in the response and whether a given barcode will be found at all, which is the next section.

📖 See also Amazon ASIN Scraper: What to Do When It Returns Nothing

Why did one barcode work and another come back empty?

Because there are two databases behind the endpoint and between them they cover food, books and not much else.

Three barcodes, three outcomes

BarcodeKind of thingResultSource namedWall clock
049000028911Soft drink multipackFound, full food recordopen_food_facts3,639 ms
9780134685991A programming bookFound, title onlyupcitemdb3,742 ms
190198001787Electronics accessoryNot foundnone3,781 ms

What the pattern says

Food is the strong case. An open food database is genuinely excellent at groceries, and it brings ingredients, allergens, nutrition and sustainability grades that a commercial product API would charge separately for.

Books fall through to a second source. The ISBN resolved from upcitemdb with a title and nothing else. The endpoint tried more than one place, which is good, and the second place is much thinner.

General merchandise is the gap. A common consumer electronics accessory returned found: false with no source at all. Not an error, not a timeout, and the call still took 3.8 seconds and still billed.

Two consequences for your code

Check found, not the status code. A miss arrives as an HTTP 200 with the full envelope and the boolean set false. A pipeline branching on status codes will treat every miss as a success with null fields, which is the same silent-failure class as the nested follower count.

Log source on every stored row. A dataset mixing open_food_facts rows and upcitemdb rows has two completely different field-completeness profiles, and six months later nobody will remember which rows could ever have had a nutrition score. Store the source and the _meta.provenance.fetched_at that comes with it.

How do you look up a barcode through one key?

Three steps, and the third is the one that covers the gap.

For agents

Grab an API key at app.monid.ai, then paste this to your agent and hand it the key:

set up https://monid.ai/SKILL.md

It learns the whole discover, inspect, run workflow itself. More in the agent quickstart.

For humans

npm install -g @monid-ai/cli
monid keys add -k <your-api-key> -l main

Step 1. Look the barcode up

The endpoints. api.strale.io/x402/v2/barcode-lookup, per call, takes barcode.

monid run -p api.strale.io -e /x402/v2/barcode-lookup \
  --query '{"barcode": "049000028911"}'

What comes back. The envelope above. Read found first, source second, and only then the product fields.

Step 2. Branch on the source

r = lookup(barcode)
if not r["found"]:
    product = fall_back(barcode)        # step 3
elif r["source"] == "open_food_facts":
    store_food(r)                        # nutrition, allergens, grades
else:
    store_thin(r)                        # name and brand only

Three branches, because the endpoint has three behaviours.

Step 3. Cover the gap with a retail route

When the barcode is not in either database, the product still exists and a retailer knows about it. Search a marketplace for the number as a query string and take the listing:

The endpoints. apify/delicious_zebu/amazon-product-details-scraper once you have an ASIN, or a marketplace search to get from the barcode string to a listing. The ASIN side and its failure modes are covered in the ASIN scraper guide.

Why this order. The barcode database is fast, cheap and structured when it hits. The retail route is slower and messier but has the long tail. Trying the cheap structured one first and falling back is strictly better than starting with the scraper.

Give this to your agent

$Set up https://monid.ai/SKILL.md, and then use Monid to look up each barcode in this list, record which source answered, and for every row that came back not found search Amazon for the barcode string and give me the product title and ASIN instead.

📖 See also Automate Amazon Product Detail Lookups

Why does a UPC not identify a product?

Because it identifies a package. The distinction costs people real money in retail analytics.

What our soda lookup actually returned

quantity: "144 fl oz" on a barcode most people would describe as Diet Coke. A hundred and forty-four fluid ounces is a twelve-pack of cans, not a can. The same drink has a different barcode for a single can, a different one for a twenty-ounce bottle, a different one for a two-litre bottle, and different ones again in other countries.

Why that matters

One product is many barcodes. If you are counting how many stores carry a drink, deduplicating by barcode undercounts, because each pack size is a separate number. You need the brand and a normalised product name, which the response gives you, not the barcode alone.

A barcode is not stable across regions. countries came back populated on our food hits, and the Nutella lookup listed Germany and the United States together. The same package sold in two markets can carry two numbers, and the same number can describe slightly different formulations.

Weight and count live in one free-text field. quantity is a string like 144 fl oz or 13oz, not a number and a unit. Parsing it is your job and it is the field most likely to break your unit economics silently.

The identifier hierarchy worth writing down

A GTIN identifies a package a manufacturer registered. An ASIN identifies a listing Amazon created, which may cover several packages or split one. An internal SKU identifies whatever your own systems decided. None of the three is a key for either of the others, and every pipeline that treats them as interchangeable eventually discovers it the expensive way.

Which endpoint should I use for which job?

EndpointWhat it doesInputOutputBest forBilling
api.strale.io/x402/v2/barcode-lookupBarcode to product recordbarcodeName, brand, categories, and food fields when the source is a food databaseThe first attempt, alwaysPer call
apify/delicious_zebu/amazon-product-details-scraperFull Amazon detail pageASINTitle, price, images, attributesThe fallback, and pricingPer result
api.kadec0.xyz/v1/nutritionFood nutrition by nameFood nameCalories, macros, microsWhen you have a name and no barcodePer call
mrscraper/cvs/productOne retailer's product pageProduct URL, ZIPPage HTML with local pricingStore-level availabilityPer call
hunterio/companies/findThe brand behind the productdomainFirmographicsTurning a brand into a companyPer call

Every row was verified with monid inspect on 2026-09-21. The table gives billing shape rather than figures, because shape drives design and current numbers live on monid.ai/tools.

The first row is where to start and the second is what to do when it misses, which on general merchandise it will.

When is a barcode the wrong key?

Four cases.

You are working in one marketplace. If everything you do is Amazon, the ASIN is the native key and going via a barcode adds a lossy hop. Start from the ASIN and stay there.

You need price. The barcode record carries no price, and it should not: price is per retailer, per region and per day. A barcode gets you identity; a retail endpoint gets you the number.

Your catalogue is not food or books. Our electronics accessory came back empty and the call still cost the same as a hit. If your catalogue is mostly general merchandise, test a representative sample before designing around this endpoint, because the hit rate is the whole economics.

You are deduplicating products. Barcodes split one product across pack sizes and regions. Deduplicate on brand plus a normalised name plus a parsed quantity, and keep the barcode as an attribute rather than the key.

And the disclosure: this is Monid's blog and we resell every endpoint here. We are also telling you that one of them missed a common consumer product and charged for the attempt, which is the information you need before putting it in a loop over a million rows.

Conclusion

Searching for a UPC works well and not uniformly. One endpoint with one parameter returned a full food record with ingredients, allergens and three grading systems for a soft drink, a bare title from a second database for a book, and nothing at all for a phone cable. The number of upstream databases is two, the number of categories they cover well is roughly one, and the field that tells you which of them answered is the one most people never store.

What matters more than the coverage is how you handle a miss. A not-found arrives as an HTTP 200 with a complete envelope and a false boolean, so branch on found rather than on the status code, log source on every row you keep, and have a retail fallback ready for the long tail. And remember that the number identifies a package: our soda barcode resolved to a hundred and forty-four fluid ounces, which is a case of cans wearing the name of a drink.

Free next step: run the endpoint against ten barcodes from your own catalogue and count how many come back found and which sources answered. That hit rate is the only number that decides whether this belongs in your pipeline. Start at monid.ai.

FAQ

What is the difference between UPC, EAN, GTIN and ASIN?

UPC is the twelve-digit code used mainly in North America and EAN is the thirteen-digit international form, with a leading zero making a UPC into an EAN. GTIN is the umbrella term covering both plus the longer case-level codes, and it is the word to use when you mean the manufacturer-registered number generally. ASIN is different in kind: it is an identifier Amazon assigns to its own listings, it exists only inside Amazon, and one ASIN can cover several GTINs or split a single one across variations. The endpoint here accepts the GTIN family, which is why an ISBN-13 resolved: a book's ISBN is also a valid GTIN.

What do you do about the coverage gaps?

Measure the hit rate on your own catalogue first, because ours varied from complete to nothing across three barcodes. Then build the fallback rather than hoping: when found is false, search a marketplace for the barcode as a plain query string, take the listing that comes back, and store it with a flag saying it came from the fallback rather than the barcode database. Keep the two provenances separate in your store, since a retail listing and a manufacturer registration disagree about pack size, naming and sometimes brand, and merging them silently produces a catalogue nobody can audit later.

How do you get from a barcode to a price?

Two hops, because the barcode record deliberately has no price in it. Resolve the barcode to a product name and brand, then search a retailer for that product and read the price from the listing, at a ZIP code or region if the retailer varies by location. The reason not to expect price in step one is that there is no such thing as the price of a barcode: it differs by retailer, by region and by day, and any single number attached to a GTIN would be wrong somewhere. Retail routes and their local-pricing parameters are the second half of that job.

Can you trust the nutrition and grade fields?

They come from an open, community-maintained food database, which means the coverage is remarkable and the individual rows vary. Our soda returned a Nutri-Score of b, a NOVA group of 4 and an Eco-Score of not-applicable, and that mix is typical: the grades are computed from whatever ingredient and nutrition data somebody contributed, so a missing input produces a missing or non-applicable grade rather than a wrong one. Treat the ingredient string and the nutrition object as good enough for filtering and segmentation, and not as a substitute for a label check if the answer has regulatory or health consequences.

Last updated September 2026.

upc lookupupc code lookupbarcode lookup apisearch for upcgtin lookup