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:

FieldTypeDescription
product_typeone of food, beverage, cosmetic, supplementWhat 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

FieldDescription
summaryOne line, e.g. "Rolled oats is the better choice: Nutri-Score A against E".
winnerproduct_a, product_b or tie.
reasons[]The 2 to 4 differences that decided it. Empty on a tie.
comparisonnutri_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).
allergensEU 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_bThe 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": []
  }
}