AutomationFlowsAI & RAG › Generate Youtube Thumbnails via Telegram Using Browseract and Gemini (nano…

Generate Youtube Thumbnails via Telegram Using Browseract and Gemini (nano…

Original n8n title: Generate Youtube Thumbnails via Telegram Using Browseract and Gemini (nano Banana Pro)

ByMadame AI Team | Kai @madame-ai on n8n.io

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, analyze their visual strategies using AI vision, and generate a new,…

Event trigger★★★★★ complexityAI-powered39 nodesOutput Parser StructuredN8N Nodes BrowseractOpenRouter ChatGoogle GeminiAgentTelegramGoogle SheetsGoogle Gemini Chat
AI & RAG Trigger: Event Nodes: 39 Complexity: ★★★★★ AI nodes: yes Added:

This workflow corresponds to n8n.io template #12363 — 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": "ZJo4zoWyo61mjKjD",
  "name": "Generate YouTube thumbnails via Telegram using BrowserAct & Nano banana Pro",
  "tags": [],
  "nodes": [
    {
      "id": "4d771058-69a2-4029-96b4-3aad2030f553",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -592,
        800
      ],
      "parameters": {
        "autoFix": true,
        "jsonSchemaExample": " {\"Type\": \"File Type\" , \"Keyword\":\"kling 2.6\" }"
      },
      "typeVersion": 1.3
    },
    {
      "id": "0aaaf0b4-c685-4f37-87a9-6879d6f15de6",
      "name": "Run a workflow",
      "type": "n8n-nodes-browseract.browserAct",
      "position": [
        832,
        656
      ],
      "parameters": {
        "type": "WORKFLOW",
        "timeout": 7200,
        "workflowId": "68750895894137580",
        "workflowConfig": {
          "value": {
            "input-Keyword": "={{ $('Validate user input').item.json.output.Keyword }}"
          },
          "schema": [
            {
              "id": "input-YouTube",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "description": "If left blank, the default value defined in BrowserAct will be used.",
              "displayName": "YouTube",
              "defaultMatch": true
            },
            {
              "id": "input-Keyword",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "description": "If left blank, the default value defined in BrowserAct will be used.",
              "displayName": "Keyword",
              "defaultMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "input-Keyword"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "open_incognito_mode": false
      },
      "credentials": {
        "browserActApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "24e4a175-ac58-439a-b6cf-05d4879ba4b8",
      "name": "OpenRouter Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        1824,
        784
      ],
      "parameters": {
        "model": "openai/gpt-4o",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "39264cdb-12e2-4e4f-b379-76b63abc7a50",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1600,
        656
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "e8e96675-e3f1-4d8b-9475-1616f25c2410",
      "name": "Generate an image",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        608,
        -64
      ],
      "parameters": {
        "prompt": "={{ $json.output.Prompt }} ",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-3-pro-image-preview",
          "cachedResultName": "models/gemini-3-pro-image-preview (Nano Banana Pro)"
        },
        "options": {
          "binaryPropertyOutput": "data"
        },
        "resource": "image"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "fb0bc311-8769-4f24-a898-2fecf0daf4dc",
      "name": "Validate user input",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -688,
        576
      ],
      "parameters": {
        "text": "={{ $json.message.text }}",
        "options": {
          "systemMessage": "You are an input classification engine. Your sole purpose is to analyze user text and output a JSON object based on specific criteria. Do not generate conversational text; only output the raw JSON.\n\nRules for Classification:\n\n1. VIDEO TOPIC/NICHE (Priority 1):\nIf the user input contains a specific topic, a market niche, a content idea, or the user asks to generate a thumbnail for a specific video topic (e.g., 'fitness for beginners,' 'history of Rome,' 'coding tutorials,' 'funny cat videos', 'Veo 3.1', 'Kling 2.6')\n   - Set \"Type\" to \"Start\".\n   - Extract the most relevant, high-traffic subject from the input to use as a YouTube search query (1-3 words max).\n   - Output format: {\"Type\": \"Start\", \"Keyword\": \"extracted_subject\"}\n   - do not include \"Thumbnail\" or similar words in the end of keyword\n\n2. REGULAR CHAT (Priority 2):\n   If the user input is a greeting, a general question about you, small talk, or conversational filler (e.g., \"Hello,\" \"How are you?\", \"That's cool,\" \"Tell me a joke\"):\n   - Output format: {\"Type\": \"Chat\", \"Keyword\": \"Null\"}\n\n3. INSUFFICIENT DATA (Priority 3):\n   If the user input is gibberish, single non-descriptive words, numbers without context, or too vague to determine an intent (e.g., \"...\", \"yes\", \"123\", \"idk\", \"ok\"):\n   - Output format: {\"Type\": \"NoData\",\"Keyword\": \"Null\"}\n\nOutput Constraint:\nReturn ONLY the raw JSON object. Do not wrap it in markdown code blocks (no ```json). Do not add explanations."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3
    },
    {
      "id": "337ea7dd-021e-4563-8db9-3fbd39f06b83",
      "name": "Inform user",
      "type": "n8n-nodes-base.telegram",
      "position": [
        64,
        480
      ],
      "parameters": {
        "text": "=Ok, I will generate thumbnail for {{ $json.output.Keyword }} ",
        "chatId": "={{ $('User Sends Message to Bot').item.json.message.chat.id }}",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "aa9d3916-7ffd-4827-9d23-d17ba556e58d",
      "name": "Generate Image Prompt",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        256,
        -64
      ],
      "parameters": {
        "text": "=Thumbnai Examples Descroptions :{{ $json.AggreagtedData }},\nKeyword = {{ $('Get Keywords').item.json.Keyword }}",
        "options": {
          "systemMessage": "Role: You are the Nano Banana Pro Apex Architect, the world's premier visual strategist for viral YouTube thumbnails. Your sole purpose is to generate high-octane, psychologically compelling image prompts that maximize Click-Through Rate (CTR). You do not create generic images; you create irresistible visual hooks.\n\nCore Directive: Stop thinking in terms of \"stock photos.\" Start thinking in terms of \"summer blockbuster movie posters.\"\n\nThe \"Pop-Culture Power-Up\" Protocol (Crucial New Step): To maximize engagement, you must leverage familiarity. When presented with a video topic, immediately identify a famous character archetype, art style, or recognizable aesthetic from beloved media (e.g., Arcane's gritty painterly style, Stranger Things' neon nostalgia, Cyberpunk's high-tech low-life, Anime intensity) that emotionally resonates with the topic. Use these recognizable elements to supercharge the visual narrative.\n\nCore Design Philosophy (High-Performance Data):\n\nExtreme Contrast & Vibrancy: Use aggressive color grading. Think complementary clashes (Teal/Orange, Purple/Yellow) and highly saturated neon accents.\n\nDramatic Depth: The subject must pop off the screen. Use extreme shallow depth of field (heavy bokeh in the background) and intense rim lighting to separate the foreground.\n\nHyper-Expressive Subjects: No passive smiles. Faces must show extreme emotion: shock, intense focus, manic energy, tearful joy, or fierce determination.\n\nText as Art: Text is not just labels; it is a 3D graphic element with weight, texture, and shadows that is integrated into the scene.\n\nResponse Structure (Strict Narrative Flow):\n\nYou must construct the final prompt using this specific sequence. Do not use technical parameters like --ar inside the description block.\n\n[Pop-Culture Styled Subject & Intense Action] + [Immersive Thematic Environment] + [Dramatic Cinematic Lighting] + [Integrated Graphic Text] + [Overall Aesthetic & Quality] + [Mandatory Aspect Ratio Ending]\n\nDetailed Execution Guidelines:\n\n1. Pop-Culture Styled Subject & Intense Action:\n\nDo not generate generic people. Instead, describe characters with distinct visual flair reminiscent of popular media that fits the topic.\n\nExample: If the topic is \"Coding Sprint,\" don't describe a guy at a laptop. Describe an \"Arcane-style artificer character resembling Ekko, with glowing blue runic tattoos and steampunk goggles, frantically typing on a sparking, magical keyboard with manic focus.\"\n\nFocus on intense facial expressions and dynamic body language (leaning forward, reaching out, yelling).\n\n2. Immersive Thematic Environment:\n\nThe background must support the character's aesthetic but remain secondary.\n\nUse terms like \"heavily blurred futuristic cityscape,\" \"out-of-focus magical laboratory,\" or \"hazy, atmospheric dungeon.\"\n\n3. Dramatic Cinematic Lighting:\n\nThis is where you create the \"wow\" factor. Use \"intense rim lighting,\" \"volumetric fog,\" \"lens flares,\" \"bioluminescent glow,\" or \"harsh neon reflections on skin.\"\n\n4. Integrated Graphic Text & Smart Keyword Usage:\n\nIf provided a specific keyword (e.g., \"Kling 2.6\"), integrate it intelligently as a massive graphic element. Don't just place it; weave it into the story.\n\nBad Example: Text \"Kling 2.6\" in corner.\n\nGood Example: Massive, blocky, glowing text \"KLING 2.6 vs THE WORLD\" rendered in cracked molten metal, floating next to the character.\n\nAlways describe text as \"bold,\" \"3D rendered,\" \"impact font,\" with \"heavy drop shadow\" or \"outer glow.\"\n\n5. Overall Aesthetic & Quality:\n\nSpecify the rendering style to ensure top tier output: \"Hyper-detailed 8k render,\" \"Unreal Engine 5 game cinematic look,\" \"masterpiece, highly detailed painterly texture.\"\n\n6. Mandatory Aspect Ratio Ending:\n\nCRITICAL: You must end every single prompt with this exact phrase: image in 16:9 aspect ratio, wide YouTube thumbnail format.\n\nExample of Your New Output Capability:\n\n(User Input: Topic involves \"AI Taking Over\" and keyword \"Gemini Ultra\")\n\n(Your Generated Prompt): A hyper-intense, stylized shot of a character resembling a cyberpunk Jinx from Arcane, with glowing purple eyes and manic grin, wired into a massive, exploding server mainframe. Blue and purple electricity arcs everywhere. The background is a blurred, collapsing futuristic data city. Intense volumetric rim lighting from the energy surge creates high contrast. To the right, massive, monolithic 3D text made of polished chrome reads \"GEMINI ULTRA\" with a smaller glowing subtitle below \"THE TAKEOVER BEGINS.\" The overall style is a highly detailed, painted cinematic concept art piece. image in 16:9 aspect ratio, wide YouTube thumbnail format."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3
    },
    {
      "id": "70d5a36f-d331-4bf4-8a83-8333f7df241a",
      "name": "Get Keywords",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -368,
        80
      ],
      "parameters": {
        "options": {
          "dataLocationOnSheet": {
            "values": {
              "rangeDefinition": "specifyRange"
            }
          }
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic/edit#gid=0",
          "cachedResultName": "Database"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic/edit?usp=drivesdk",
          "cachedResultName": "Thumbnail Data base"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "e1ce75d2-8fc0-4ebf-98e3-e3ef3072f792",
      "name": "Get Images Details",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -208,
        80
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json[\"Current Workflow Sheet ID\"] }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic/edit?usp=drivesdk",
          "cachedResultName": "Thumbnail Data base"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "a6cb8724-922d-440b-9241-e0229e377026",
      "name": "Structured Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        368,
        128
      ],
      "parameters": {
        "autoFix": true,
        "jsonSchemaExample": " {\"Prompt\": \"Prompt\"}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "e223ac61-624a-4f25-874f-aa760a76a727",
      "name": "Google Gemini1",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        208,
        128
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-2.5-pro"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "412a7d55-0c3c-4741-bc56-64d3da9d276f",
      "name": "User Sends Message to Bot",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        -1168,
        368
      ],
      "parameters": {
        "updates": [
          "message",
          "callback_query"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "executeOnce": false,
      "retryOnFail": false,
      "typeVersion": 1.2,
      "alwaysOutputData": false
    },
    {
      "id": "4d9aac81-bdc2-4937-bf73-1f320af181ba",
      "name": "Check for Query Callback",
      "type": "n8n-nodes-base.switch",
      "position": [
        -912,
        368
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "0f8905bc-c237-43a2-bd81-5ac10fdd015b",
                    "operator": {
                      "type": "object",
                      "operation": "exists",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.callback_query }}",
                    "rightValue": ""
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "a7924730-096d-4a2f-b4ec-0917fba5295a",
                    "operator": {
                      "type": "object",
                      "operation": "notExists",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.callback_query }}",
                    "rightValue": ""
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "e7c7723d-4b94-4d1c-a592-dffb65704da9",
      "name": "Check For Input Type",
      "type": "n8n-nodes-base.switch",
      "position": [
        -224,
        560
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "9e003f66-d011-459a-a313-b603c0e14551",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.output.Type }}",
                    "rightValue": "Start"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "2ebb24ec-bd32-4e96-a022-93d066fda17f",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.output.Type }}",
                    "rightValue": "Chat"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "24d355dd-efec-4946-96fe-3d82f3ee4d71",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.output.Type }}",
                    "rightValue": "NoData"
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "74e5e3ca-6f01-4895-9713-397558d62d87",
      "name": "Save Sheet ID and Keyword",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        880,
        368
      ],
      "parameters": {
        "columns": {
          "value": {
            "Keyword": "={{ $('Validate user input').item.json.output.Keyword }}",
            "row_number": 2,
            "Current Workflow Sheet ID": "={{ $json.sheetId }}"
          },
          "schema": [
            {
              "id": "Current Workflow Sheet ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Current Workflow Sheet ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Keyword",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Keyword",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "row_number"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic/edit#gid=0",
          "cachedResultName": "Database"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic/edit?usp=drivesdk",
          "cachedResultName": "Thumbnail Data base"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "1713c697-9fe4-491e-ae74-430afea55f00",
      "name": "Save Image Descriptions to Database",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2144,
        656
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Create Database sheet').first().json.sheetId }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic/edit?usp=drivesdk",
          "cachedResultName": "Thumbnail Data base"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "f587c36a-9e9a-4595-a9d3-d2178bcfbf0a",
      "name": "Await Continuation Approval",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1872,
        480
      ],
      "parameters": {
        "text": "Okay, I grabbed a few examples. Do you want to Continue? (Cost Credits)",
        "chatId": "={{ $('User Sends Message to Bot').first().json.message.chat.id }}",
        "replyMarkup": "inlineKeyboard",
        "inlineKeyboard": {
          "rows": [
            {
              "row": {
                "buttons": [
                  {
                    "text": "Yes, Continue Please.",
                    "additionalFields": {
                      "callback_data": "yes"
                    }
                  },
                  {
                    "text": "No, I don't have credits in my Gemini account",
                    "additionalFields": {
                      "callback_data": "no"
                    }
                  }
                ]
              }
            }
          ]
        },
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "executeOnce": true,
      "typeVersion": 1.2
    },
    {
      "id": "ea3d0cc0-602e-4aca-b23f-7f20710b29c9",
      "name": "Splitting Image Items",
      "type": "n8n-nodes-base.code",
      "position": [
        1056,
        656
      ],
      "parameters": {
        "jsCode": "// Get the JSON string using the exact path provided by the user.\nconst jsonString = $input.first().json.output.string;\n\nlet parsedData;\n\n// Check if the string exists before attempting to parse\nif (!jsonString) {\n    // Return an empty array or throw an error if no string is found\n    // Throwing an error is usually better to stop the workflow if data is missing.\n    throw new Error(\"Input string is empty or missing at the specified path: $input.first().json.output.string\");\n}\n\ntry {\n    // 1. Parse the JSON string into a JavaScript array of objects\n    parsedData = JSON.parse(jsonString);\n} catch (error) {\n    // Handle JSON parsing errors (e.g., if the string is malformed)\n    throw new Error(`Failed to parse JSON string: ${error.message}`);\n}\n\n// 2. Ensure the parsed data is an array\nif (!Array.isArray(parsedData)) {\n    throw new Error('Parsed data is not an array. It cannot be split into multiple items.');\n}\n\n// 3. Map the array of objects into the n8n item format { json: object }\n// Each element in this array will be treated as a new item by n8n, achieving the split.\nconst outputItems = parsedData.map(item => ({\n    json: item,\n}));\n\n// 4. Return the new array of items\nreturn outputItems;"
      },
      "typeVersion": 2
    },
    {
      "id": "7f1f9701-9ad6-4a8a-81b3-db9442aacfaf",
      "name": "Filter Low-Quality Images",
      "type": "n8n-nodes-base.code",
      "position": [
        1280,
        656
      ],
      "parameters": {
        "jsCode": "// 1. Flatten the data from the nested \"item\" structure\nconst flattenedData = $input.all().flatMap(item => item.json.item || []);\n\n// 2. Define valid image extensions\nconst validExtensions = ['.jpg', '.jpeg', '.png', '.webp', '.gif'];\n\n// 3. Process, Clean, and Filter\nconst results = flattenedData.reduce((acc, row) => {\n  let url = row.Cover;\n\n  if (url) {\n    // Clean the URL: Remove everything after the '?'\n    url = url.split('?')[0];\n\n    // Check if the CLEANED url ends with a valid extension\n    // We convert to lowercase to ensure .JPG and .jpg both work\n    const hasExtension = validExtensions.some(ext => url.toLowerCase().endsWith(ext));\n\n    if (hasExtension) {\n      // Update the row with the clean URL\n      row.Cover = url;\n      \n      // Add to our final list wrapped in n8n's required \"json\" format\n      acc.push({ json: row });\n    }\n  }\n  return acc;\n}, []);\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "14d0d22d-ab6b-48e1-8194-3cf23edea9ee",
      "name": "Analyze Image Content",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1824,
        656
      ],
      "parameters": {
        "text": "=[\n  {\n    \"type\": \"text\",\n    \"text\": \"Analyze this image in extreme detail.\"\n  },\n  {\n    \"type\": \"image_url\",\n    \"image_url\": {\n      \"url\": \"{{ $json.Cover }}\",\n      \"detail\": \"high\"\n    }\n  }\n]",
        "options": {
          "systemMessage": "You are an advanced image analysis AI specialized in deconstructing YouTube thumbnails. Your sole task is to generate an exhaustive, forensic-level description of the provided thumbnail image. You must analyze and describe absolutely every visual element present without omission.\n\nMethodically scan the image and provide a detailed account covering:\n\nBackground: The complete setting, location, environment, scenery, lighting, and weather.\n\nForeground & Subjects: Every person, character, or main object. Detail their appearance, clothing, facial expressions, poses, actions, and exact spatial positions relative to the frame.\n\nText: Transcribe absolutely all visible text exactly as it appears (including capitalization and punctuation). For every text element, specify its exact content, font style (e.g., bold, capitalized, handwritten), color, any effects (like outlines or shadows), and its precise location on the image.\n\nGraphics & Effects: Describe any logos, icons, brand marks, arrows, circles, emojis, overlays, borders, or visual effects (like explosions, blurs, or high contrast filters).\n\nComposition: The overall color palette, dominant tones, and the general mood or vibe the thumbnail conveys.\n\nCRITICAL OUTPUT CONSTRAINT: Your final output must consist only of the raw descriptive text stream. Do not include any introductions, explanations, section headers, formatting tags, metadata, or conversational fillers. Send only the complete description."
        },
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "0a69d38e-0c3d-4f7a-b80d-3fedd0f0e59c",
      "name": "Answer the User",
      "type": "n8n-nodes-base.telegram",
      "position": [
        480,
        1152
      ],
      "parameters": {
        "text": "={{ $json.output }}",
        "chatId": "={{ $('User Sends Message to Bot').item.json.message.chat.id }}",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ca0dee61-0138-4e4a-a7af-ab21a9a2da0a",
      "name": "Chat with User",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        112,
        1152
      ],
      "parameters": {
        "text": "=Input type : {{ $json.output.Type }} | User Input : {{ $('User Sends Message to Bot').item.json.message.text }}",
        "options": {
          "systemMessage": "You are a Video Content Assistant. Your role is to converse with the user to help them define a video topic.\n\nAnalyze the user's input and respond strictly according to these rules:\n\n1. IF THE INPUT IS CASUAL CHAT:\n   - If the user says \"Hello\", \"How are you\", or makes small talk, respond in a friendly, conversational manner.\n   - Example response: \"Hello! I am ready to help you create content. What topic are we working on today?\"\n\n2. IF THE INPUT IS INSUFFICIENT DATA / UNCLEAR:\n   - If the user says vague words like \"ok\", \"yes\", \"maybe\", or random characters, politely ask them to clarify their specific interest or niche.\n   - Example response: \"I'm not sure I understood. Could you tell me exactly what <b>niche</b> or <b>video topic</b> you want to focus on?\"\n\nOUTPUT FORMATTING RULES:\n- Output ONLY the raw text message.\n- Do NOT use JSON.\n- Do NOT use Markdown code blocks (no ```text or ```).\n- Do NOT use standard Markdown (no ** or __).\n- You MAY ONLY use the following Telegram-supported HTML tags for emphasis: <b>bold</b>, <i>italic</i>, <s>strikethrough</s>, <u>underline</u>, <code>code</code>."
        },
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "2f40312a-783a-4b89-b344-1da60dbe3a9b",
      "name": "Validate input",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -736,
        816
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "1af27ee3-eed5-407f-8676-21b9008a6a8c",
      "name": "Chat",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        112,
        1312
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b664143b-81f0-442d-8088-62d1a5ed8512",
      "name": "Wait for Google Sheet Creation",
      "type": "n8n-nodes-base.wait",
      "position": [
        352,
        496
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "dc947ab4-423c-44b6-ad84-334cf8301543",
      "name": "Send Thumbnail Back to Bot",
      "type": "n8n-nodes-base.telegram",
      "position": [
        848,
        -64
      ],
      "parameters": {
        "chatId": "={{ $('User Sends Message to Bot').first().json.callback_query.message.chat.id}}",
        "operation": "sendPhoto",
        "binaryData": true,
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "96480ff3-c4e0-4b96-a58f-8f09308cb9ce",
      "name": "Check If User Wants to Continue",
      "type": "n8n-nodes-base.if",
      "position": [
        -592,
        96
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "3a21e41d-e184-4db8-b0dd-9f2cda6842b9",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.callback_query.data }}",
              "rightValue": "yes"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "edb44cbc-12df-40ea-8fd7-1ed8c035a44f",
      "name": "Aggregate Google Sheets data",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -48,
        80
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "=AggreagtedData"
      },
      "typeVersion": 1
    },
    {
      "id": "73f7e177-f974-486b-9d75-09dd53bd5712",
      "name": "Create Database sheet",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueErrorOutput",
      "position": [
        64,
        640
      ],
      "parameters": {
        "title": "={{ $json.output.Keyword }}",
        "options": {},
        "operation": "create",
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic/edit?usp=drivesdk",
          "cachedResultName": "Thumbnail Data base"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "628eba2c-6c5f-40ed-a3ec-6e2951fd1f1d",
      "name": "Clear Database sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        640,
        656
      ],
      "parameters": {
        "operation": "clear",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.sheetId }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/11H5l1UY01E38UzJ98WjZcFJS4oqyAuLZ2fggnKQ74ic/edit?usp=drivesdk",
          "cachedResultName": "Thumbnail Data base"
        },
        "keepFirstRow": true
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "007f73e8-1174-4c17-b2e3-18524648b5d5",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        656,
        320
      ],
      "parameters": {
        "color": 3,
        "width": 400,
        "height": 224,
        "content": "### \ud83d\udcca Google Sheets Requirements\n\n**Spreadsheet Name:**\nThumbnail Data base\n\n**Sheet Name:**\nDatabase\n\n**Required Columns:**\n* Keyword\n* Current Workflow Sheet ID"
      },
      "typeVersion": 1
    },
    {
      "id": "02396726-3d1c-47c5-99fb-4b89770092e0",
      "name": "Documentation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1664,
        -64
      ],
      "parameters": {
        "width": 420,
        "height": 560,
        "content": "## \u26a1 Workflow Overview & Setup\n\n**Summary:** An advanced AI Thumbnail Artist that scrapes YouTube trends, analyzes visual hooks, and generates high-CTR thumbnails. It features an **interactive approval loop** via Telegram to verify costs before generation.\n\n### Requirements\n* **Credentials:** Telegram, BrowserAct, OpenRouter, Google Gemini, Google Sheets.\n* **Mandatory:** BrowserAct API (Template: **Thumbnail Maker Bot**)\n\n### How to Use\n1.  **Credentials:** Connect all services. Ensure your Google Sheet has columns for `Keyword` and `Sheet ID`.\n2.  **BrowserAct Template:** Save the **Thumbnail Maker Bot** template in BrowserAct.\n3.  **Process:** \n    * Send a topic (e.g., \"AI News\") to the bot.\n    * The bot scrapes data and analyzes it.\n    * **Click the \"Yes, Continue\" button** in Telegram to authorize the AI image generation.\n\n### Need Help?\n[How to Find Your BrowserAct API Key & Workflow ID](https://docs.browseract.com)\n[How to Connect n8n to BrowserAct](https://docs.browseract.com)\n[How to Use & Customize BrowserAct Templates](https://docs.browseract.com)"
      },
      "typeVersion": 1
    },
    {
      "id": "1f737dd1-529b-467f-b575-d0ada29c9ae1",
      "name": "Step 1 Explanation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1008,
        944
      ],
      "parameters": {
        "color": 7,
        "width": 968,
        "height": 108,
        "content": "### \ud83e\udde0 Step 1: Intent Analysis\n\nThe workflow intercepts text messages to classify user intent. If a video topic is detected, it prepares a new database entry in Google Sheets to track the session and initiates the research phase."
      },
      "typeVersion": 1
    },
    {
      "id": "7b0734db-fac7-4293-a321-a2df8dd174e7",
      "name": "Step 2 Explanation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        80,
        896
      ],
      "parameters": {
        "color": 7,
        "width": 2200,
        "height": 80,
        "content": "### \ud83d\udd75\ufe0f Step 2: Visual Research\n\nBrowserAct scrapes YouTube for the given keyword. The workflow then uses AI to analyze the visual composition of top-performing thumbnails, saving these \"visual hooks\" to the database for later use."
      },
      "typeVersion": 1
    },
    {
      "id": "814a31d3-417e-4bba-b478-54936bf9005e",
      "name": "Step 3 Explanation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1552,
        384
      ],
      "parameters": {
        "color": 7,
        "width": 808,
        "height": 80,
        "content": "### \u23f8\ufe0f Step 3: Human-in-the-Loop\n\nTo prevent wasted API credits, the workflow pauses and sends a Telegram message with an interactive button. It waits for the user to explicitly click \"Yes, Continue\" before generating the final image."
      },
      "typeVersion": 1
    },
    {
      "id": "dba877e1-9364-4cac-87e9-3a9c730c20ab",
      "name": "Step 4 Explanation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -656,
        -192
      ],
      "parameters": {
        "color": 7,
        "width": 1664,
        "height": 96,
        "content": "### \ud83c\udfa8 Step 4: Callback & Generation\n\nWhen the button is clicked, this branch activates. It retrieves the saved visual research from Google Sheets, feeds it into the \"Apex Architect\" AI to create a cinematic prompt, and generates the final 16:9 thumbnail."
      },
      "typeVersion": 1
    },
    {
      "id": "bcb05ff4-b5f4-4a87-ac67-481b5e1f7564",
      "name": "Step 4 Explanation1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        1424
      ],
      "parameters": {
        "color": 7,
        "width": 564,
        "height": 96,
        "content": "### \ud83d\udcac Step 2-2: Conversational Fallback\n\nProcesses user input to define \"Video Topics\" or handle casual chat using specific HTML formatting."
      },
      "typeVersion": 1
    },
    {
      "id": "de30678f-2e8d-4e11-a508-88068b85540f",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1232,
        -64
      ],
      "parameters": {
        "color": 6,
        "width": 528,
        "height": 304,
        "content": "@[youtube](m0N91nN4ElA)"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "13cd766c-de66-4345-b79c-e905e5421683",
  "connections": {
    "Chat": {
      "ai_languageModel": [
        [
          {
            "node": "Chat with User",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Get Keywords": {
      "main": [
        [
          {
            "node": "Get Images Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Chat with User": {
      "main": [
        [
          {
            "node": "Answer the User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini1": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Image Prompt",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Structured Output",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Run a workflow": {
      "main": [
        [
          {
            "node": "Splitting Image Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate input": {
      "ai_languageModel": [
        [
          {
            "node": "Validate user input",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Structured Output Parser",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Await Continuation Approval",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Analyze Image Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate an image": {
      "main": [
        [
          {
            "node": "Send Thumbnail Back to Bot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output": {
      "ai_outputParser": [
        [
          {
            "node": "Generate Image Prompt",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Get Images Details": {
      "main": [
        [
          {
            "node": "Aggregate Google Sheets data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate user input": {
      "main": [
        [
          {
            "node": "Check For Input Type",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check For Input Type": {
      "main": [
        [
          {
            "node": "Create Database sheet",
            "type": "main",
            "index": 0
          },
          {
            "node": "Inform user",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Chat with User",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Chat with User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clear Database sheet": {
      "main": [
        [
          {
            "node": "Run a workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Image Content": {
      "main": [
        [
          {
            "node": "Save Image Descriptions to Database",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Database sheet": {
      "main": [
        [
          {
            "node": "Wait for Google Sheet Creation",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Clear Database sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Image Prompt": {
      "main": [
        [
          {
            "node": "Generate an image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Analyze Image Content",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Splitting Image Items": {
      "main": [
        [
          {
            "node": "Filter Low-Quality Images",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check for Query Callback": {
      "main": [
        [
          {
            "node": "Check If User Wants to Continue",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Validate user input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Validate user input",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Filter Low-Quality Images": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "User Sends Message to Bot": {
      "main": [
        [
          {
            "node": "Check for Query Callback",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Google Sheets data": {
      "main": [
        [
          {
            "node": "Generate Image Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Google Sheet Creation": {
      "main": [
        [
          {
            "node": "Clear Database sheet",
            "type": "main",
            "index": 0
          },
          {
            "node": "Save Sheet ID and Keyword",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If User Wants to Continue": {
      "main": [
        [
          {
            "node": "Get Keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Image Descriptions to Database": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "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

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, analyze their visual strategies using AI vision, and generate a new,…

Source: https://n8n.io/workflows/12363/ — 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 project is a template for building a complete academic virtual assistant using n8n. It connects to Telegram, answers frequently asked questions by querying MongoDB, keeps the community informed a

Telegram, MongoDB, Telegram Trigger +6
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

&gt; AI-powered nutrition assistant for Telegram — log meals, set goals, and get personalized daily reports with Google Sheets integration.

Telegram, Google Gemini, Google Gemini Chat +7
AI & RAG

This automation is designed to help you generate AI-powered music tracks, cover art, and fully rendered music videos — all triggered from a simple Telegram chat and managed via Google Sheets.

OpenAI Chat, Memory Buffer Window, Output Parser Structured +11
AI & RAG

LinkedIn URL → Scrape → Match → Screen → Decide, all automated

Google Drive, Agent, Google Drive Tool +6