Barcode Lookup API

A barcode in, a product out — and the maths checked first

The Barcode Lookup API resolves UPC, EAN and GTIN codes as clean JSON.

no credit card1,000 free credits · instant API key · live in 10 seconds
Missing a Barcode Lookup endpoint, or need a source we don't have yet?Contact us real people · same-day reply.
B
/barcode/v1

7 active endpoints, on 0 and 1 credit tiers.

  • POST/barcode/v1/lookup
  • POST/barcode/v1/batch
  • POST/barcode/v1/search
  • POST/barcode/v1/by_brand
  • POST/barcode/v1/by_prefix
  • POST/barcode/v1/by_mpn
  • POST/barcode/v1/validate

What Barcode Lookup endpoints does ReefAPI ship?

7 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.

7 endpoints

lookup

1 cr

Barcode → one merged product.

required
barcode
optional
source, off_db, deep_weight

batch

1 cr

Up to 20 barcodes in one call → array of merged products (input order preserved), each with i…

required
barcodes
optional
source, off_db, deep_weight

search

1 cr

Free-text product-name search across the open databases → product cards with pagination.

required
query
optional
category, off_db, source, page, page_size

by_brand

1 cr

All products for a brand/manufacturer → product cards with pagination.

required
brand
optional
category, off_db, page, page_size

by_prefix

1 cr

GS1 company-prefix (partial-barcode) search → products whose barcode starts with the given 6+…

required
prefix
optional
off_db, page, page_size

by_mpn

1 cr

Manufacturer-Part-Number / model lookup → products with that MPN/model (UPCitemdb keyword ind…

required
mpn
optional
page, page_size

validate

0 cr

Validate + decode a barcode WITHOUT a network call.

required
barcode
optional

Every parameter, every allowed value →

Barcode Lookup API

3 of 7 endpoints, ready to run

View docs ↗

The product behind a barcode: title, brand, category, images, and the code itself decoded — its GTIN form, whether the check digit is right, and the country that issued the prefix.

1 credit1 required · 1 optional
POST/barcode/v1/lookup
ok2311 ms · 1 records · sample
{
  "ok": true,
  "meta": {
    "api": "barcode",
    "endpoint": "lookup",
    "mode": "live",
    "latency_ms": 2310.8,
    "record_count": 1,
    "cache_hit": false
  },
  "data": {
    "product": {
      "barcode": "5449000000996",
      "gtin13": "5449000000996",
      "gtin_type": "GTIN-13 (EAN-13)",
      "valid_check_digit": true,
      "issuing_country": "Belgium / Luxembourg",
      "is_isbn": false,
      "title": "Coca-Cola",
      "brand": "Coca-Cola",
      "category": "pt:bebidas cafeína",
      "description": "Bebida refrescante aromatizada",
      "image": "https://images.openfoodfacts.org/images/products/544/900/000/0996/front_en.1129.400.jpg",
      "images": [
        "https://images.openfoodfacts.org/images/products/544/900/000/0996/front_en.1129.400.jpg",
        "https://images.openfoodfacts.org/images/products/544/900/000/0996/front_en.1129.400.jpg"
      ],
      "brands": [
        "Coca-Cola"
      ],
      "categories": [
        "Colas",
        "pt:bebidas cafeína"
      ],
      "quantity": "330 ml",
      "ingredients": "Agua carbonatada, azúcar, colorante (E-150d), acidulante (ácido fosfórico), aromas naturales (contiene cafeína).",
      "labels": [
        "Made in the EU",
        "Triman"
      ],
      "stores": [
        "ahorramas",
        "carrefour",
        "greggs"
      ],
      "countries": [
        "Albania",
        "Austria",
        "Belgium"
      ],
      "packaging": "Unknown packaging",
      "nutrition": {
        "energy_kcal_100g": 42,
        "energy_kj_100g": 180,
        "fat_100g": 0,
        "saturated_fat_100g": 0,
        "carbohydrates_100g": 10.6,
        "sugars_100g": 10.6,
        "proteins_100g": 0,
        "salt_100g": 0,
        "sodium_100g": 0,
        "serving_size": "1 portion (330 ml)",
        "nutriscore_grade": "e",
        "nova_group": 4,
        "ecoscore_grade": "not-applicable"
      },
      "is_food": true,
      "off_url": "https://world.openfoodfacts.org/product/5449000000996",
      "color": "White",
      "category_path": "Media > DVDs & Videos",
      "offers": [
        {
          "merchant": "eBay.com",
          "domain": null,
          "title": "Portable 4.3\" Glass Bong Smoking Water Pipe Cool Bong Bubbler Hookah w/14mm Bowl",
          "price": 13.94,
          "list_price": null,
          "shipping": null,
          "condition": null,
          "currency": "USD",
          "availability": null,
          "link": null,
          "updated_t": "2026-08-28 17:24:54"
        },
        {
          "merchant": "eBay US Used",
          "domain": null,
          "title": "Japanese Satsuma vintage Victorian Meiji Period oriental antique bottle vase F",
          "price": 88.35,
          "list_price": null,
          "shipping": null,
          "condition": null,
          "currency": "USD",
          "availability": null,
          "link": null,
          "updated_t": "2026-08-28 17:24:54"
        },
        {
          "merchant": "OnBuy.com",
          "domain": null,
          "title": "Hannibal Rising - DVD",
          "price": 6.32,
          "list_price": null,
          "shipping": null,
          "condition": null,
          "currency": null,
          "availability": null,
          "link": null,
          "updated_t": "2019-10-18 23:47:56"
        }
      ],
      "store_count": 5,
      "price_lowest": 6.32,
      "price_highest": 88.35,
      "currency": "USD",
      "country_of_registration": "Belgium & Luxembourg",
      "name_variations": [
        "Hannibal Rising - DVD",
        "Id1398z - Hannibal Rising - Dvd -",
        "Portable 4.3\" Glass Bong Smoking Water Pipe Cool Bong Bubbler Hookah w/14mm Bowl"
      ],
      "upcitemdb_url": "https://www.upcitemdb.com/upc/5449000000996",
      "weight": 1,
      "weight_unit": "lb",
      "weight_grams": 453.592,
      "weight_type": "package",
      "weight_source": "upcitemdb",
      "weight_raw": "1.00 lbs",
      "net_content": {
        "value": 330,
        "unit": "ml",
        "grams": null,
        "is_volume": true,
        "raw": "330 ml"
      },
      "weight_confidence": "medium",
      "weight_flags": [],
      "sources": [
        "openfoodfacts",
        "upcitemdb"
      ],
      "field_source": {
        "title": "openfoodfacts",
        "brand": "openfoodfacts",
        "category": "openfoodfacts",
        "description": "openfoodfacts",
        "image": "openfoodfacts",
        "brands": "openfoodfacts",
        "categories": "openfoodfacts",
        "quantity": "openfoodfacts",
        "ingredients": "openfoodfacts",
        "labels": "openfoodfacts",
        "stores": "openfoodfacts",
        "countries": "openfoodfacts",
        "packaging": "openfoodfacts",
        "nutrition": "openfoodfacts",
        "is_food": "openfoodfacts",
        "off_url": "openfoodfacts",
        "color": "upcitemdb",
        "category_path": "upcitemdb",
        "offers": "upcitemdb",
        "store_count": "upcitemdb",
        "price_lowest": "upcitemdb",
        "price_highest": "upcitemdb",
        "currency": "upcitemdb",
        "country_of_registration": "upcitemdb",
        "name_variations": "upcitemdb",
        "upcitemdb_url": "upcitemdb",
        "net_content": "openfoodfacts",
        "weight": "upcitemdb"
      },
      "resolution_level": "full"
    }
  }
}
Real response, fetched from the live endpoint with the parameters on the left — trimmed to the first few rows, with seller names left out. Press Try it for the untrimmed response.

How the Barcode Lookup API works

Barcode Lookup is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.

01
Authenticate
x-api-key header

No OAuth app, no request signing, no per-site account. One key covers all 184 engines.

02
Call
POST /barcode/v1/…

Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.

03
Pay
0 or 1 credits per call

Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.

04
Read
{ ok, data, meta, error }

One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.

Cleaning a supplier feed before you try to look anything up

Supplier spreadsheets are full of barcodes with a digit dropped, a leading zero eaten by Excel, or a number that was never a GTIN. Looking those up wastes a call each and returns nothing useful.

01validate
POST/barcode/v1/validate
{"barcode": "5449000000997"}

Offline arithmetic, tens of milliseconds. A bad code came back with the digit it carries, the digit it should carry, and a plain-English reason.

02batch
POST/barcode/v1/batch
{"barcodes": ["5449000000996", "0885909950805"]}

Only the codes that survived validation. One call for the list rather than one per row.

The validation step is free of network calls and removes the rows that could never have matched, so the lookups you do pay for are the ones with a chance of returning something.

request
curl -X POST https://api.reefapi.com/barcode/v1/lookup \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"barcode":"5449000000996"}'
response envelope
{
  "ok": true,
  "data": { … },
  "meta": {
    "api": "barcode",
    "endpoint": "lookup",
    "mode": "live",
    "latency_ms": …,
    "record_count": …
  },
  "error": null
}

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 sentgtin_type returnedgtin13 after normalizationissuing_country
5449000000996 (13 digits)GTIN-13 (EAN-13)5449000000996Belgium / Luxembourg
0885909950805 (13 digits)GTIN-13 (EAN-13)0885909950805US / Canada
9780262033848 (ISBN-13)GTIN-13 (EAN-13), is_isbn true9780262033848ISBN (Bookland, books)
96385074 (8 digits)GTIN-8 (EAN-8)0000096385074see the note below
00012345678905 (14 digits)GTIN-14 (ITF-14)0012345678905US / Canada
5449000000997 (bad check digit)GTIN-13 (EAN-13), valid false5449000000997Belgium / 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.

Which catalogue answers, and what the answer looks like when it comes from a crowd

Measured on a food barcode, an electronics barcode and a deliberately broken one. Two rows go against us.

The code is decoded even when the product is not found

Every response reports the GTIN family, whether the check digit is valid, and the country that issued the prefix — a Belgian code and a US/Canadian one were named as such. That part is arithmetic on the number itself, so it holds regardless of whether any catalogue knows the product.

Food and general retail come from different catalogues

A drinks barcode answered with nutrition-grade fields — nutrition score, processing group, quantity. A consumer-electronics barcode answered with model number, manufacturer part number and colour instead. Same endpoint, different shape, because the underlying catalogues are different; read the fields that are present rather than expecting one schema.

Against us: food data is crowd-contributed, so its language varies

A globally-sold soft drink came back with its category and description in Portuguese, because that is the language of the contributor who filled that record in. Titles and brands are usually stable; free-text categories and descriptions are whatever the last editor wrote, in whatever language they wrote it. If you display these fields, expect to have to handle that.

Against us: the search total saturates on broad queries

A narrow brand query returned a real total in the hundreds. A broad one returned exactly ten thousand, which is a ceiling rather than a count. Use the total for narrow searches and treat a round ten thousand as 'more than we will tell you'. A query that matches nothing returns no rows and no total at all, rather than a fabricated zero.

Validation explains itself

A code with one digit changed came back invalid with the reason naming the mod-10 check, the digit present and the digit expected. That is enough to tell a transposed pair from a truncated code, which matters when you are deciding whether to fix a supplier row or discard it.

What people build with Barcode Lookup

The jobs this data is most often used for.

7

endpoints

0/1

credits per call

01

Inventory apps call lookup to resolve a scanned barcode to a product.

02

Catalog enrichment uses by_brand and by_mpn to match products.

03

Retail systems use validate to check a GTIN's check digit.

What Barcode Lookup data costs

The cheapest call here is 0 credits, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.

Full pricing →
$0.67–$1.50 / 1,000 credits
  • 1,000 free credits on signup, no card
  • One key, all 184 APIs, one credit pool
  • Failed and blocked calls are never charged
  • Credits roll over and never expire

Call it in two lines

Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.

curl
curl -X POST https://api.reefapi.com/barcode/v1/lookup \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"barcode":"5449000000996"}'
python
import requests

r = requests.post(
    "https://api.reefapi.com/barcode/v1/lookup",
    headers={"x-api-key": REEF_KEY},
    json={
  "barcode": "5449000000996"
},
)
print(r.json()["data"])
FAQ

Have a question? We got answers.

The questions people actually ask before wiring up Barcode Lookup.

Get a free key →
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.

19 Utilities & AI APIs on the same key

One key, one credit pool, one response envelope. If you are pulling Barcode Lookup, you are one call away from the rest of the category — no second contract, no second integration.

Need something this API does not do?

Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.

0/4000

No account needed · we reply from [email protected]

Try it on your own data before you pay anything

The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 183 APIs, and the same envelope everywhere.

Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-30.