What the Telegram node can do
| Operation | What it does |
|---|---|
| Send Message | Send text (Markdown/HTML), reply keyboards, inline keyboards |
| Send Photo / Audio / Document / Video / Sticker | Send binary media from upstream nodes |
| Edit Message | Update a previously sent message in-place |
| Delete Message | Remove a message from a chat |
| Pin / Unpin Chat Message | Pin or unpin a message |
| Get Chat / Get Chat Members Count | Inspect chat metadata |
| Answer Inline Query | Respond to inline @bot queries |
| Answer Callback Query | Acknowledge inline keyboard button presses |
| Set Chat Description / Title | Manage group metadata |
| Send Location / Venue / Contact | Send structured location or contact data |
The Telegram Trigger node listens for: messages, edited messages, callback queries (inline keyboard presses), inline queries, channel posts, and more.
Setting up credentials
- Open Telegram and message @botfather.
- Run
/newbot, follow the prompts, and copy your bot token (format:1234567890:ABCdef...). - In n8n: Settings → Credentials → New → Telegram API.
- Paste the token. Save.
Getting the chat ID:
- For a private chat: message your bot, then call
https://api.telegram.org/bot<TOKEN>/getUpdates— thechat.idis in the response. - For a group: add your bot to the group, send a message, then check getUpdates — group IDs are negative numbers (e.g.
-100123456789). - For channels: use
@channelusername(the public handle) or the numeric ID.
Telegram Trigger node
The Trigger fires your workflow on inbound events. Key configuration:
| Field | Notes |
|---|---|
| Credential | Same bot token as above |
| Updates | Select which event types trigger the workflow: message, callback_query, inline_query, etc. Select only what you need — every update type adds webhook overhead |
| Additional Fields → Allowed Updates | Fine-grained filter; leave blank to receive all selected types |
Accessing trigger data:
// The incoming message text
{{ $json.message.text }}
// The chat ID to reply to
{{ $json.message.chat.id }}
// Callback query data (from inline keyboard button press)
{{ $json.callback_query.data }}
// The sender's username
{{ $json.message.from.username }}
Gotcha — webhook vs polling: n8n uses webhooks by default. Your n8n instance must be reachable over HTTPS (public URL or a tunnel). If you're running n8n locally without a tunnel, the Trigger won't receive updates. Use ngrok or similar to expose the webhook endpoint during development.
Send Message operation
The most-used operation. Core fields:
| Field | Notes |
|---|---|
| Chat ID | Numeric ID, @channelusername, or expression from trigger data |
| Text | Supports Markdown and HTML (set Parse Mode accordingly) |
| Parse Mode |
Markdown, MarkdownV2, or HTML — pick one and be consistent |
| Reply To Message ID | Thread a reply to a specific message |
| Disable Notification | Silent push for non-urgent messages |
| Reply Markup | Attach an inline keyboard or reply keyboard |
MarkdownV2 gotcha: MarkdownV2 requires escaping special characters (-, ., (, ), !, etc.) with a backslash. If your text comes from dynamic expressions, escape it in a Code node first or use HTML parse mode instead — HTML is less brittle.
// Code node: escape text for MarkdownV2
const text = $input.first().json.rawText;
const escaped = text.replace(/([_*\[\]()~`>#+\-=|{}.!\\])/g, '\\$1');
return [{ json: { escapedText: escaped } }];
Inline keyboards (callback buttons)
Inline keyboards attach buttons directly to a message. When a user clicks a button, a callback_query event fires with the button's data payload.
Sending a message with inline keyboard:
Operation: Send Message
Reply Markup: Inline Keyboard
Inline Keyboard Buttons:
- Row 1:
- Text: ✅ Approve | Callback Data: approve_123
- Text: ❌ Reject | Callback Data: reject_123
Handling the callback in the Trigger:
// In the workflow triggered by callback_query:
Chat ID: {{ $json.callback_query.message.chat.id }}
Message ID: {{ $json.callback_query.message.message_id }}
Button pressed: {{ $json.callback_query.data }}
After handling the callback, always call Answer Callback Query with the callback_query_id to dismiss the loading spinner on the button:
Operation: Answer Callback Query
Callback Query ID: {{ $json.callback_query.id }}
Text: Done! (optional toast message shown to user)
Sending files (photos, documents, audio)
Use the binary-input operations. Feed binary data from an upstream node (HTTP Request, Read Files, etc.) into the Telegram node:
Operation: Send Document
Chat ID: {{ $json.chatId }}
Binary Data: true
Binary Property: data ← must match the binary field name from the upstream node
File Name: report.pdf
Caption: Your weekly report
Gotcha — file size limits: Telegram bots can send files up to 50 MB via the Bot API. For larger files, upload to a CDN first and send the URL instead (set Binary Data: false, provide a URL in the document field).
Gotchas & common errors
1. Chat not found / bot not in chat
The bot must have been added to the group/channel before it can send messages there. For channels, the bot needs to be an admin with post permission.
2. Message too long (400 Bad Request)
Telegram messages have a 4096 character limit. For longer output, split with a Code node or send as a document.
3. Flood control (429)
Telegram rate-limits at ~30 messages/second globally and ~1 message/second per chat. For bulk sends, add a Wait node (1s delay) between messages or use a Split in Batches node.
4. Webhook conflict
If you test locally and then deploy to production, old webhook registrations can conflict. Call https://api.telegram.org/bot<TOKEN>/deleteWebhook to clear stale registrations.
5. Callback query timeout
Telegram shows a loading spinner on button presses for up to 10 seconds. Always answer callback queries promptly — if your workflow takes longer, answer immediately with a "processing…" text and update the message when done.
6. HTML parse mode vs Markdown
<b>bold</b> and <i>italic</i> work reliably in HTML mode. Markdown mode silently ignores improperly escaped characters. Prefer HTML for dynamic content.
3 workflow patterns
Pattern 1: Approval bot
Webhook (form submission / external event)
→ Telegram (Send Message with inline keyboard: Approve / Reject buttons)
→ [wait for callback_query trigger]
→ Switch (route on callback data: approve_* / reject_*)
→ Telegram (Edit Message: update to "✅ Approved by @username")
→ Notion / Airtable / Spreadsheet (update record status)
→ Telegram (Send confirmation to submitter chat)
Use case: expense approvals, content moderation, PR review notifications — any human-in-the-loop decision you want to route through chat.
Pattern 2: Scheduled digest bot
Schedule Trigger (every morning 08:00)
→ HTTP Request / Spreadsheet / Notion (fetch today's data)
→ Code node (format as HTML: bold headers, list items)
→ Telegram Send Message (Parse Mode: HTML)
Chat ID: -100[group_id] or personal chat
Use case: daily metrics digest, top-of-morning task list, monitoring alert summary.
Pattern 3: Command handler bot
Telegram Trigger (message events)
→ IF node: {{ $json.message.text.startsWith('/') }} = true
→ Switch node (route on command: /status, /report, /help)
→ Branch /status: fetch system metrics → Telegram reply
→ Branch /report: generate PDF → Telegram Send Document
→ Branch /help: Telegram reply with command list
Use case: ops bots, internal tooling bots, personal automation command center.
Free workflow JSON
Here's a starter approval-bot workflow — webhook receives a request, bot sends an inline keyboard to a Telegram chat, and the callback triggers an update:
{
"name": "Telegram Approval Bot Starter",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "approval-request",
"responseMode": "lastNode"
},
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [240, 300]
},
{
"parameters": {
"chatId": "={{ $json.body.chatId }}",
"text": "New approval request from {{ $json.body.requester }}:\n\n{{ $json.body.description }}",
"additionalFields": {
"parseMode": "HTML",
"replyMarkup": "inlineKeyboard",
"inlineKeyboard": {
"rows": [
{
"row": {
"buttons": [
{ "text": "✅ Approve", "callbackData": "approve_{{ $json.body.requestId }}" },
{ "text": "❌ Reject", "callbackData": "reject_{{ $json.body.requestId }}" }
]
}
}
]
}
}
},
"name": "Send Approval Request",
"type": "n8n-nodes-base.telegram",
"position": [460, 300]
},
{
"parameters": {
"updates": ["callback_query"]
},
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"position": [240, 500]
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.callback_query.data }}",
"operation": "startsWith",
"value2": "approve_"
}
]
}
},
"name": "Approved?",
"type": "n8n-nodes-base.if",
"position": [460, 500]
},
{
"parameters": {
"callbackQueryId": "={{ $json.callback_query.id }}",
"text": "Decision recorded!"
},
"name": "Answer Callback",
"type": "n8n-nodes-base.telegram",
"position": [680, 500]
}
],
"connections": {
"Webhook": { "main": [[{ "node": "Send Approval Request", "type": "main", "index": 0 }]] },
"Telegram Trigger": { "main": [[{ "node": "Approved?", "type": "main", "index": 0 }]] },
"Approved?": { "main": [[{ "node": "Answer Callback", "type": "main", "index": 0 }]] }
}
}
Import via Settings → Import from URL/Clipboard.
Next steps
- Pair with the n8n OpenAI node to build AI-powered Telegram bots
- Use the n8n Schedule Trigger for timed digest bots
- Add n8n Error Trigger to get Telegram alerts on workflow failures
- Browse the full n8n Workflow Starter Pack for pre-built automation patterns
What are you building with the Telegram node? Drop your bot idea or pattern in the comments.
Related Articles
- n8n Slack Node: Send Messages and Build Bot Workflows
- n8n AI Agent Node: Build Autonomous AI Workflows
- n8n HTTP Request Node: Advanced Patterns, Auth, and Pagination\n\n---\n\n*Free: n8n Integration Checklist*\n25 production checks before you ship any n8n workflow — credentials, error handling, dedup, and integration-specific gotchas.\n→ Get the free checklist
Want this built for you? I build production-ready n8n workflows for small businesses — fixed price, 48-hour turnaround, honest refund policy. See the service and get a quote → occelatus.io/automate
Top comments (1)
Are you using the Telegram node to build approval bots, scheduled digest bots, or command handlers in n8n? Drop your use case in the comments — would love to see what people are routing through Telegram.