Open Food Facts Scraper - Barcode, Nutrition, Allergens
Pricing
from $1.00 / 1,000 run start fees
Open Food Facts Scraper - Barcode, Nutrition, Allergens
Look up food products by EAN/UPC barcode or search by category, brand, label, country or Nutri-Score. Returns ingredients, allergens, additives, nutrition per 100g, Nutri-Score, NOVA and Eco-Score from the Open Food Facts open database.
Pricing
from $1.00 / 1,000 run start fees
Rating
0.0
(0)
Developer
SR
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Open Food Facts Scraper
Look up food products by barcode, or search a whole category, brand, label or country. You get the ingredient list, the declared allergens, the additives, the nutrition table per 100g, and the three scores people actually filter on: Nutri-Score (A-E), NOVA (processing level 1-4) and Eco-Score.
Open Food Facts is an open database of food products, contributed the way Wikipedia is and published under an open licence. This Actor reads its public API rather than scraping the site, so it is fast, stable and returns far more per product than the rendered page shows.
The barcode is the point
Every product is addressed by its EAN/UPC. That is an exact join key, not a fuzzy name match, and it is the same key the retail scrapers return.
So the workflow this Actor is built for is: scrape prices somewhere, put the barcodes in here, get the food data back. No name matching, no guessing which "Coca-Cola 330ml" is which. Feed it a list of barcodes and every row comes back keyed on the barcode you supplied.
barcodes: ["5000112548167", "737628064502"]
That returns Coca-Cola Light (Nutri-Score C, NOVA 4) and a Thai peanut noodle kit (Nutri-Score D, 385 kcal/100g, allergens: peanuts, sesame seeds, soybeans).
Or search instead
Leave the barcodes empty and filter:
| Field | Example | What it does |
|---|---|---|
categories | breakfast-cereals | Everything in a category (27,046 matches) |
brands | nestle | One brand's catalogue |
labels | organic, vegan, gluten-free | Products carrying a label |
countries | netherlands | Products sold in a market |
stores | lidl, albert-heijn | Products a retailer carries |
nutrition_grades | a | Only Nutri-Score A products |
allergens | gluten | Products declaring an allergen |
Filters combine. labels: organic plus countries: netherlands returns 4,064
matches. Use the tag form with hyphens, lower case.
What comes back
Per product:
- Identity:
barcode,product_name,generic_name,brands,quantity,serving_size,packaging - Composition:
ingredients_text,allergens,traces,additives(E-numbers),origins - Scores:
nutriscore_gradeA-E,nova_group1-4,ecoscore_gradeA-E - Nutrition per 100g:
energy_kcal_100g,fat_100g,saturated_fat_100g,carbohydrates_100g,sugars_100g,fiber_100g,proteins_100g,salt_100g,sodium_100g - Classification:
categories,labels,countries,stores - Images:
image_url, plus separate photos of the ingredient list and the nutrition table, which is what you want if you are checking a claim against the pack completeness: how filled-in the record is, 0 to 1
Tags arrive from the API language-prefixed (en:gluten). They are returned
stripped and readable (gluten), so they join cleanly.
Two honest notes about the data
is_stub tells you when a record is empty. Open Food Facts contains
barcodes that somebody scanned and nobody ever filled in. Those come back with
is_stub: true and a null product_name rather than being dropped, because
when you are joining on barcodes there is a real difference between "this
product is not in the database" and "it is in the database but empty". The
run summary counts them.
Coverage varies by country and brand. This is volunteer-contributed open
data, not a commercial catalogue. European food products, and French ones in
particular, are covered far better than most. A missing product is a gap in the
database, not a failure of the scraper, and the Actor says which of the two it
is: an unknown barcode returns a not_found error naming that barcode, never a
row of nulls.
About the intermittent 503s
Open Food Facts is a non-profit running on donated infrastructure, and its API
returns HTTP 503 intermittently and without much pattern. Measured while
building this: page_size=50 failed on a query where page_size=100 succeeded
seconds earlier, and page 2 failed on two different network exits right after
page 1 came back fine.
Two things this Actor does about that:
- Every request is retried with backoff (
retries, default 4). Most 503s clear on the next attempt. - A 503 is never parsed as an empty result. It arrives as a 22 KB HTML error page, and a scraper that reads it as JSON would report "this category has no products" — a confident wrong answer, on a run that looks successful. Non-JSON responses are retried and then reported as an explicit error, with the rows already collected returned intact.
If a page fails mid-pagination, you get the rows up to that point plus an error saying where it stopped. Partial and honest beats complete and wrong.
Input reference
| Field | Type | Default |
|---|---|---|
barcodes | list of EAN/UPC strings | — |
categories | category tag | breakfast-cereals |
brands, labels, countries, stores, allergens | tag string | — |
nutrition_grades | a-e | any |
limit | 1-5000 | 100 |
retries | 1-8 | 4 |
Give at least one barcode, a category, or one filter. An empty input is rejected with a message rather than walking the whole database.
Licence and attribution
Open Food Facts data is published under the Open Database License (ODbL). If you redistribute it you inherit that obligation, including attribution and share-alike on derived databases. The product photos carry their own licences. Check the Open Food Facts terms before republishing; using the data internally for analysis or enrichment is straightforward.