Barcode Lookup API & Scraper
The Barcode Lookup API resolves UPC, EAN and GTIN codes as clean JSON.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
The primary lookup endpoint returns a product by barcode with GTIN, check-digit validity, issuing country, title, brand and category, and you can batch, search, look up by brand, prefix or MPN, and validate a code. It is built for retail, inventory and catalog-enrichment tools that need product identity from a barcode. One ReefAPI key, one shared credit pool, the standard envelope.
Barcode formats accepted, and what each one normalizes to
Whatever length you send, the engine decodes it to a single 13-digit form so you can key your own database on one field. Every row below is a live validate call made on 2026-08-27, and validate does the whole decode offline with no upstream request. Spaces and dashes are stripped before the check.
| Barcode sent | gtin_type returned | gtin13 after normalization | issuing_country |
|---|---|---|---|
| 5449000000996 (13 digits) | GTIN-13 (EAN-13) | 5449000000996 | Belgium / Luxembourg |
| 0885909950805 (13 digits) | GTIN-13 (EAN-13) | 0885909950805 | US / Canada |
| 9780262033848 (ISBN-13) | GTIN-13 (EAN-13), is_isbn true | 9780262033848 | ISBN (Bookland, books) |
| 96385074 (8 digits) | GTIN-8 (EAN-8) | 0000096385074 | see the note below |
| 00012345678905 (14 digits) | GTIN-14 (ITF-14) | 0012345678905 | US / Canada |
| 5449000000997 (bad check digit) | GTIN-13 (EAN-13), valid false | 5449000000997 | Belgium / Luxembourg |
A 12-digit UPC-A is accepted too and normalizes by gaining a leading zero, which is why a US barcode reports issuing_country 'US / Canada' off the 0 prefix. issuing_country is decoded from the normalized gtin13, so for an 8-digit EAN-8 it is decoded from the zero-padded form and is not a real GS1 country assignment; ignore that column for 8-digit codes. A failed check digit is reported rather than thrown: validate returned valid false with reason 'check digit 7 != expected 6 (mod-10)' and still filled in the type and country.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/barcode/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"query": "nutella"
}
}{
"ok": true,
"meta": {
"api": "barcode",
"endpoint": "search",
"mode": "live",
"latency_ms": 16018.7,
"record_count": 5,
"bytes": 20424,
"cache_hit": false,
"method": "open_data_multi_source (off+upcitemdb-web-scrape)",
"query": "nutella",
"source": "upcitemdb",
"page": 1,
"page_size": 20,
"has_more": true,
"count": 2673,
"next_page": 2
},
"data": {
"products": [
{
"barcode": "[redacted-phone]",
"ean": "[redacted-phone]",
"upc": "[redacted-phone]",
"isbn": null,
"title": "Nutella & Go! Breadstick 1.9 Oz (Pack of 12)",
"brand": "Nutella",
"model": "80314",
"mpn": "80314",
"category": "Snack Foods",
"category_path": "Food, Beverages & Tobacco > Food Items > Snack Foods",
"description": "Nutella s uniquely delicious one-of-a-kind hazelnut and cocoa taste now with complementary breadstick snacks.",
"image": "http://pics.drugstore.com/prodimg/484398/450.jpg",
"images": [
"http://pics.drugstore.com/prodimg/484398/450.jpg",
"http://c.shld.net/rpx/i/s/pi/mp/4143/[redacted-phone]?src=http%3A%2F%2Ficdn.tonzof.com%2F3%2F5%2F4%2F[redacted-phone]%2F175757.JPG&d=6f2ba53db11e4672325d38285d44aa1e95268711",
"http://pics2.ds-static.com/prodimg/484398/300.JPG"
],
"color": "Black",
"size": null,
"dimension": "9.6 X 6.8 X 8 inches",
"weight": "1.4 Pounds",
"offers": [
{
"merchant": "[trimmed-depth]",
"domain": "[trimmed-depth]",
"title": "[trimmed-depth]",
"price": "[trimmed-depth]",
"list_price": "[trimmed-depth]",
"shipping": "[trimmed-depth]",
"condition": "[trimmed-depth]",
"currency": "[trimmed-depth]",
"availability": "[trimmed-depth]",
"link": "[trimmed-depth]",
"updated_t": "[trimmed-depth]"
},
{
"merchant": "[trimmed-depth]",
"domain": "[trimmed-depth]",
"title": "[trimmed-depth]",
"price": "[trimmed-depth]",
"list_price": "[trimmed-depth]",
"shipping": "[trimmed-depth]",
"condition": "[trimmed-depth]",
"currency": "[trimmed-depth]",
"availability": "[trimmed-depth]",
"link": "[trimmed-depth]",
"updated_t": "[trimmed-depth]"
},
{
"merchant": "[trimmed-depth]",
"domain": "[trimmed-depth]",
"title": "[trimmed-depth]",
"price": "[trimmed-depth]",
"list_price": "[trimmed-depth]",
"shipping": "[trimmed-depth]",
"condition": "[trimmed-depth]",
"currency": "[trimmed-depth]",
"availability": "[trimmed-depth]",
"link": "[trimmed-depth]",
"updated_t": "[trimmed-depth]"
}
],
"store_count": 24,
"price_lowest": 8.89,
"price_highest": 63.04,
"currency": null,
"upcitemdb_url": "https://www.upcitemdb.com/upc/[redacted-phone]",
"source": "upcitemdb"
},
{
"barcode": "[redacted-phone]",
"ean": "[redacted-phone]",
"upc": "[redacted-phone]",
"isbn": null,
"title": "Nutella B-Ready - 6ct/6oz",
"brand": "Nutella",
"model": "87880865",
"mpn": "87880865",
"category": null,
"category_path": "",
"description": "Ready to love Nutella in a whole new way? Meet Nutella B-ready, the deliciously convenient snack that combines a crisp wafer shell and the original and tasty Nutella in one treat. The Nutella B-ready bars features a delicate crunchy wafer shell filled with creamy Nutella and sprinkled with puffed wheat crisps for a satisfying multi-texture experience. It?s the ready-to-enjoy Nutella you know and love, now as the perfect snack for your busiest days. For more than 50 years, Nutella has been delighting chocolate lovers worldwide with its signature creamy texture and authentic hazelnut and cocoa f",
"image": "https://pics.walgreens.com/prodimg/666724/450.jpg",
"images": [
"https://pics.walgreens.com/prodimg/666724/450.jpg",
"https://target.scene7.com/is/image/Target/GUEST_22b1967e-645b-42b3-b309-04d014fe25b7?wid=1000&hei=1000",
"https://i5.walmartimages.com/asr/811a8d43-e[redacted-phone]-ae1b3a3439d4.968ad745d15e0a9b483c407a4607c3fa.jpeg?odnHeight=450&odnWidth=450&odnBg=ffffff"
],
"color": null,
"size": null,
"dimension": null,
"weight": "0.3",
"offers": [
{
"merchant": "[trimmed-depth]",
"domain": "[trimmed-depth]",
"title": "[trimmed-depth]",
"price": "[trimmed-depth]",
"list_price": "[trimmed-depth]",
"shipping": "[trimmed-depth]",
"condition": "[trimmed-depth]",
"currency": "[trimmed-depth]",
"availability": "[trimmed-depth]",
"link": "[trimmed-depth]",
"updated_t": "[trimmed-depth]"
},
{
"merchant": "[trimmed-depth]",
"domain": "[trimmed-depth]",
"title": "[trimmed-depth]",
"price": "[trimmed-depth]",
"list_price": "[trimmed-depth]",
"shipping": "[trimmed-depth]",
"condition": "[trimmed-depth]",
"currency": "[trimmed-depth]",
"availability": "[trimmed-depth]",
"link": "[trimmed-depth]",
"updated_t": "[trimmed-depth]"
},
{
"merchant": "[trimmed-depth]",
"domain": "[trimmed-depth]",
"title": "[trimmed-depth]",
"price": "[trimmed-depth]",
"list_price": "[trimmed-depth]",
"shipping": "[trimmed-depth]",
"condition": "[trimmed-depth]",
"currency": "[trimmed-depth]",
"availability": "[trimmed-depth]",
"link": "[trimmed-depth]",
"updated_t": "[trimmed-depth]"
}
],
"store_count": 4,
"price_lowest": 3.49,
"price_highest": 13.99,
"currency": null,
"upcitemdb_url": "https://www.upcitemdb.com/upc/[redacted-phone]",
"source": "upcitemdb"
},
{
"barcode": "[redacted-phone]",
"ean": "[redacted-phone]",
"upc": "[redacted-phone]",
"isbn": null,
"title": "Nutella B-Ready Crispy Wafers 0.7 Ounce (Pack of 36)",
"brand": "Nutella",
"model": "1694269",
"mpn": "1694269",
"category": null,
"category_path": "",
"description": "Nutella B-Ready Crispy Wafers 0.7 Ounce (Pack of 36) A crispy wafer baked to perfection filled with delicious Nutella and sprinkled with wheat crisps. Its soft crispy and convenient. B-Ready is the perfect way to bring a smile to your mid-morning break. Individually wrapped and all for less than 120 calories. Ingredients: HAZELNUT Spread with cocoa 81.5% (sugar palm oil hazelnuts (13%) fat reduced cocoa (7.4%) skimmed milk powder (6.6%) whey powder (milk) emulsifier: lecithin (soy) vanillin wheat flour bakers yeast powdered BARLEY malt extract salt skimmed milk powder emulsifier: lecithin (soy",
"image": "https://i5.walmartimages.com/asr/60404d26-d[redacted-phone]c6f-cf53bb8bb543.3f637c95bff284229edbc733bd026e38.jpeg?odnHeight=450&odnWidth=450&odnBg=ffffff",
"images": [
"https://i5.walmartimages.com/asr/60404d26-d[redacted-phone]c6f-cf53bb8bb543.3f637c95bff284229edbc733bd026e38.jpeg?odnHeight=450&odnWidth=450&odnBg=ffffff",
"http://site.unbeatablesale.com/SCTP1281.JPG",
"https://cdn3.ykso.co/images/2023/04/14/19/6439e326a7fcf[redacted-phone]a8-transformed.jpeg"
],
"color": "Black",
"size": "0.7 oz",
"dimension": null,
"weight": "4 lb",
"offers": [
{
"merchant": "[trimmed-depth]",
"domain": "[trimmed-depth]",
"title": "[trimmed-depth]",
"price": "[trimmed-depth]",
"list_price": "[trimmed-depth]",
"shipping": "[trimmed-depth]",
"condition": "[trimmed-depth]",
"currency": "[trimmed-depth]",
"availability": "[trimmed-depth]",
"link": "[trimmed-depth]",
"updated_t": "[trimmed-depth]"
},
{
"merchant": "[trimmed-depth]",
"domain": "[trimmed-depth]",
"title": "[trimmed-depth]",
"price": "[trimmed-depth]",
"list_price": "[trimmed-depth]",
"shipping": "[trimmed-depth]",
"condition": "[trimmed-depth]",
"currency": "[trimmed-depth]",
"availability": "[trimmed-depth]",
"link": "[trimmed-depth]",
"updated_t": "[trimmed-depth]"
},
{
"merchant": "[trimmed-depth]",
"domain": "[trimmed-depth]",
"title": "[trimmed-depth]",
"price": "[trimmed-depth]",
"list_price": "[trimmed-depth]",
"shipping": "[trimmed-depth]",
"condition": "[trimmed-depth]",
"currency": "[trimmed-depth]",
"availability": "[trimmed-depth]",
"link": "[trimmed-depth]",
"updated_t": "[trimmed-depth]"
}
],
"store_count": 5,
"price_lowest": 23.37,
"price_highest": 52.99,
"currency": null,
"upcitemdb_url": "https://www.upcitemdb.com/upc/[redacted-phone]",
"source": "upcitemdb"
}
],
"query": "nutella",
"page": 1,
"page_size": 20,
"has_more": true,
"count": 2673,
"next_page": 2
}
}What the Barcode Lookup API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| lookup | Barcode → one merged product: title/brand/category/image/description + dimensions/model + PACKAGE WEIGHT as an explicit {weight, weight_unit} pair (plus weight_grams, weight_type, weight_source and a weight_confidence flag) + retailer offers&prices (UPCitemdb) + net content + nutrition/ingredients/allergens if food (OFF). Includes check-digit validation, GTIN-13 normalization and issuing-country. source=auto merges them, and falls back to go-upc — US general merchandise, retailer private label, apparel and footwear — for barcodes the first two do not carry. Weight is published by roughly 1 barcode in 5 (1 in 3 with deep_weight=true) — when no source states one, weight is null, never 0 and never borrowed from a similar product. | Ops teams call lookup to get barcode → one merged product. | barcode, source, off_db, deep_weight |
| batch | Up to 20 barcodes in one call → array of merged products (input order preserved), each with its own source/validation. The competitor caps at 10. | Developer tools call batch to get up to 20 barcodes in one call → array of merged products (input order preserved), each with i…. | barcodes, source, off_db, deep_weight |
| search | Free-text product-name search across the open databases → product cards with pagination. Optional category scope. (Competitor: keyword/title/category search.) | Validation workflows call search to get free-text product-name search across the open databases → product cards with pagination. | query, category, off_db, source, page, ... |
| by_brand | All products for a brand/manufacturer → product cards with pagination. (Competitor: brand + manufacturer search.) | Data-quality teams call by_brand to get all products for a brand/manufacturer → product cards with pagination. | brand, category, off_db, page, page_size |
| by_prefix | GS1 company-prefix (partial-barcode) search → products whose barcode starts with the given 6+ digits, plus the decoded issuing country. (Competitor: `491234*` partial method.) | Ops teams call by_prefix to get gS1 company-prefix (partial-barcode) search → products whose barcode starts with the given 6+…. | prefix, off_db, page, page_size |
| by_mpn | Manufacturer-Part-Number / model lookup → products with that MPN/model (UPCitemdb keyword index over the MPN). Exact model/mpn matches are surfaced first. Closes the competitor's mpn query-method (the proprietary mpn= DB-index isn't on the open tier, but the keyword index resolves real MPNs — Logitech 910-005565, Sony WH-1000XM4, Canon 2727C002 all verified). | Developer tools call by_mpn to get manufacturer-Part-Number / model lookup → products with that MPN/model (UPCitemdb keyword ind…. | mpn, page, page_size |
| validate | Validate + decode a barcode WITHOUT a network call: mod-10 check digit, GTIN type, GTIN-13 normalization, GS1 issuing country, ISBN/Bookland detection. (We EXCEED the competitor here — it has no standalone validate.) | Validation workflows call validate to validate + decode a barcode WITHOUT a network call. | barcode |
Call search from your stack
curl -X POST https://api.reefapi.com/barcode/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"query":"nutella"}'import requests
r = requests.post(
"https://api.reefapi.com/barcode/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"query": "nutella"
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/barcode/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"query": "nutella"
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.barcode.search with {"query":"nutella"}.Who uses this API and why
- Inventory apps call lookup to resolve a scanned barcode to a product.
- Catalog enrichment uses by_brand and by_mpn to match products.
- Retail systems use validate to check a GTIN's check digit.
Questions developers ask before integrating
Which barcode standards does this API recognize?
UPC-A at 12 digits, EAN-13 and ISBN-13 at 13, EAN-8 at 8, and GTIN-14 or ITF-14 at 14. All of them are normalized to a 13-digit gtin13 and tagged with gtin_type. ISBNs are detected separately: 9780262033848 came back with is_isbn true and issuing_country 'ISBN (Bookland, books)', because 978 and 979 are the book prefixes rather than a country.
What happens if the check digit is wrong?
It depends on the action, and none of them raise a parameter error. validate returns valid false with expected_check_digit and a reason string, and still decodes the type and country. lookup goes ahead and queries the sources, then returns ok false with error code NOT_FOUND because no product carries that number. In batch the item comes back as found false with valid false while the other barcodes in the same call still resolve.
What does the API return for a barcode nobody has catalogued?
lookup returns ok false with error code NOT_FOUND and a message naming the sources it tried. batch never fails as a whole: a four-barcode call on 2026-08-27 returned meta.requested 4 and meta.found_count 3, with the unresolved item as {input, barcode, found: false} and each resolved one carrying a nested product object. Results stay in the order you sent them, so you can zip them against your input list.
Why do some barcodes return nutrition and others return retailer prices?
Two different open datasets are merged and which fields you get depends on which one has the product. Food comes from Open Food Facts, general merchandise from UPCitemdb. A Coca-Cola EAN returned nutrition with energy_kcal_100g 42, sugars_100g 10.6, nutriscore_grade 'e' and nova_group 4, plus retailer offers. An iPhone UPC returned sources ['upcitemdb'] only, with nutrition and ingredients null and eight retailer offers. Read the sources array and the field_source map to see where each field came from.
Is the weight field the product weight or the package weight?
Package weight, and it is not the same thing as net content. A 330 ml can of Coca-Cola returned weight 1.0 with weight_unit 'lb', weight_grams 453.592, weight_type 'package', weight_source 'upcitemdb' and weight_confidence 'medium', while net_content returned value 330, unit 'ml' and is_volume true. Use net_content for what is inside and weight for shipping. Check weight_confidence before trusting either, and set deep_weight true to spend one extra upstream call chasing a weight the product page did not publish.
How current are the retailer prices in offers?
They vary a lot, and each offer carries its own updated_t so you can tell. In one measured Coca-Cola lookup the offers ranged from an eBay row stamped 2026-08-25 to an OnBuy row stamped 2019-10-18. price_lowest and price_highest are computed across whatever offers came back, stale rows included, so filter on updated_t before you quote a price.
Can I search without knowing the full barcode?
Yes, three ways. by_prefix takes the first six or more digits, the GS1 company prefix, and returns products whose barcode starts with them plus the decoded issuing country; prefix 5449000 returned 'Belgium / Luxembourg'. search does free-text product-name matching, by_brand lists a brand's products, and by_mpn resolves a manufacturer part number such as 910-005565 with exact matches surfaced first.
How many barcodes can go in one call?
batch takes up to 20 in one request, as a JSON array or a comma-separated string, and preserves input order. meta reports requested, found_count and weight_found_count so you can measure coverage without walking the array. Note that lookup is a network call against two open datasets while validate is pure arithmetic, so validate is the cheap way to screen a list before spending lookups on it.
What is the Barcode Lookup API?
Barcode Lookup API is a ReefAPI endpoint group for barcode lookup It returns live JSON through POST requests under /barcode/v1.
Is the Barcode Lookup API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Barcode Lookup calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Barcode Lookup login or account?
No login to Barcode Lookup is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Barcode Lookup data?
The page example is captured from a live lookup call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Barcode Lookup API use?
Barcode Lookup actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.
Can I call Barcode Lookup from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call barcode actions with the same key, credit pool and JSON envelope used by normal REST requests.