Extracting a food’s packaging from Agribalyse is not a matter of selecting the first process found under Agricultural\Food\Packaging. A Ciqual product sits several stages downstream from the food and its packaging, and products cooked at consumer level can also lead to the packaging carried by their frying oil.
A first-match traversal would associate 78 products with the wrong branch. Pan-fried beef, for example, can inherit a one-litre sunflower oil bottle and the oil’s own ingredients. The rows remain internally consistent, which makes the problem easy to miss.
A public script now applies explicit selection and classification rules to extract two tables from Agribalyse 3.2:
- the edible ingredients of each food;
- its packaging systems, expressed per functional unit.
The tested extraction covers all 2,451 products in the Ciqual table. The method below explains which level of the graph to read, how to identify the product’s own packaging stage and which shortcuts to avoid.
The product is not the recipe
A Ciqual product is the process at the consumer end of a lifecycle chain. The food recipe and its packaging sit several steps upstream:
Aioli | at consumer [Ciqual code: 11168]└─ Aioli | at retail └─ Aioli | at distribution └─ Aioli | at packaging ├─ Mayonnaise, 425 g | Packaging System └─ Aioli sauce, recipe, at plantReading the direct inputs of the consumer process gives preparation, retail losses and logistics. It does not give a bill of ingredients. The extraction first finds the product’s packaging stage, then reads the food consumed by that stage. Both output sheets describe that same food while retaining the Ciqual product identifier.

The executed extraction returns the edible inputs of the aioli recipe and 2.35 units of its 425 g packaging system per kilogram of product. The two sheets join on the Ciqual product process ID.
The quantity of packaging stays relative to the packed food. For the aioli, the stage consumes one packaging system for 0.425 kg of food, which gives 1 / 0.425 = 2.35 systems per kilogram. Folding retail and consumer losses into that number would produce 2.61 instead, but those losses belong to later lifecycle stages.
What counts as an ingredient
A technosphere input is not necessarily an ingredient. Electricity, cleaning chemicals, transport and waste treatment are inputs too.
Agribalyse recipes use three properties that can be combined into a practical boundary. The script keeps an input when:
- its producing activity has
Category type = material; - its exchange role is
raw_material,otherorwater; - its unit is a food unit rather than
m3, which removes the remaining natural-gas and compressed-air inputs.
These rules work on the recipe, transformation or consumption mix found at the bottom of the product chain. Applying them indiscriminately to factory processes would be wrong. On an ecoinvent-derived yogurt production process, for example, the same filter retains the cleaning station alongside the milk.
The full Ciqual run produces 7,405 ingredient rows for 2,036 products. The other 415 products lead to a transformation or consumption mix with no edible input of its own. An apple has no recipe to extract, and the output should not pretend otherwise.
Packaging is a process, not a material list
Agribalyse models packaging one stage downstream from the recipe. The stage consumes the packed food and a packaging-system process. That system is kept as one row: an impact engine can resolve the materials and operations below it when needed.
The difficult part is telling the stage from the system. Both are stored under Agricultural\Food\Packaging. PACK_AGB separates them through the category path: systems and their components sit under a segment beginning with a dot, such as .Packaging systems, while food stages do not.
That distinction was checked across the database. Agribalyse 3.2 contains 1,558 processes in dotted packaging branches, and none consumes a food. The rule is therefore grounded in the database’s own structure rather than in a name heuristic.
The completed Ciqual extraction finds a packaging stage for every product: 2,294 have a system and 157 are packed in nothing. Across the database, 2,286 packaging stages resolve to 1,540 distinct product-system pairs.
Checks that prevent plausible but incorrect rows
Do not take the first packaging stage found
Products cooked at consumer level consume both a food and a cooking input. Each branch can contain a packaging stage. A depth-first walk that stops at the first match may reach the sunflower oil branch before the beef branch, so the beef inherits the oil’s bottle and recipe.
Rank the filtered supply-chain entries by depth instead. The product’s own packaging stage is the shallowest non-system entry; packaging carried by an ingredient can only appear deeper. On Agribalyse 3.2, this distinction affects 78 products.
Do not treat everything under Packaging as packaging
A food at packaging stage can itself be used as the proxy food of another packaging stage. If every process under the Packaging branch is classified as a packaging system, that proxy disappears from the food side of the bill. Eight products would then lose their packaging.
The reverse shortcut is equally unsafe: if a packaging system is read as a stage, it appears to be packed in itself. Sweeping every process without the dotted-path distinction can produce 236 invented rows.
Name the co-product, not only the activity
An activity can produce several products. Using the typed target_process_id alone identifies the target activity but can resolve to an arbitrary co-product. A biscuit input named Palm oil, crude, consumption mix, for example, can receive the process ID of palm-kernel oil.
Across the food branch, relying on an activity-level target would leave 2,321 of 19,174 resolvable targets attached to the wrong co-product. Another 628 rows would point back to their own product, which can make recursive traversal loop.
The raw exchange contains the unambiguous pair: activityLinkId for the producing activity and flowId for the product flow. Their join is the process identifier written to ingredient_process_id. This distinction affects the exported identifier rather than the engine’s calculation.
Ciqual products and recipes are two different scopes
The default output has one row subject per Ciqual product. This is the useful scope when each product needs its own Ciqual code and packaging format.
A second scope extracts the 763 composite-food recipes directly. Neither scope contains the other. Seventeen recipes are reached by no Ciqual product, thirteen of them with ingredients, including rice noodles, reconstituted broths, yogurt variants, snail in parsley butter, anchovy fillets and grated carrots.
Keeping both scopes avoids turning a convenient default into a false claim of completeness.
Reproducing the extraction
The script and tests are published in the MTES-MCT Ecobalyse method-tooling repository. The script uses PEP 723 dependencies and runs with uv. It downloads and starts a pinned VoLCA engine through pyvolca; the Agribalyse export itself is supplied by the user.
uv run extract_agribalyse_recipes.py \ --agribalyse "/path/to/AGB32_final.CSV.zip" \ --out agribalyse_ciqual.xlsxA dry run can be limited to the first 20 products:
uv run extract_agribalyse_recipes.py --limit 20 --out sample.xlsxThe workbook always contains two sheets, ingredients and packaging, joined by product_process_id. The local self-check covers the stage selection, packaging division, proxy foods, co-product identifiers and functional-unit scaling:
uv run test_extract.pyInterpretation boundaries
The extraction depends on Agribalyse 3.2 modelling conventions, especially its classifications and PACK_AGB category paths. Those checks should be rerun for another database version.
A packaging row identifies the system used for a product format. It does not turn that inventory into a generic packaging option, and it should not be reused to compare formats outside the scope for which PACK_AGB authored it. Names containing Pack proxy identify stand-ins rather than product-specific measurements.
The output is therefore a traceable reading of Agribalyse, not a reconstruction of recipes from arbitrary LCA databases. Its main safeguard is that missing stages, empty packaging and multiple variants remain visible instead of being silently filled in.
Data and software
- Database: Agribalyse 3.2, complete SimaPro CSV export supplied separately.
- Packaging model: PACK_AGB as included in Agribalyse 3.2.
- Engine: VoLCA 0.9.3.
- Python client: pyvolca 0.9.0 or later.
- Public implementation: Agribalyse recipe extraction.