When to use this skill
When the user asks to find food products matching criteria — "show me orange juices with a good Nutri-Score", "find vegan snack bars", "what cereals are NOVA group 1" — reach for the Open Food Facts search endpoint. It filters by category, nutrition grade (A through E), brand, dietary label, and more across a 3-million-product crowdsourced database. The nutrient_levels field classifies fat, salt, sugar, and saturated fat as "low", "moderate", or "high" so you can answer dietary questions without interpreting raw milligram counts. For looking up a single known product by barcode, use look-up-food-product-by-barcode instead.
Your best first call
curl "https://world.openfoodfacts.org/api/v2/search?categories=Orange+Juice&nutrition_grades=a&fields=code,product_name,brands,nutriscore_grade,nova_group,nutrient_levels&page_size=5"
No auth. No key. The ?fields= parameter is not optional — each product carries 200+ fields and an untrimmed search returns megabytes per page. Always request exactly the fields you need. Use page_size to control results per page; page for pagination.
The response is a JSON object with a products array:
count — total matching products across all pages
page, page_size, page_count — pagination state
products[] — array containing only the fields you listed in ?fields=. Key fields: code (barcode), product_name, brands, nutriscore_grade (A is best, E is worst), nova_group (1 is unprocessed, 4 is ultra-processed), nutrient_levels (fat/salt/sugars/saturated-fat as low/moderate/high)
Fallbacks (when the best call isn't enough)
- Single product by barcode →
/api/v2/product/{barcode} returns the full record for one known product — ingredients, allergens, nutrition per 100 g, the works. Use when the user has a barcode, not a category query.
Pitfalls
- Search queries allow only 10 req/min — a tenth of the product-read limit. Facet queries (categories, brands, labels) are even tighter at 2 req/min. A browse-heavy workflow hits the facet limit fast.
- Omit
?fields= and each product dumps 200+ fields. A page_size=24 search without field trimming returns megabytes. This is the single biggest performance lever.
status: 0 means "product not found", not an HTTP error. The API returns HTTP 200 with status: 0 and status_verbose: "product not found". Check the status field in the response body, not the HTTP status code.
One-line summary for the user
I can search for food products by category, nutrition grade, brand, or dietary label across the Open Food Facts database — but always include ?fields= to trim the response or you'll get megabytes per page.
SKILL.md source (frontmatter + body)
---
name: search-food-products
description: When the user asks to find food products matching criteria — category, nutrition grade, Nutri-Score, NOVA group, brand, dietary label — reach for Open Food Facts search. Unauthenticated, 3M+ product database.
---
## When to use this skill
When the user asks to find food products matching criteria — "show me orange juices with a good Nutri-Score", "find vegan snack bars", "what cereals are NOVA group 1" — reach for the Open Food Facts search endpoint. It filters by category, nutrition grade (A through E), brand, dietary label, and more across a 3-million-product crowdsourced database. The `nutrient_levels` field classifies fat, salt, sugar, and saturated fat as "low", "moderate", or "high" so you can answer dietary questions without interpreting raw milligram counts. For looking up a single known product by barcode, use `look-up-food-product-by-barcode` instead.
## Your best first call
```bash
curl "https://world.openfoodfacts.org/api/v2/search?categories=Orange+Juice&nutrition_grades=a&fields=code,product_name,brands,nutriscore_grade,nova_group,nutrient_levels&page_size=5"
```
No auth. No key. The `?fields=` parameter is not optional — each product carries 200+ fields and an untrimmed search returns megabytes per page. Always request exactly the fields you need. Use `page_size` to control results per page; `page` for pagination.
The response is a JSON object with a `products` array:
- `count` — total matching products across all pages
- `page`, `page_size`, `page_count` — pagination state
- `products[]` — array containing only the fields you listed in `?fields=`. Key fields: `code` (barcode), `product_name`, `brands`, `nutriscore_grade` (A is best, E is worst), `nova_group` (1 is unprocessed, 4 is ultra-processed), `nutrient_levels` (fat/salt/sugars/saturated-fat as low/moderate/high)
## Fallbacks (when the best call isn't enough)
- **Single product by barcode** → `/api/v2/product/{barcode}` returns the full record for one known product — ingredients, allergens, nutrition per 100 g, the works. Use when the user has a barcode, not a category query.
## Pitfalls
- **Search queries allow only 10 req/min** — a tenth of the product-read limit. Facet queries (categories, brands, labels) are even tighter at 2 req/min. A browse-heavy workflow hits the facet limit fast.
- **Omit `?fields=` and each product dumps 200+ fields.** A `page_size=24` search without field trimming returns megabytes. This is the single biggest performance lever.
- **`status: 0` means "product not found", not an HTTP error.** The API returns HTTP 200 with `status: 0` and `status_verbose: "product not found"`. Check the `status` field in the response body, not the HTTP status code.
## One-line summary for the user
I can search for food products by category, nutrition grade, brand, or dietary label across the Open Food Facts database — but always include `?fields=` to trim the response or you'll get megabytes per page.