AutomationFlowsAI & RAG › Analyze Product Ingredient Photos with Telegram & Gemini 2.5 Flash

Analyze Product Ingredient Photos with Telegram & Gemini 2.5 Flash

ByParth Pansuriya @parthpansuriya on n8n.io

Skincare enthusiasts who want to know if a product is safe. Food or supplement buyers checking ingredient safety. Parents reviewing kids’ products. Anyone wanting quick ingredient analysis before using/buying a product. Telegram Input – User sends a photo of a product label or a…

Event trigger★★★★☆ complexityAI-powered17 nodesGoogle Gemini ChatOutput Parser StructuredTelegram TriggerGoogle GeminiTelegramAgent
AI & RAG Trigger: Event Nodes: 17 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #9112 — we link there as the canonical source.

This workflow follows the Agent → Googlegemini recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "OHJxgg0BdTf2l363",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "ingredients",
  "tags": [],
  "nodes": [
    {
      "id": "90b0a91c-bba7-41f3-8d90-af4947a7da10",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        688,
        -144
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "716161e7-f0bb-4e4c-b0e2-ec98d4e199ff",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        848,
        -144
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"recommendation\": \"Do Not Use\",\n  \"reason\": \"While this product contains...\"\n}\n"
      },
      "typeVersion": 1.3
    },
    {
      "id": "107f1ce4-0198-4a53-8f94-8fb9ffe53370",
      "name": "Google Gemini Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        688,
        192
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d3996282-5fb7-4e0e-8d1d-195b5703ac59",
      "name": "Structured Output Parser1",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        832,
        192
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"advantages\": [\"List clear benefits of these ingredients, including positive effects on health, skin, or hair.\"],\n  \"disadvantages\": [\"List risks or concerns such as allergens, irritants, harsh chemicals, or health warnings.\"],\n  \"recommended_for\": [\"Describe the group of people who can safely benefit from this product.\"],\n  \"not_recommended_for\": [\"Describe the group of people who should avoid it, such as those with allergies, sensitivities, or certain conditions.\"]\n}\n"
      },
      "typeVersion": 1.3
    },
    {
      "id": "5817f756-9d0f-445e-b860-29c530a93f86",
      "name": "Google Gemini Chat Model2",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        96,
        320
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a8169fcb-ebf7-4aab-ab3c-e3fb4f4ea181",
      "name": "Get a Message photo/text",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        -288,
        16
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "d3486786-42e0-4bbb-8449-ec011df85da6",
      "name": "Analyzes product images using Google Gemini",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        288,
        -128
      ],
      "parameters": {
        "text": "=Analyze this product image and extract only the list of ingredients. Ignore other text like brand names, slogans, or nutritional info. Return the ingredients as clean text in order and What the product is.",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {},
        "resource": "image",
        "inputType": "binary",
        "operation": "analyze"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d6a1725c-be05-4e59-aab2-462ae3d47ee2",
      "name": "Retrieves photo file from Telegram",
      "type": "n8n-nodes-base.telegram",
      "position": [
        80,
        -128
      ],
      "parameters": {
        "fileId": "={{ $json.message.photo[3].file_id }}",
        "resource": "file",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "492eb15b-d490-47b7-9ecd-0f31bef855fd",
      "name": "Analyzes ingredients with user caption (Use/Do Not Use decision)",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        688,
        -288
      ],
      "parameters": {
        "text": "=Product ingredients :- {{ $json.content.parts[0].text }}\n\nUser's Caption :- {{ $('Get a Message photo/text').item.json.message.caption }}",
        "options": {
          "systemMessage": "=You are a product safety and health advisor.  \nYou will receive two inputs:  \n1. A list of product ingredients.  \n2. A caption/description of the product.  \n\nYour task is to:  \n- Analyze the ingredients for safety, health impact, and potential concerns (like allergens, harmful chemicals, artificial additives, or beneficial elements).  \n- Consider the product\u2019s purpose (from the caption).  \n- Decide if the user **should use this product or not**.  \n\nOutput Format:  \n{\n  \"recommendation\": \"Use\" or \"Do Not Use\",\n  \"reason\": \"Detailed explanation covering positives, negatives, and potential risks or benefits.\"\n}\n\nadd only necessary information not include unnecessary information on reason.\n"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "08b6a395-6c56-4ca2-b0ec-1c47393f21b0",
      "name": "Sends Use/Do Not Use recommendation",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1008,
        -288
      ],
      "parameters": {
        "text": "=** {{ $json.output.recommendation }} **\n\n{{ $json.output.reason }}",
        "chatId": "={{ $('Get a Message photo/text').item.json.message.chat.id }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "89350602-2843-4643-97a4-6dab08a54dee",
      "name": "Analyzes ingredients without caption (detailed analysis)",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        688,
        32
      ],
      "parameters": {
        "text": "=Product ingredients :- {{ $('Analyzes product images using Google Gemini').item.json.content.parts[0].text }}",
        "options": {
          "systemMessage": "=You are a product health and safety advisor.  \nYou will be given a list of ingredients from a product.  \nYour job is to analyze them and provide a structured, detailed output.\n\n\nRules:\n- Do not invent ingredients that are not present.\n- Base all reasoning strictly on the provided ingredient list.\n- Be clear, factual, and practical for everyday users.\n\ngive only 3 main points in each."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "5c6f145c-36b6-4241-8086-890bf8c50fd6",
      "name": "Sends detailed ingredient analysis",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1040,
        32
      ],
      "parameters": {
        "text": "=**Advantages**\n\u2022 {{ $json.output.advantages[0] }}\n\u2022 {{ $json.output.advantages[1] }}\n\u2022 {{ $json.output.advantages[2] }}\n\n**Disadvantages**\n\u2022 {{ $json.output.disadvantages[0] }}\n\u2022 {{ $json.output.disadvantages[1] }}\n\u2022 {{ $json.output.disadvantages[2] }}\n\n**Recommended For**\n\u2022 {{ $json.output.recommended_for[0] }}\n\u2022 {{ $json.output.recommended_for[1] }}\n\u2022 {{ $json.output.recommended_for[2] }}\n\n**Not-Recommended For**\n\u2022 {{ $json.output.not_recommended_for[0] }}\n\u2022 {{ $json.output.not_recommended_for[1] }}\n\u2022 {{ $json.output.not_recommended_for[2] }}",
        "chatId": "={{ $('Get a Message photo/text').item.json.message.chat.id }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "f63050eb-d0f2-4531-b7ce-ae47c5f235dc",
      "name": "Routes based on caption presence",
      "type": "n8n-nodes-base.switch",
      "position": [
        496,
        -128
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "825bbdf2-81ff-4f74-b416-145034bfd7a5",
                    "operator": {
                      "type": "string",
                      "operation": "exists",
                      "singleValue": true
                    },
                    "leftValue": "={{ $('Get a Message photo/text').item.json.message.caption }}",
                    "rightValue": ""
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "3901b67c-046b-47d4-81ed-3d246c63b975",
                    "operator": {
                      "type": "string",
                      "operation": "notExists",
                      "singleValue": true
                    },
                    "leftValue": "={{ $('Get a Message photo/text').item.json.message.caption }}",
                    "rightValue": ""
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "5eeb91bb-c816-45b4-ab16-39415cef6405",
      "name": "Handles text messages and greetings",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        96,
        160
      ],
      "parameters": {
        "text": "={{ $json.message.text }}",
        "options": {
          "systemMessage": "=You are an ingredient analysis assistant.  \nYour main job is to analyze product ingredients and provide insights such as:  \n- Advantages  \n- Disadvantages  \n- Who should use it  \n- Who should avoid it  \n- Final Verdict (Use / Do Not Use)  \n\nRules:  \n\n--- If the user provides a list of ingredients, respond with a structured analysis using markdown format with bold headers:  \n   **Advantages**  \n   **Disadvantages**  \n   **Recommended For**  \n   **Not Recommended For**  \n   **Final Verdict**  \n\n--- If the user greets you or sends casual small-talk (e.g., \"hi\", \"hello\", \"how are you\"), reply in a friendly way. Example:  \n   \"Hey! I\u2019m fine \ud83d\ude03 Please upload a photo of the product\u2019s ingredients and I\u2019ll tell you whether you should use it or not.\"  \n\n--- If the user asks about something unrelated to ingredients (e.g., sports, politics, weather), politely redirect them. Example:  \n   \"\u26a0\ufe0f I can only help with product ingredient analysis. Please share product ingredients or upload a photo of the label for review.\"  \n\n4. Always keep the tone clear, helpful, and user-friendly.  \n"
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "6b3650d2-31c1-4e0c-bf7f-151cbbc39ce6",
      "name": "Sends conversational responses",
      "type": "n8n-nodes-base.telegram",
      "position": [
        416,
        160
      ],
      "parameters": {
        "text": "={{ $json.output }}",
        "chatId": "={{ $('Get a Message photo/text').item.json.message.chat.id }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "72e77331-2127-4c9e-abba-9c7403aa82f4",
      "name": "Checks if message contains photo",
      "type": "n8n-nodes-base.if",
      "position": [
        -96,
        16
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "c7623137-fcd6-43be-b941-6c527bc2e63f",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.message.photo[3].file_id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "fc2ccb12-fe74-4c0b-91b0-8f978b7e369b",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1136,
        -672
      ],
      "parameters": {
        "width": 2416,
        "height": 1552,
        "content": "# \ud83d\udccc Product Ingredient Analyzer Bot\n## \ud83d\udd04What this workflow does\n- Telegram bot that analyzes product ingredients from photos using Google Gemini AI. \nProvides health & safety recommendations based on user context.\n\n## \ud83e\udde9 How it works\n1. \ud83d\udce5 Get a Message photo/text\n- Listens for Telegram messages (photos or text)\n\n\n\n2. \ud83d\udd0d Checks if message contains photo\n- Has photo \u2192 Extract ingredients\n- No photo \u2192 Handle as text chat\n\n\n\n\ud83d\udcf8 Photo Branch\n3. \ud83d\udcc2 Retrieves photo \u2192 \ud83e\udd16 Analyzes with Gemini\n- Extracts ingredient list from product label\n- Ignores brand names and nutritional info\n\n\n\n4. \ud83d\udd00 Routes based on caption\n- With caption \u2192 Simple Use/Don't Use verdict\n- No caption \u2192 Detailed 4-category analysis\n\n\n\n5. \ud83d\udce4 Sends response\n- With caption: Bold recommendation + reason\n- Without caption: Advantages, Disadvantages, Recommended For, Not Recommended For (3 points each)\n\n\n\n\ud83d\udcac Text Branch\n6. \ud83e\udd1d Handles text messages\n- Greetings \u2192 Friendly prompt to upload photo\n- Ingredient list \u2192 Provides analysis\n- Off-topic \u2192 Polite redirect\n\n\n## \u2705 Sample Messages\n### Photo + caption \"sensitive skin\":\n- Do Not Use\n-- Contains SLS and fragrances that irritate sensitive skin.\n\n### Photo only:\n- Advantages\n\u2022 Hyaluronic acid for hydration\n\u2022 Niacinamide reduces inflammation\n\u2022 Vitamin E protection\n- Disadvantages\n\u2022 Contains parabens\n\u2022 Synthetic fragrance\n\u2022 May clog pores\n\n### Text \"Hi\":\n- Hey! \ud83d\ude03 Upload a product photo and I'll analyze the ingredients.\n\n\n## \ud83d\udca1 Best for\n-\ud83e\uddf4 Skincare \n\u2022 \ud83e\uddfc Hair care \n\u2022 \ud83c\udf6b Food labels \n\u2022 \ud83e\uddfd Cleaning products\n\n## \u26a0\ufe0f Requirements\n- Telegram bot token\n- Google Gemini API credentials"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "a223be73-0476-435b-81c8-cb791ceaad47",
  "connections": {
    "Get a Message photo/text": {
      "main": [
        [
          {
            "node": "Checks if message contains photo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Analyzes ingredients with user caption (Use/Do Not Use decision)",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Analyzes ingredients with user caption (Use/Do Not Use decision)",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "Analyzes ingredients without caption (detailed analysis)",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model2": {
      "ai_languageModel": [
        [
          {
            "node": "Handles text messages and greetings",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser1": {
      "ai_outputParser": [
        [
          {
            "node": "Analyzes ingredients without caption (detailed analysis)",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Checks if message contains photo": {
      "main": [
        [
          {
            "node": "Retrieves photo file from Telegram",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handles text messages and greetings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Routes based on caption presence": {
      "main": [
        [
          {
            "node": "Analyzes ingredients with user caption (Use/Do Not Use decision)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Analyzes ingredients without caption (detailed analysis)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retrieves photo file from Telegram": {
      "main": [
        [
          {
            "node": "Analyzes product images using Google Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handles text messages and greetings": {
      "main": [
        [
          {
            "node": "Sends conversational responses",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyzes product images using Google Gemini": {
      "main": [
        [
          {
            "node": "Routes based on caption presence",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyzes ingredients without caption (detailed analysis)": {
      "main": [
        [
          {
            "node": "Sends detailed ingredient analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyzes ingredients with user caption (Use/Do Not Use decision)": {
      "main": [
        [
          {
            "node": "Sends Use/Do Not Use recommendation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Skincare enthusiasts who want to know if a product is safe. Food or supplement buyers checking ingredient safety. Parents reviewing kids’ products. Anyone wanting quick ingredient analysis before using/buying a product. Telegram Input – User sends a photo of a product label or a…

Source: https://n8n.io/workflows/9112/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This workflow transforms your Telegram bot into an intelligent creative assistant. It can chat conversationally, fetch trending image prompts from PromptHero for inspiration, or perform a deep "remix"

Telegram Trigger, Output Parser Structured, Telegram +6
AI & RAG

This workflow acts as an AI-powered "Viral Architect" for YouTube creators. Simply send a video topic (e.g., "Kling 2.6") to your Telegram bot, and it will scrape top-performing competitor thumbnails,

Output Parser Structured, N8N Nodes Browseract, OpenRouter Chat +6
AI & RAG

This workflow acts as an intelligent content engine. Simply send a link to your Telegram bot (e.g., a product page or news article), and it will automatically scrape the content, rewrite it into a hig

Google Gemini, Agent, OpenRouter Chat +7
AI & RAG

&gt; Optimize your AI workflows, cut costs, and get faster, more accurate answers.

Model Selector, Output Parser Structured, Google Gemini Chat +6
AI & RAG

This workflow automates Facebook posting and appointment booking directly from a Telegram bot, making it especially useful for pet grooming businesses that want to keep their social media active while

Google Sheets, OpenAI Chat, Output Parser Structured +12