This workflow follows the HTTP Request → Telegram 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 →
{
"name": "Telegram Weather Chatbot",
"nodes": [
{
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"id": "telegram-trigger",
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1.1,
"position": [
0,
0
],
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "set-original-text",
"name": "originalText",
"value": "={{ $json.message.text }}",
"type": "string"
},
{
"id": "set-chat-id",
"name": "chatId",
"value": "={{ $json.message.chat.id }}",
"type": "number"
}
]
},
"options": {}
},
"id": "set-captura",
"name": "Captura Mensagem",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
220,
0
]
},
{
"parameters": {
"method": "POST",
"url": "https://openrouter.ai/api/v1/chat/completions",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $env.OPENROUTER_API_KEY }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"model\": \"qwen/qwen3-vl-235b-a22b-thinking\",\n \"models\": [\"qwen/qwen3-vl-235b-a22b-thinking\", \"qwen/qwen3-next-80b-a3b-instruct:free\"],\n \"route\": \"fallback\",\n \"temperature\": 0.1,\n \"max_tokens\": 80,\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"Voc\u00ea extrai nomes de cidades brasileiras. Responda APENAS com: Cidade,UF,BR (sempre termine com ,BR). Exemplos: S\u00e3o Paulo,SP,BR | Belo Horizonte,MG,BR | Colatina,ES,BR. Apelidos: sampa=S\u00e3o Paulo,SP,BR, BH=Belo Horizonte,MG,BR, floripa=Florian\u00f3polis,SC,BR, poa=Porto Alegre,RS,BR, rio=Rio de Janeiro,RJ,BR, brasilia=Bras\u00edlia,DF,BR, cwb=Curitiba,PR,BR. Se n\u00e3o identificar, responda ERRO. Sem explica\u00e7\u00f5es.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"{{ $json.originalText }}\"\n }\n ]\n}",
"options": {
"response": {
"response": {
"neverError": true
}
}
}
},
"id": "llm-extrai-cidade",
"name": "LLM Extrai Cidade",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
440,
0
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n const data = item.json;\n const chatId = $('Captura Mensagem').first().json.chatId;\n const originalText = $('Captura Mensagem').first().json.originalText || '';\n let queue = '';\n\n try {\n const llmResponse = data.choices[0].message.content.trim();\n const cleaned = llmResponse.replace(/<think>[\\s\\S]*?<\\/think>/g, '').trim();\n if (cleaned && cleaned !== 'ERRO') {\n queue = cleaned;\n }\n } catch (e) {\n // LLM falhou, usa fallback\n }\n\n // Fallback determin\u00edstico \u2014 extra\u00e7\u00e3o e normaliza\u00e7\u00e3o sem LLM\n if (!queue) {\n let text = originalText.trim();\n // Remove frases comuns para extrair s\u00f3 o nome da cidade\n text = text.replace(/^(qual o clima em|clima em|temperatura de|temperatura em|como .* em|me .* de)\\s*/i, '').trim();\n // Remove pontua\u00e7\u00e3o final\n text = text.replace(/[?.!]+$/g, '').trim();\n // Normaliza separadores: 'S\u00e3o Paulo SP' \u2192 'S\u00e3o Paulo,SP'\n // Detecta UF de 2 letras no final separada por espa\u00e7o\n text = text.replace(/\\s+([A-Za-z]{2})$/, ',$1');\n // Split na v\u00edrgula, trim de cada parte, e remonta\n const parts = text.split(',').map(p => p.trim()).filter(p => p.length > 0);\n // Se tem 2 partes (Cidade,UF), adiciona BR\n if (parts.length === 2 && parts[1].length === 2) {\n parts.push('BR');\n }\n queue = parts.join(',');\n }\n\n results.push({\n json: { queue, chatId, originalText }\n });\n}\n\nreturn results;"
},
"id": "code-parse-llm",
"name": "Processa Resposta LLM",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
660,
0
]
},
{
"parameters": {
"method": "GET",
"url": "https://api.openweathermap.org/data/2.5/weather",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $json.queue }}"
},
{
"name": "units",
"value": "metric"
},
{
"name": "lang",
"value": "pt_br"
},
{
"name": "appid",
"value": "={{ $env.OPENWEATHER_API_KEY }}"
}
]
},
"options": {
"response": {
"response": {
"neverError": true
}
}
}
},
"id": "http-openweather",
"name": "Consulta OpenWeather",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
880,
0
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "condition-cod-200",
"leftValue": "={{ $json.cod }}",
"rightValue": 200,
"operator": {
"type": "number",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "if-valida-resposta",
"name": "Resposta V\u00e1lida?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1100,
0
]
},
{
"parameters": {
"method": "POST",
"url": "https://openrouter.ai/api/v1/chat/completions",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $env.OPENROUTER_API_KEY }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"model\": \"qwen/qwen3-vl-235b-a22b-thinking\",\n \"models\": [\"qwen/qwen3-vl-235b-a22b-thinking\", \"qwen/qwen3-next-80b-a3b-instruct:free\"],\n \"route\": \"fallback\",\n \"temperature\": 0.5,\n \"max_tokens\": 150,\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"Voc\u00ea \u00e9 um assistente de clima simp\u00e1tico. Receba os dados do clima e responda de forma curta, educada e natural em portugu\u00eas brasileiro. Use emojis de clima. Inclua a temperatura e a condi\u00e7\u00e3o. M\u00e1ximo 2 frases.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Cidade: {{ $json.name }}, Temperatura: {{ $json.main.temp }}\u00b0C, Condi\u00e7\u00e3o: {{ $json.weather[0].description }}, Humidade: {{ $json.main.humidity }}%, Vento: {{ $json.wind.speed }} m/s\"\n }\n ]\n}",
"options": {
"response": {
"response": {
"neverError": true
}
}
}
},
"id": "llm-resposta-sucesso",
"name": "LLM Resposta Sucesso",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1320,
-120
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n const data = item.json;\n const chatId = $('Processa Resposta LLM').first().json.chatId;\n let message = '';\n\n try {\n const llmResponse = data.choices[0].message.content.trim();\n const cleaned = llmResponse.replace(/<think>[\\s\\S]*?<\\/think>/g, '').trim();\n if (cleaned) {\n message = cleaned;\n }\n } catch (e) {\n // LLM falhou\n }\n\n // Fallback determin\u00edstico\n if (!message) {\n const weather = $('Resposta V\u00e1lida?').first().json;\n const cidade = weather.name || 'Desconhecida';\n const temp = Math.round(weather.main.temp);\n const desc = weather.weather[0].description || '';\n message = `\ud83c\udf24\ufe0f A temperatura em ${cidade} \u00e9 de ${temp}\u00b0C.\\nCondi\u00e7\u00e3o: ${desc}.`;\n }\n\n results.push({\n json: { chatId, message }\n });\n}\n\nreturn results;"
},
"id": "code-formata-sucesso",
"name": "Formata Sucesso",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1540,
-120
]
},
{
"parameters": {
"chatId": "={{ $json.chatId }}",
"text": "={{ $json.message }}",
"additionalFields": {}
},
"id": "telegram-send-sucesso",
"name": "Envia Temperatura",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
1760,
-120
],
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://openrouter.ai/api/v1/chat/completions",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $env.OPENROUTER_API_KEY }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"model\": \"qwen/qwen3-vl-235b-a22b-thinking\",\n \"models\": [\"qwen/qwen3-vl-235b-a22b-thinking\", \"qwen/qwen3-next-80b-a3b-instruct:free\"],\n \"route\": \"fallback\",\n \"temperature\": 0.3,\n \"max_tokens\": 120,\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"Voc\u00ea \u00e9 um assistente de clima simp\u00e1tico. O usu\u00e1rio pediu o clima de uma cidade que n\u00e3o foi encontrada. Responda de forma educada em portugu\u00eas brasileiro, informando que n\u00e3o encontrou a cidade e sugerindo o formato Cidade,UF (exemplo: S\u00e3o Paulo,SP). Use emoji \u274c. M\u00e1ximo 2 frases.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"A mensagem original do usu\u00e1rio foi: {{ $('Processa Resposta LLM').first().json.originalText }}\"\n }\n ]\n}",
"options": {
"response": {
"response": {
"neverError": true
}
}
}
},
"id": "llm-resposta-erro",
"name": "LLM Resposta Erro",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1320,
120
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n const data = item.json;\n const chatId = $('Processa Resposta LLM').first().json.chatId;\n let message = '';\n\n try {\n const llmResponse = data.choices[0].message.content.trim();\n const cleaned = llmResponse.replace(/<think>[\\s\\S]*?<\\/think>/g, '').trim();\n if (cleaned) {\n message = cleaned;\n }\n } catch (e) {\n // LLM falhou\n }\n\n // Fallback determin\u00edstico\n if (!message) {\n message = '\u274c Cidade n\u00e3o encontrada. Use o formato Cidade,UF (ex.: S\u00e3o Paulo,SP).';\n }\n\n results.push({\n json: { chatId, message }\n });\n}\n\nreturn results;"
},
"id": "code-formata-erro",
"name": "Formata Erro",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1540,
120
]
},
{
"parameters": {
"chatId": "={{ $json.chatId }}",
"text": "={{ $json.message }}",
"additionalFields": {}
},
"id": "telegram-send-erro",
"name": "Envia Erro",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
1760,
120
],
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
}
],
"connections": {
"Telegram Trigger": {
"main": [
[
{
"node": "Captura Mensagem",
"type": "main",
"index": 0
}
]
]
},
"Captura Mensagem": {
"main": [
[
{
"node": "LLM Extrai Cidade",
"type": "main",
"index": 0
}
]
]
},
"LLM Extrai Cidade": {
"main": [
[
{
"node": "Processa Resposta LLM",
"type": "main",
"index": 0
}
]
]
},
"Processa Resposta LLM": {
"main": [
[
{
"node": "Consulta OpenWeather",
"type": "main",
"index": 0
}
]
]
},
"Consulta OpenWeather": {
"main": [
[
{
"node": "Resposta V\u00e1lida?",
"type": "main",
"index": 0
}
]
]
},
"Resposta V\u00e1lida?": {
"main": [
[
{
"node": "LLM Resposta Sucesso",
"type": "main",
"index": 0
}
],
[
{
"node": "LLM Resposta Erro",
"type": "main",
"index": 0
}
]
]
},
"LLM Resposta Sucesso": {
"main": [
[
{
"node": "Formata Sucesso",
"type": "main",
"index": 0
}
]
]
},
"Formata Sucesso": {
"main": [
[
{
"node": "Envia Temperatura",
"type": "main",
"index": 0
}
]
]
},
"LLM Resposta Erro": {
"main": [
[
{
"node": "Formata Erro",
"type": "main",
"index": 0
}
]
]
},
"Formata Erro": {
"main": [
[
{
"node": "Envia Erro",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [],
"triggerCount": 1,
"updatedAt": "2026-02-21T17:40:00.000Z",
"versionId": "4"
}
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.
telegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Telegram Weather Chatbot. Uses telegramTrigger, httpRequest, telegram. Event-driven trigger; 12 nodes.
Source: https://github.com/fredstrey/Telegram-Weather-Chatbot---N8N/blob/2d7e0cab9187d7a2b3d3a24a36f09d3599328bea/workflow-chatbot-telegram.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Try on any outfit virtually - right inside Telegram. A user sends a person photo, then a garment photo (captioned ), and the bot replies with an AI-generated try-on result image using a dedicated Virt
A robust n8n workflow designed to enhance Telegram bot functionality for user management and broadcasting. It facilitates automatic support ticket creation, efficient user data storage in Redis, and a
Transform your digital payment business with a fully-featured Telegram bot that handles everything from product listings to transaction processing. Perfect for entrepreneurs looking to automate their
TGBot. Uses telegram, googleSheets, telegramTrigger, httpRequest. Event-driven trigger; 30 nodes.
This template provides a workflow to integrate a Telegram bot with NeurochainAI's inference capabilities, supporting both text processing and image generation. Follow these steps to get started: