Add or edit product
add_or_edit_productAdd a new food product or update an existing one on Open Food Facts. Provide barcode, name, brands, categories, and other details to improve data quality. Helps build a global, open food database for nutrition and sustainability.
Instructions
Add a new product or edit an existing one on Open Food Facts. Requires OFF_USER_ID and OFF_PASSWORD.
The more fields you fill, the more useful the entry. At minimum provide product_name, brands, and categories — these feed the search index, and a sparse entry won't be findable. If you have a photo of the pack, transcribe everything you can read: ingredients, nutrition, origins, traceability stamps, recycling icons, certifications.
Fields that drive derived data:
ingredients_text → allergens, additives, NOVA group, fruit/veg %
nutrition + categories → Nutri-Score
packagings + origins → Eco-Score
product_name + brands + categories + labels → search _keywords
Pitfalls learned the hard way:
Free-text packaging shapes get fuzzy-matched against the taxonomy. "Pouch" resolves to "en:pouch-flask" (a stand-up spouted pouch). Use taxonomy IDs like "en:bag" or "en:individual-bag" instead.
OFF has no generic "pouch" shape in its taxonomy. For vacuum-sealed individual portions use "en:individual-bag"; for plastic film wrap use "en:film".
Recommended workflow for adding a product from photos:
Check if product exists with get_product first to avoid overwriting good data
Upload photos with upload_image. Prefer more photos over fewer — panels with text (ingredients, nutrition, certifications, recycling instructions) are highest value as OFF can OCR them. Plain sides with just a colour or logo are lowest value but still worth uploading if you have them. Use the most appropriate imagefield (front, ingredients, nutrition, packaging) and "other" for the rest.
Call this tool with all fields you can read from the photos. Set both quantity and serving_size.
Set packagings_complete: true only when all packaging components are listed
For products with only prepared nutrition (jelly mixes, powdered drinks, etc.), use nutrition_prepared instead of nutrition. For values printed as "< 0.5g" on the packet, pass the string "< 0.5" — the less-than modifier will be preserved.
Nutrition fields mirror the label columns: nutrition (per 100g as sold), nutrition_per_serving (per serving as sold), nutrition_prepared (per 100g prepared), nutrition_prepared_per_serving (per serving prepared). OFF auto-derives per-serving from per-100g + serving_size, so nutrition_per_serving is only needed when the label shows explicit per-serving values you want to preserve.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| barcode | Yes | Product barcode (EAN-13, UPC-A, EAN-8, etc.). Required. If the product doesn't exist yet, it will be created. | |
| product_name | No | Product name as it should appear in search results. Start from what's printed on the front of pack, but include the product type if it's not in the headline but is integral to the product — e.g. pack says "Fajita Halloumi" but it's a wrap, so use "High Protein Fajita Halloumi Wrap". Feeds search keywords. | |
| generic_name | No | Legal name / product description, often found near the ingredients, e.g. "Carbonated no added sugar pineapple and grapefruit flavoured soft drink with sweeteners". Feeds search keywords. | |
| brands | No | Brand name(s), comma-separated. For supermarket own-brands include both the sub-brand and the retailer, e.g. "The Fishmonger, Aldi" — this makes the product findable by either brand tag. Feeds search keywords. | |
| quantity | No | Net quantity as printed, e.g. "400g", "6 x 330ml", "1L". OFF parses this into product_quantity automatically. Always set this — it is separate from serving_size and OFF will warn "quantity undefined" without it. | |
| categories | No | Categories, comma-separated, most general first, e.g. "Seafood, Fishes, Salmons, Frozen fishes". Feeds search keywords and enables category browsing. | |
| labels | No | Certifications, claims, and dietary marks, comma-separated, e.g. "Sustainable Seafood MSC, Vegan, High protein, No added sugar, Made in Scotland". OFF canonicalises these against its taxonomy. | |
| ingredients_text | No | Full ingredients list verbatim from the pack. Mark allergens with underscores, e.g. "Wholegrain _Wheat_ (53%), _Wheat_ Protein, Sugar, _Barley_ Malt Extract". OFF parses this to detect allergens, additives, and compute NOVA group. Percentages matter for Nutri-Score fruit/veg estimation. | |
| allergens | No | Allergens, comma-separated, e.g. "en:gluten, en:milk". Usually auto-detected from ingredients_text underscores, so only set this if ingredients are unavailable. | |
| traces | No | "May contain" allergens, comma-separated, e.g. "en:nuts, en:peanuts, en:milk, en:sesame-seeds, en:soybeans". | |
| origins | No | Where the ingredients come from, e.g. "Scotland" or "Northeast Pacific (FAO 67), Northwest Pacific (FAO 61)". Affects Eco-Score. | |
| emb_codes | No | Traceability/health marks — the oval stamp with a country code, e.g. "CN 2100/02398 EC" or "UK MD047 EC". Comma-separated if multiple. | |
| manufacturing_places | No | Where the product was made/packed, e.g. "Grimsby, United Kingdom". | |
| countries | No | Countries where sold, comma-separated, e.g. "United Kingdom, Ireland". | |
| stores | No | Retailers where sold, comma-separated, e.g. "Aldi, Iceland". | |
| packagings | No | Structured packaging components. Each item describes one physical part of the packaging (outer box, inner bag, lid, etc.). This populates the packagings array the UI displays and feeds the Eco-Score. Use taxonomy IDs ("en:box") not free text. | |
| packagings_complete | No | Set to true to mark that all packaging components have been listed. Only set this when you are confident the packagings array is complete. | |
| packaging_text | No | Recycling instructions and/or packaging information as printed on the pack, e.g. "Tray - Plastic - Recycle\nFilm - Plastic - Do Not Recycle". This is the human-readable text, separate from the structured packagings array. | |
| serving_size | No | Serving size as printed, e.g. "30g", "100g (1 fillet)", "330ml (1 can)". OFF uses this to derive per-serving values from per-100g when per-serving values are not provided explicitly. | |
| nutrition | No | Nutrition facts as sold, per 100g (or per 100ml for beverages). Transcribe per-100g values exactly as printed — don't back-calculate from per-serving. For values printed as "< 0.5g" on the packet, pass the string "< 0.5" — the less-than modifier will be preserved. | |
| nutrition_per_serving | No | Nutrition facts as sold, per serving. Use this when the label shows a separate per-serving column alongside per-100g. If omitted and serving_size is set, OFF auto-derives per-serving from per-100g values. | |
| nutrition_prepared | No | Nutrition facts as prepared, per 100g (or per 100ml). For products like jelly mixes, powdered drinks, instant noodles — anything where the packet shows separate "as prepared" nutrition values. | |
| nutrition_prepared_per_serving | No | Nutrition facts as prepared, per serving. Use this when the label shows a separate per-serving column for prepared values. | |
| comment | No | Edit comment explaining what was changed, shown in product edit history. E.g. "Add nutrition data from packaging photo". | |
| language | No | Language code for language-dependent fields (product_name, generic_name, ingredients_text). Defaults to "en". Set to "fr" for French products, etc. This determines which language version of these fields is written. | en |
| extra_fields | No | Raw form fields for anything else. Useful for less common nutriments (nutriment_sodium, nutriment_calcium, nutriment_vitamin-c) or fields not exposed above. Values are strings. |