Compare two products
POST /v1/label/compare · $0.02 a call
Send label photos of two products: before is product A, after is product B. Each is read and scored exactly like POST /v1/label, then compared with fixed rules: the Nutri-Score grade decides first, then the NOVA processing group, then clear differences per 100 g in sugars, saturated fat, salt, fiber and protein, and the number of additives. Allergens are listed for both. A note is added when the products are of different kinds.
For product scanners, grocery and diet apps.
Request
Send two photos, before and after, as multipart files, or as before_url / after_url or before_base64 / after_base64. These fields go alongside them:
| Field | Type | Description |
|---|---|---|
product_type | one of food, beverage, cosmetic, supplement | What both products are, when you already know it. |
Photo tips. Two photos, one label each: the back of each pack, flat and in focus, with the nutrition table and ingredient list in frame.
curl https://truelens.keronlabs.com/v1/label/compare \
-H "Authorization: Bearer $TRUELENS_KEY" \
-F before=@before-label.jpg \
-F after=@after-label.jpg \
-F product_type="food"
Response
| Field | Description |
|---|---|
summary | One line, e.g. "Rolled oats is the better choice: Nutri-Score A against E". |
winner | product_a, product_b or tie. |
reasons[] | The 2 to 4 differences that decided it. Empty on a tie. |
comparison | nutri_score, nova, additives, sugars_g, saturated_fat_g, salt_g, fiber_g, protein_g: each with a, b and better (product_a, product_b, same, or null when a value is missing). |
allergens | EU allergens both contain, and those only in product A or only in product B. |
notes[] | Why the comparison may be less fair, e.g. different kinds of product or different Nutri-Score scales. |
product_a, product_b | The full POST /v1/label result for each photo. |
Example
Output of this API’s own code on a sample photo. Values will differ for your photos.
{
"metadata": {
"id": "req_9cf4da08fe7f40dab71a",
"engine": "label/compare",
"status": "success",
"cached": false,
"credits_used": 2,
"created_at": "2026-10-19T09:30:00.000Z",
"processing_ms": 3400
},
"summary": "Rolled oats is the better choice: Nutri-Score A against E",
"winner": "product_b",
"reasons": [
"Nutri-Score A against E.",
"Less processed: NOVA 1 against 4.",
"Less sugars: 0.7 g against 56.3 g per 100 g.",
"Less saturated fat: 1.3 g against 10.6 g per 100 g."
],
"comparison": {
"nutri_score": {
"a": "E",
"b": "A",
"better": "product_b"
},
"nova": {
"a": 4,
"b": 1,
"better": "product_b"
},
"additives": {
"a": 1,
"b": 0,
"better": "product_b"
},
"sugars_g": {
"a": 56.3,
"b": 0.7,
"better": "product_b"
},
"saturated_fat_g": {
"a": 10.6,
"b": 1.3,
"better": "product_b"
},
"salt_g": {
"a": 0.11,
"b": 0,
"better": "same"
},
"fiber_g": {
"a": null,
"b": 10,
"better": null
},
"protein_g": {
"a": 6.3,
"b": 14,
"better": "product_b"
}
},
"allergens": {
"both": [],
"only_a": [
"soybeans",
"milk",
"nuts"
],
"only_b": [
"gluten"
]
},
"notes": [],
"product_a": {
"summary": "Nutri-Score E, NOVA 4, 1 additive",
"product": {
"type": "food",
"name": "Chocolate hazelnut spread",
"brand": null,
"language": "en"
},
"legibility": "clear",
"nutrition": {
"basis_printed": "per_100g",
"serving_size": 15,
"unit": "g",
"per_100": {
"energy_kj": 2252,
"energy_kcal": 539,
"fat_g": 30.9,
"saturated_fat_g": 10.6,
"carbohydrates_g": 57.5,
"sugars_g": 56.3,
"fiber_g": null,
"protein_g": 6.3,
"salt_g": 0.11
},
"checks": []
},
"nutri_score": {
"grade": "E",
"score": 31,
"category": "general",
"negative_points": 31,
"positive_points": 0,
"components": {
"negative": [
{
"id": "energy",
"value": 2252,
"points": 6,
"points_max": 10
},
{
"id": "sugars",
"value": 56.3,
"points": 15,
"points_max": 15
},
{
"id": "saturated_fat",
"value": 10.6,
"points": 10,
"points_max": 10
},
{
"id": "salt",
"value": 0.11,
"points": 0,
"points_max": 20
}
],
"positive": [
{
"id": "fiber",
"value": null,
"points": 0,
"points_max": 5
},
{
"id": "fruits_vegetables_legumes",
"value": 0,
"points": 0,
"points_max": 5
}
]
},
"proteins_counted": false,
"algorithm": "2023",
"notes": [
"Fiber is not printed and counts as 0."
]
},
"nova": {
"group": 4,
"markers": [
{
"ingredient": "emulsifier: lecithins (soya)",
"marker": "Emulsifier",
"group": 4
},
{
"ingredient": "E322 Lecithin‚ hydroxylated",
"marker": "lecithin‚ hydroxylated",
"group": 4
},
{
"ingredient": "Sugar",
"marker": "sugar",
"group": 3
},
{
"ingredient": "skimmed milk powder",
"marker": "milk powder",
"group": 3
}
],
"basis": "Contains ingredients or additives typical of ultra-processed foods."
},
"additives": [
{
"e_number": "E322",
"name": "Lecithin‚ hydroxylated",
"classes": [],
"efsa_overexposure_risk": null,
"note": null
}
],
"allergens": {
"contains": [
"soybeans",
"milk",
"nuts"
],
"may_contain": []
},
"ingredients": [
{
"name": "Sugar",
"percent": null,
"e_number": null
},
{
"name": "palm oil",
"percent": null,
"e_number": null
},
{
"name": "hazelnuts",
"percent": 13,
"e_number": null
},
{
"name": "skimmed milk powder",
"percent": 8.7,
"e_number": null
},
{
"name": "fat-reduced cocoa",
"percent": 7.4,
"e_number": null
},
{
"name": "emulsifier: lecithins (soya)",
"percent": null,
"e_number": "E322"
},
{
"name": "vanillin",
"percent": null,
"e_number": null
}
],
"ingredients_text": "Sugar, palm oil, hazelnuts 13%, skimmed milk powder 8.7%, fat-reduced cocoa 7.4%, emulsifier: lecithins (soya), vanillin.",
"cosmetic": null,
"warnings": []
},
"product_b": {
"summary": "Nutri-Score A, NOVA 1, 0 additives",
"product": {
"type": "food",
"name": "Rolled oats",
"brand": null,
"language": "en"
},
"legibility": "clear",
"nutrition": {
"basis_printed": "per_100g",
"serving_size": 40,
"unit": "g",
"per_100": {
"energy_kj": 1566,
"energy_kcal": 374,
"fat_g": 7,
"saturated_fat_g": 1.3,
"carbohydrates_g": 59,
"sugars_g": 0.7,
"fiber_g": 10,
"protein_g": 14,
"salt_g": 0
},
"checks": []
},
"nutri_score": {
"grade": "A",
"score": -5,
"category": "general",
"negative_points": 5,
"positive_points": 10,
"components": {
"negative": [
{
"id": "energy",
"value": 1566,
"points": 4,
"points_max": 10
},
{
"id": "sugars",
"value": 0.7,
"points": 0,
"points_max": 15
},
{
"id": "saturated_fat",
"value": 1.3,
"points": 1,
"points_max": 10
},
{
"id": "salt",
"value": 0,
"points": 0,
"points_max": 20
}
],
"positive": [
{
"id": "proteins",
"value": 14,
"points": 5,
"points_max": 7
},
{
"id": "fiber",
"value": 10,
"points": 5,
"points_max": 5
},
{
"id": "fruits_vegetables_legumes",
"value": 0,
"points": 0,
"points_max": 5
}
]
},
"proteins_counted": true,
"algorithm": "2023",
"notes": []
},
"nova": {
"group": 1,
"markers": [],
"basis": "No processing markers found in the ingredients."
},
"additives": [],
"allergens": {
"contains": [
"gluten"
],
"may_contain": [
"milk"
]
},
"ingredients": [
{
"name": "Whole grain oat flakes",
"percent": 100,
"e_number": null
}
],
"ingredients_text": "Whole grain oat flakes. May contain traces of milk.",
"cosmetic": null,
"warnings": []
}
}