📁 last Posts

How to Connect n8n to Telegram: Complete Bot Guide + Templates

How to Connect n8n to Telegram: Complete Bot Guide + Templates

⏱️ 20 min read · 📥 Free template + dynamic menus, media & polling coverage

Here's a confession: my first Telegram bot ignored me for two hours. The trigger was "working" — the workflow was active, the token was right — but the bot sat there silent. The cause was a setting buried in BotFather's menu that nobody's guide mentions. You'll read it in section 2, and you'll never lose those two hours yourself.

The Direct Answer

Connecting n8n to Telegram takes three steps: (1) create a bot with BotFather and copy its token; (2) add that token as a Telegram credential in n8n; (3) build a workflow with a Telegram Trigger (to receive messages and button presses) and a Telegram node (to send replies). Inline keyboard buttons are sent via the Bot API, and the full importable command bot is in section 8.

The two things that trip up 90% of people — finding the chat ID and the trigger not firing in groups — get their own sections (6 and 16), because nobody else explains them properly.


1. What the Telegram Nodes Can Do

n8n has two Telegram nodes, and knowing the split saves you an hour of searching the node panel:

NodeDirectionWhat it does
Telegram Trigger Telegram → n8n Fires on new messages, callback queries (button presses), inline queries, and edited messages. This is the bot's ears.
Telegram n8n → Telegram Sends messages, photos, videos, audio, documents; edits and deletes messages; manages chat members; pins messages. This is the bot's mouth.

The sending node's most useful operations, in the order you'll actually use them:

OperationUse it for
Send MessageText replies, alerts, HTML/Markdown formatting, keyboards
Send Photo / DocumentAttaching files from other nodes or by URL
Edit MessageLive status updates — "processing…" → "done ✅"
Delete MessageCleaning up bot replies, removing expired content
Get Chat / Get Chat MembersReading group info, building member lists
Pin / Unpin MessagePinning daily reports in a channel
Answer Callback QueryClosing the "loading" state after a button press

2. BotFather: Token, Commands & Privacy Mode

Every bot starts in a chat with @BotFather — Telegram's official bot-creator. Open the chat and run /newbot. It asks for a name (anything) and a username (must end in bot, must be unique). It then returns the only thing that matters:

Use this token to access the HTTP API:
7123456789:AAHxKpQ1wZ4vV5mN8rT2yU9sW3cB6dE0fG7h

Keep your token secure and store it safely.
It can be used by anyone to control your bot.

Then run these three BotFather commands — the third one is the setting that ignored me for two hours:

1

/setcommands — register your bot's commands

Paste a list like start - Welcome message per line. It powers the little / menu users see in the chat — a detail that makes your bot feel professional for free.

2

/setprivacy — then choose Disable

This is the two-hour trap. With privacy mode ON (the default), your bot in a group only sees messages that mention it or start with /. Disable it if the bot must read all group messages — e.g., an auto-moderation bot.

3

/setjoingroups — decide where the bot may live

If the bot is personal (alerts only), disable group joining — it removes an entire class of abuse and confusion.


3. Connect n8n (Credential + Token Security)

In n8n: Credentials → Add credential → Telegram API, paste the token from BotFather, save. Give it a name like MyBot. That's it — both Telegram nodes will offer this credential.

⚠️
The token IS the bot. Anyone who holds it can read your bot's messages and post as your bot. Keep it in the credential only — never in workflow JSON you share, never in screenshots. If it ever leaks, /revoke in BotFather generates a fresh one in seconds.

One more thing worth doing now: when you publish a workflow template, n8n replaces real credential references with placeholders — but your own exports contain the credential IDs. That's fine for your backups; just don't share raw exports publicly.


4. Your First Bot: Trigger + Echo

The minimal bot is two nodes: a Telegram Trigger listening for messages, and a Telegram Send Message replying. The trigger returns the raw Telegram update — the fields you'll use most:

  • $json.message.text — what the user typed
  • $json.message.chat.id — where to reply
  • $json.message.from.first_name — who wrote it
  • $json.callback_query.data — which button was pressed (section 5)

The trigger node, exported (this is the exact structure to import):

{
  "parameters": {
    "updates": ["message", "callback_query"],
    "additionalFields": {
      "download": true
    }
  },
  "name": "Telegram Trigger",
  "type": "n8n-nodes-base.telegramTrigger",
  "typeVersion": 1.1,
  "position": [250, 300],
  "credentials": {
    "telegramApi": {
      "id": "YOUR_TELEGRAM_CREDENTIAL_ID"
    }
  }
}

And the reply node — the two required fields are chatId and text:

{
  "parameters": {
    "chatId": "={{ $json.message.chat.id }}",
    "text": "=You said: {{ $json.message.text }}",
    "additionalFields": {
      "parseMode": "HTML"
    }
  },
  "name": "Send Reply",
  "type": "n8n-nodes-base.telegram",
  "typeVersion": 1.2,
  "position": [650, 300],
  "credentials": {
    "telegramApi": {
      "id": "YOUR_TELEGRAM_CREDENTIAL_ID"
    }
  }
}
💡
Remember the = rule: any field using {{ }} must start with = — otherwise n8n sends the expression as literal text. It's the single most common "my bot replies with brackets" bug.

Connect them, activate the workflow (production activation — manual "Execute workflow" doesn't run triggers), open your bot in Telegram, press Start, and send a message. The echo comes back instantly.

ℹ️
One requirement nobody warns you about: the Telegram Trigger works over a webhook — when you activate the workflow, n8n registers itself with Telegram, which means n8n must be reachable through a public HTTPS URL. Hosting behind CGNAT or without a domain? Section 10 has the polling alternative.

5. Inline Keyboards & Callback Buttons

A bot that only echoes is a toy. A bot with buttons is an interface. Inline keyboards are the row of tappable buttons under a message — and they're the single biggest gap in every competitor's guide, because most of them never explain what happens after the tap.

5.1 The two halves of a button

  • Sending the keyboard: the message carries a reply_markup with an inline_keyboard array. Each button has text (the label) and either callback_data (fires your workflow) or url (opens a link).
  • Receiving the tap: when a user presses a callback button, Telegram sends a callback_query update — which is why the trigger in section 4 listens for callback_query too, not just messages.

5.2 The reliable way: send via the Bot API

Here's the honest engineering truth: the Telegram node's visual keyboard builder is rigid — one fixed keyboard per node. The moment your buttons need to change (dynamic lists, per-user menus), the community-standard solution is to call Telegram's API directly from an HTTP Request node. It works on every n8n version and every plan. One trick makes it clean: the token comes from an environment variable ($env.TELEGRAM_TOKEN), so it never has to sit inside the workflow itself:

// Code node — build the payload (keyboard included)
const item = $input.item.json;
const chatId = item.message.chat.id;

const payload = {
  chat_id: chatId,
  text: 'What would you like to do?',
  reply_markup: {
    inline_keyboard: [
      [
        { text: '✅ Approve', callback_data: 'approve' },
        { text: '❌ Reject', callback_data: 'reject' }
      ],
      [
        { text: '🌐 Visit site', url: 'https://triggerworkflow.com' }
      ]
    ]
  }
};

return [{ json: { body: JSON.stringify(payload) } }];
# First, expose the token once — in your docker-compose.yml
environment:
  - TELEGRAM_TOKEN=7123456789:AA-your-real-token

# HTTP Request node — POST the payload to the Bot API
# URL:
=https://api.telegram.org/bot{{ $env.TELEGRAM_TOKEN }}/sendMessage
# Body content type: JSON, body:
={{ $json.body }}

Limits worth memorizing: callback_data is capped at 64 bytes, and one message fits roughly 1–2 rows × 8 buttons before the keyboard gets cramped. For anything bigger, link to a sub-menu message instead.

5.3 Dynamic menus & multi-level navigation

Static keyboards answer one question. Dynamic menus build an interface — main menu → settings → profile — where every tap redraws the buttons. The pattern is a switch on callback_data:

// Menu router — every button's callback_data is a route
const cq = item.callback_query;
const route = cq.data;                 // 'main' | 'settings' | 'profile'
let text = '';
let keyboard = null;

switch (route) {
  case 'main':
    text = 'Main menu';
    keyboard = [[
      { text: '⚙️ Settings', callback_data: 'settings' },
      { text: '👤 Profile', callback_data: 'profile' }
    ]];
    break;
  case 'settings':
    text = 'Settings — nothing here yet.';
    keyboard = [[{ text: '🔙 Back', callback_data: 'main' }]];
    break;
  default:
    text = 'Unknown action';
}

const payload = {
  chat_id: cq.message.chat.id,
  text,
  reply_markup: keyboard ? { inline_keyboard: keyboard } : undefined
};

return [{ json: { body: JSON.stringify(payload) } }];
  • Update in place: instead of a new message per tap, call editMessageText with the same message_id — the menu redraws itself in the same bubble, and the user never scrolls through a stack of old menus.
  • The full pattern: the official dynamic menus template on n8n.io implements this exact switch-case structure with a rating system on top.
ℹ️
Pressed a button and the bot "thinks" forever? That's the un-answered callback query — Telegram keeps the spinner until you call answerCallbackQuery. Sending a new message does NOT close it (I learned that the hard way). The template in section 8 answers every callback automatically, so your users never see the spinner.

6. Find Any Chat ID (The #1 Question)

Every send needs a destination. Here's the complete map, because "what's my chat ID?" is the most-asked Telegram question in existence:

1

Your own ID — 10 seconds

Open a chat with @userinfobot or @RawDataBot and press Start. They reply with your numeric ID instantly.

2

Group / channel ID — the API way

Add your bot to the group (or channel, as admin), send any message there, then open this URL in a browser:

https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates

Find the latest update and read message.chat.id. Group and channel IDs are negative (like -1001234567890) — copy the minus sign too, or you'll get "chat not found" and blame the bot.

💡
Public channels accept their @username as the chat ID directly — the one case where you don't need the number at all.

7. Groups & Channels

  • Groups: add the bot via the group's "Add member" menu. If the bot must read all messages (moderation, logging), recall section 2: /setprivacy → Disable.
  • Channels: add the bot as an administrator — without admin rights it can't post. Use the channel's negative ID or public @username as the destination.
  • Posting rights: "Not enough rights to send" errors mean the bot is a plain member or lacks the posting permission — check the channel's administrator list.
  • Rate limits: Telegram throttles bots at ~1 message/second per chat and ~20/minute per group. Batch sends need a Wait node between messages — or Telegram will drop them silently.

8. Free Template: The Importable Command Bot

Everything above, assembled into one production-ready bot: /start sends a welcome with an inline keyboard, /help lists commands, button presses are answered and their spinner is closed properly, and anything else is echoed. Five nodes, no credentials beyond Telegram.

{
  "name": "Telegram Command Bot",
  "nodes": [
    {
      "parameters": {
        "updates": ["message", "callback_query"],
        "additionalFields": {
          "download": true
        }
      },
      "id": "trigger",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1.1,
      "position": [250, 300],
      "credentials": {
        "telegramApi": {
          "id": "YOUR_TELEGRAM_CREDENTIAL_ID"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const item = $input.item.json;\nconst isCallback = Boolean(item.callback_query);\n\nconst chatId = isCallback\n  ? item.callback_query.message.chat.id\n  : (item.message?.chat?.id || 0);\nconst text = isCallback\n  ? item.callback_query.data\n  : (item.message?.text || '');\nconst firstName = isCallback\n  ? item.callback_query.from.first_name\n  : (item.message?.from?.first_name || 'there');\nconst callbackQueryId = isCallback ? item.callback_query.id : '';\n\nlet reply;\nlet keyboard = null;\n\nif (isCallback) {\n  reply = `Button pressed: ${text}`;\n} else if (text === '/start') {\n  reply = `Welcome, ${firstName}! I am your n8n-powered bot.`;\n  keyboard = {\n    inline_keyboard: [\n      [{ text: '✅ Get Started', callback_data: 'started' }],\n      [{ text: '❓ Help', callback_data: 'help' }, { text: '🌐 Website', url: 'https://triggerworkflow.com' }]\n    ]\n  };\n} else if (text === '/help') {\n  reply = 'Commands:\\n/start — welcome + menu\\n/help — this list\\nAnything else is echoed back.';\n} else {\n  reply = text || 'Send /help for commands.';\n}\n\nconst payload = { chat_id: chatId, text: reply };\nif (keyboard) { payload.reply_markup = keyboard; }\n\nreturn [{ json: { isCallback, chatId, reply, callbackQueryId, body: JSON.stringify(payload) } }];"
      },
      "id": "parse",
      "name": "Parse & Decide",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [450, 300]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "c1",
              "leftValue": "={{ $json.isCallback }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "if-callback",
      "name": "Callback?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [650, 300]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_TOKEN }}/answerCallbackQuery",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\"callback_query_id\": \"{{ $json.callbackQueryId }}\", \"text\": \"Done ✅\"}",
        "options": {}
      },
      "id": "answer-cb",
      "name": "Answer Callback",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [850, 200]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_TOKEN }}/sendMessage",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ $('Parse & Decide').item.json.body }}",
        "options": {}
      },
      "id": "http-send",
      "name": "Send Reply (Bot API)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1050, 300]
    }
  ],
  "connections": {
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Parse & Decide",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse & Decide": {
      "main": [
        [
          {
            "node": "Callback?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Callback?": {
      "main": [
        [
          {
            "node": "Answer Callback",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Reply (Bot API)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Answer Callback": {
      "main": [
        [
          {
            "node": "Send Reply (Bot API)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true
  }
}
  • The token stays secret: both raw API calls read it from the TELEGRAM_TOKEN environment variable (set it once in your compose file, section 5.2) — nothing sensitive sits inside the workflow, and the template contains no real token.
  • Want Markdown instead of plain text? add parse_mode: 'HTML' to the payload in the Code node and use <b>bold</b> tags.
  • More ready-to-import blueprints live in our n8n Workflow Templates Library.

9. Telegram as Your Alert Hub

The bot is nice. The alert hub is where Telegram earns its keep: a fixed chat ID (yours, from section 6) and every workflow on your server can reach your pocket in seconds.

  • Error alerts: route your Error Trigger workflow's critical branch to Telegram — our n8n Error Handling guide builds exactly this, with severity-based routing.
  • Downtime alerts: the Website Downtime Checker template ends in a Telegram node — your site goes down, your phone buzzes before your users notice.
  • Daily digests: a scheduled workflow that sums up yesterday's numbers and sends one morning message beats a dashboard nobody opens.
  • Incoming webhooks from anywhere: any external service can POST to an n8n Webhook node that forwards to Telegram — see What is a Webhook if the concept is new.

10. Webhooks vs Polling: Which One to Use

The Telegram Trigger works over a webhook: on activation, n8n registers itself with Telegram, and Telegram pushes every update to your WEBHOOK_URL — which means n8n must be reachable through a public HTTPS address. Not every host can do that. Here is the honest comparison:

Webhook (Telegram Trigger)Polling (community node)
How it worksTelegram pushes updates to n8nn8n pulls updates via getUpdates on an interval
RequirementsPublic HTTPS URL (WEBHOOK_URL set)Nothing — works behind CGNAT, on a LAN, without a domain
LatencyNear-instantSlight delay (the polling interval)
Best forProduction bots on a real VPS + domainDevelopment, home servers, ISPs that block port 443
  • Stuck behind CGNAT or a home network? Install @mentoster/n8n-nodes-telegram-polling from Settings → Community Nodes — it adds a Telegram Trigger (long polling) node that works anywhere, no public URL needed.
  • Switching between the two: while a webhook is set, getUpdates returns nothing. To go back to polling, delete the webhook first (Telegram's deleteWebhook endpoint).
  • Need a public URL temporarily? A Cloudflare Tunnel or ngrok exposes your local n8n in minutes — useful for testing webhook bots before you buy a domain.
  • Rule of thumb: one bot, one consumer. Never run the webhook trigger and a polling trigger on the same bot at once.

11. Sending Files, Photos & Videos

Text is the start, not the end. Three patterns cover 95% of media use:

  • Send a photo by URL: the Telegram node's Send Photo operation accepts a direct URL in the photo field — no download step needed.
  • Send a file from your workflow: connect a node that produces binary data (HTTP download, Google Drive) and pass it to Send Document. Enable download on the trigger to receive files users send you — they arrive as binary data, ready for Drive, S3, or Sheets.
  • Send a batch as one album: Telegram groups up to 10 photos/videos into a single media group via sendMediaGroup:
// Build a media group — up to 10 items, one message
const urls = ['https://example.com/a.jpg', 'https://example.com/b.jpg'];
const media = urls.map((u, i) => ({
  type: 'photo',
  media: u,
  caption: i === 0 ? 'Batch report' : undefined
}));
return [{ json: { body: JSON.stringify({ chat_id: CHAT_ID, media }) } }];
// POST https://api.telegram.org/bot{{ $env.TELEGRAM_TOKEN }}/sendMediaGroup

12. Retries, Rate Limits & Long Messages

Three production realities every bot hits sooner or later:

12.1 Retry transient failures

Network blips (ECONNRESET, timeouts) are normal. On the Telegram or HTTP Request node, enable Retry On Fail with 3 tries and a short wait — that alone clears most flaky sends. Full resilience patterns live in the n8n Error Handling guide.

12.2 Respect the rate limits

Telegram throttles bots to roughly 1 message per second per chat (and ~30 per second globally). Batch broadcasts need a Wait node (0.6–1.2 s) between sends — otherwise Telegram silently drops the extras.

12.3 Split long messages (4096-char limit)

Telegram rejects messages over 4096 characters. Split before sending:

// Split long text under Telegram's 4096-character limit
const MAX = 4000;
const chunks = [];
for (let i = 0; i < text.length; i += MAX) {
  chunks.push(text.slice(i, i + MAX));
}
return chunks.map(c => ({ json: { chatId, text: c } }));

13. Community Nodes Worth Installing

The built-in nodes cover most needs. Two verified community nodes fill the real gaps:

PackageWhat it addsInstall
@mentoster/n8n-nodes-telegram-pollingA Telegram Trigger (long polling) node — bots without a public URLSettings → Community Nodes
@topvisor/n8n-nodes-telegram-send-message-customSend messages with raw JSON reply_markup through your telegramApi credentialSettings → Community Nodes
⚠️
Community nodes are third-party code that runs with your credentials' permissions. Verify the package name in the registry before installing, prefer maintained packages, and never run unknown nodes in production without a test first.

14. Real-World Builds

  • AI support bot: Telegram Trigger → AI Agent node — answers come from your LLM with the conversation as context. Add memory to make it remember users across sessions.
  • Rating system: buttons rate_1…rate_5 → append to Google Sheets — the official dynamic menus & rating template on n8n.io demonstrates the full switch-case pattern.
  • Task manager: a personal bot as the front end to Airtable or Supabase — add, list, and complete tasks from any chat, no app install.

15. Security Checklist

  • ✅ Token only in the n8n credential — never in shared JSON, logs, or screenshots
  • ✅ For raw Bot API calls (HTTP Request nodes), pass the token via the TELEGRAM_TOKEN environment variable — never hardcode it in node fields
  • ✅ /setjoingroups → Disable for personal alert bots
  • ✅ /setcommands keeps the bot's surface predictable — unknown commands fall through to your default reply
  • ✅ Webhook workflows that feed Telegram should check a secret header or path token (our webhook guides cover this)
  • ✅ If the token leaks: /revoke in BotFather, then update the n8n credential — two minutes, total reset
  • ✅ Store the bot's chat IDs you trust in a Code node list — don't let any webhook spam your phone

16. The 8 Most Common Errors & Fixes

#Error / SymptomCauseFix
1 Trigger never fires — bot is silent Workflow not activated, wrong token, or the bot was never added to the group Activate the workflow, re-check the credential, add the bot to the chat
2 Bot ignores normal group messages BotFather privacy mode is ON — the bot only sees mentions and commands /setprivacy → Disable in BotFather (section 2, step 2)
3 Forbidden: bot was blocked by the user The user blocked the bot; your broadcast keeps hitting the dead ID Skip that ID in your send loop — and prune blocked IDs from your list regularly
4 Bad Request: chat not found Wrong chat ID, missing minus sign on group IDs, or bot not a member Re-check the ID with getUpdates (section 6) and bot membership
5 409 Conflict: terminated by other getUpdates request Two processes polling the same bot (two n8n instances, or another bot app) One bot = one polling consumer. Deactivate the duplicate workflow or app
6 Bot replies with literal {{ $json... }} text Expression field missing the leading = Start the field with = (section 4 callout)
7 Buttons do nothing when pressed The trigger isn't listening for callback_query updates Add callback_query to the trigger's updates list (section 4)
8 Not enough rights to send ... Bot is not an admin (channels) or lacks posting rights Promote the bot in the channel's administrators list (section 7)
ℹ️
Silent failures again? Route your Telegram workflows through an Error Trigger so a dead bot alerts you on another channel — the Error Handling guide shows the setup.

17. Frequently Asked Questions

How do I connect n8n to a Telegram bot?

Create a bot with BotFather to get the token, add a Telegram credential in n8n with that token, then use the Telegram Trigger node to receive updates and the Telegram node to send messages (sections 2–4).

Why is my n8n Telegram trigger not working?

The five usual causes: the workflow is not activated, the bot token is wrong, the bot was never added to the group, BotFather privacy mode hides group messages, or another process is polling the same bot (409 Conflict). Section 16 covers each.

How do I find my Telegram chat ID?

Message @userinfobot or @RawDataBot for your personal ID. For groups and channels: add the bot, send a message, then open api.telegram.org/bot<TOKEN>/getUpdates and read chat.id — group and channel IDs are negative numbers (section 6).

Can n8n send messages to Telegram groups and channels?

Yes. Add the bot to the group (privacy mode off if it must read messages) or as a channel administrator, then use the negative chat ID. Public channels accept their @username as the destination (section 7).

How do inline keyboard buttons work in n8n?

You send a reply_markup with an inline_keyboard array — each button carries a callback_data or url. The Telegram Trigger must listen for callback_query updates, which arrive with the callback data when a user presses a button (section 5).

Can I run two n8n instances with the same Telegram bot?

Not with polling. Telegram allows only one active getUpdates consumer per bot — a second instance gets a 409 Conflict and one of them silently stops receiving updates. Point one bot at one n8n instance.

Is my Telegram bot token a secret?

Yes — anyone with the token controls your bot. Keep it in the n8n credential, never in shared workflow JSON or screenshots, and /revoke it in BotFather if it ever leaks (section 3).

Can n8n send photos and files to Telegram?

Yes. The Telegram node supports Send Photo, Send Video, Send Audio, and Send Document operations — attach files from previous nodes or send them by URL (section 1).

How do I use Telegram as an alert channel for my workflows?

Add a Telegram sendMessage node at the end of any workflow, or route your Error Trigger workflow's critical branch to Telegram for every failure. A fixed chat ID turns Telegram into your personal notification center (section 9).

Does the n8n Telegram Trigger need a public HTTPS URL?

Yes. The Telegram Trigger works over a webhook — on activation n8n registers itself with Telegram, so n8n must be reachable through a public HTTPS address. Behind CGNAT or without a domain, install the long-polling community node instead (section 10).

How do I send messages longer than 4096 characters?

Telegram rejects messages over 4096 characters. Split the text into chunks of about 4000 characters before sending, one sendMessage call per chunk — the ready-to-copy snippet is in section 12.3.


Sources & References

Explore More Guides

Ahmed Ayari — TriggerWorkflow The bot in section 8 is the one that runs TriggerWorkflow.com's own alerts — same trigger, same keyboard pattern, same two-hour lesson about BotFather privacy mode baked into section 2. Every error in section 16 is one I've hit, fixed, and written down so you don't have to. Read more guides by Mr.Ayari
Comments