Telegram Bot API
🌐 Русский

Как отправить сообщение через бота Telegram: sendMessage, разметка и кнопки

· 8 мин чтения

Чтобы отправить сообщение через бота Telegram, достаточно одного HTTP-запроса к методу sendMessage: https://api.telegram.org/bot<token>/sendMessage с параметрами chat_id (кому) и text (что). Ниже — готовые примеры на curl, Python и JavaScript, форматирование через parse_mode (HTML и MarkdownV2), inline-кнопки, отправка в группы и каналы и разбор ошибок, которые чаще всего возвращает Telegram Bot API.

Как отправить сообщение через бота: формат запроса

Любой метод Telegram Bot API вызывается по адресу https://api.telegram.org/bot<token>/ИМЯ_МЕТОДА. Обратите внимание: слово bot пишется слитно с токеном. Поддерживаются GET и POST, а параметры можно передать в query string, как application/x-www-form-urlencoded, application/json или multipart/form-data (последний нужен для загрузки файлов).

У sendMessage два обязательных параметра:

Ответ всегда приходит в JSON: при успехе — "ok": true и отправленное сообщение (объект Message) в поле result, при ошибке — "ok": false, error_code и description. И главное ограничение: бот не может написать пользователю первым. Человек должен сам открыть бота и нажать «Старт» (/start).

Отправка сообщения через curl

Самый быстрый способ проверить, что всё работает. Подставьте свой токен и chat id:

TOKEN="123456789:AAEexampleTokenReplaceWithYours"

curl -s -X POST "https://api.telegram.org/bot$TOKEN/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{"chat_id": 123456789, "text": "Привет! Это сообщение отправлено через Bot API"}'

Успешный ответ (сокращённо):

{
  "ok": true,
  "result": {
    "message_id": 42,
    "chat": {"id": 123456789, "first_name": "Иван", "type": "private"},
    "date": 1793275200,
    "text": "Привет! Это сообщение отправлено через Bot API"
  }
}

Если параметров немного, можно обойтись без JSON — curl сам закодирует кириллицу и спецсимволы:

curl -s "https://api.telegram.org/bot$TOKEN/sendMessage" \
  -d chat_id=123456789 \
  --data-urlencode "text=Сборка #512 прошла успешно"

Пример на Python (requests)

import requests

TOKEN = "123456789:AAEexampleTokenReplaceWithYours"
API_URL = f"https://api.telegram.org/bot{TOKEN}"


def send_message(chat_id, text, **params):
    payload = {"chat_id": chat_id, "text": text, **params}
    resp = requests.post(f"{API_URL}/sendMessage", json=payload, timeout=10)
    data = resp.json()
    if not data["ok"]:
        raise RuntimeError(f"{data['error_code']}: {data['description']}")
    return data["result"]


msg = send_message(123456789, "Привет из Python!")
print("message_id:", msg["message_id"])

Функция возвращает объект Message: message_id пригодится, чтобы потом отредактировать или удалить сообщение. Дополнительные параметры передаются именованными аргументами, например send_message(chat_id, text, parse_mode="HTML").

Пример на JavaScript (fetch)

// Node.js 18+: fetch встроен. Запуск: BOT_TOKEN=... node send.mjs
const TOKEN = process.env.BOT_TOKEN ?? '123456789:AAEexampleTokenReplaceWithYours';

async function sendMessage(chatId, text, extra = {}) {
  const res = await fetch(`https://api.telegram.org/bot${TOKEN}/sendMessage`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ chat_id: chatId, text, ...extra }),
  });
  const data = await res.json();
  if (!data.ok) throw new Error(`${data.error_code}: ${data.description}`);
  return data.result;
}

const msg = await sendMessage(123456789, 'Привет из JavaScript!');
console.log('message_id:', msg.message_id);

Этот код заработает и в браузере, но в продакшене так делать нельзя: токен во фронтенде увидит любой посетитель. Отправку держите на сервере, а токен — в переменных окружения.

parse_mode HTML: жирный текст, ссылки и код

Чтобы оформить текст, передайте "parse_mode": "HTML". Telegram понимает ограниченный набор тегов:

curl -s -X POST "https://api.telegram.org/bot$TOKEN/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": 123456789,
    "parse_mode": "HTML",
    "text": "<b>Заказ №1024 оплачен</b>\nСумма: <code>1 990 ₽</code>\n<a href=\"https://example.com/orders/1024\">Открыть заказ</a>"
  }'

Все символы <, > и &, которые не входят в тег, нужно заменить на &lt;, &gt; и &amp;. Из именованных HTML-сущностей API понимает только эти три и &quot;, плюс любые числовые. Пользовательский ввод экранируйте всегда:

import html

name = "<Иван & Ко>"  # пришло от пользователя
text = f"Новый заказ от <b>{html.escape(name, quote=False)}</b>"
send_message(123456789, text, parse_mode="HTML")

MarkdownV2 в Telegram: синтаксис и экранирование

MarkdownV2 компактнее HTML: *жирный*, _курсив_, __подчёркнутый__, ~зачёркнутый~, ||спойлер||, `код`, [ссылка](https://example.com), а строки, начинающиеся с >, превращаются в цитату. Подвох — в экранировании: вне разметки каждый из символов _ * [ ] ( ) ~ ` > # + - = | { } . ! нужно предварять обратным слешем \, иначе API вернёт ошибку разбора. Сам \ тоже экранируется. Внутри `кода` и блоков ``` экранируются только ` и \, а внутри круглых скобок ссылки — ) и \.

import re

def escape_md2(text: str) -> str:
    return re.sub(r"([_*\[\]()~`>#+\-=|{}.!\\])", r"\\\1", text)

price = "1.990 руб. (скидка -10%)"
send_message(123456789, f"*Итого:* {escape_md2(price)}", parse_mode="MarkdownV2")
# уйдёт текст: *Итого:* 1\.990 руб\. \(скидка \-10%\)

На JavaScript это одна строка:

const escapeMd2 = (s) => s.replace(/[_*[\]()~`>#+\-=|{}.!\\]/g, '\\$&');

Старый режим Markdown оставлен только для обратной совместимости: в нём нет подчёркивания, зачёркивания, спойлеров и цитат. Для новых ботов выбирайте HTML или MarkdownV2, а если текст приходит от пользователей, HTML обычно надёжнее — экранировать нужно всего три символа.

Inline-кнопки: reply_markup с url и callback_data

Кнопки под сообщением задаются параметром reply_markup с полем inline_keyboard — это массив рядов, а каждый ряд — массив кнопок. Кнопка с url открывает ссылку, кнопка с callback_data присылает боту апдейт callback_query.

{
  "chat_id": 123456789,
  "text": "Подтвердите заказ №1024",
  "reply_markup": {
    "inline_keyboard": [
      [{"text": "Открыть сайт", "url": "https://example.com"}],
      [
        {"text": "Подтвердить", "callback_data": "confirm:1024"},
        {"text": "Отменить", "callback_data": "cancel:1024"}
      ]
    ]
  }
}

Как отправить сообщение в группу или канал

curl -s "https://api.telegram.org/bot$TOKEN/sendMessage" \
  -d chat_id=@my_channel \
  --data-urlencode "text=Новый пост в канале"

Тихие сообщения, превью ссылок и ответы

{
  "chat_id": 123456789,
  "text": "Ночной отчёт готов: https://example.com/report",
  "disable_notification": true,
  "link_preview_options": {"is_disabled": true},
  "protect_content": true,
  "reply_parameters": {"message_id": 42}
}

Частые ошибки sendMessage и что с ними делать

ОшибкаПричинаЧто делать
400 Bad Request: chat not foundНеверный chat_id, пользователь не запускал бота, бота нет в группе или каналеПроверьте id через getUpdates, добавьте бота в чат
400 Bad Request: can't parse entitiesОшибка разметки: неэкранированный символ MarkdownV2 или незакрытый тегЭкранируйте текст, проверьте теги
400 Bad Request: message is too longТекст длиннее 4096 символовРазбейте его на несколько сообщений
401 UnauthorizedНеверный или отозванный токенПроверьте токен через getMe
403 Forbidden: bot was blocked by the userПользователь заблокировал ботаИсключите его из рассылки
403 Forbidden: bot can't initiate conversation with a userПользователь ни разу не запускал ботаПопросите его нажать «Старт»
429 Too Many Requests: retry after NПревышен лимит частотыПодождите retry_after секунд и повторите

Так выглядит ответ с ошибкой 429:

{"ok": false, "error_code": 429, "description": "Too Many Requests: retry after 7", "parameters": {"retry_after": 7}}

Подробно о лимитах и о том, как делать рассылки без 429, — в гайде лимиты Telegram Bot API.

Попробуйте sendMessage без кода

  1. Откройте Bot API Tester на форме sendMessage.
  2. Вставьте токен бота. Если токена ещё нет, поможет гайд как получить токен бота.
  3. Заполните chat_id и text, при желании выберите parse_mode и добавьте reply_markup.
  4. Нажмите Ctrl+Enter: в ответе появится message_id или текст ошибки.

Полное описание всех параметров метода — на странице sendMessage.

Частые вопросы

Как отправить сообщение через бота телеграм без библиотек?

Отправьте HTTP-запрос на https://api.telegram.org/bot<token>/sendMessage с параметрами chat_id и text. Подойдёт curl, requests в Python или fetch в JavaScript — SDK для этого не нужен.

Почему бот не может написать пользователю первым?

Так устроен Telegram: бот не может начать диалог сам. Пользователь должен открыть бота и нажать «Старт» — до этого sendMessage будет возвращать ошибку 403.

Какие символы нужно экранировать в MarkdownV2?

Вне разметки — _ * [ ] ( ) ~ ` > # + - = | { } . ! и сам обратный слеш: перед каждым из них ставится \. Иначе Telegram вернёт ошибку 400 о том, что не может разобрать сущности.

Как отправить сообщение в канал через бота?

Сделайте бота администратором канала с правом публикации и укажите в chat_id @username канала. Для приватного канала используйте числовой id вида -1001234567890.

Что выбрать для parse_mode: HTML или MarkdownV2?

Для текста от пользователей надёжнее HTML: экранировать нужно только <, > и &. MarkdownV2 компактнее, но требует экранировать 18 спецсимволов.

Что делать при ошибке 429 Too Many Requests?

Подождать столько секунд, сколько указано в parameters.retry_after, и повторить запрос. Чтобы не ловить 429, держите темп не выше 1 сообщения в секунду в один чат и около 30 сообщений в секунду суммарно.

Как создать бота в Телеграм: от @BotFather до первого сообщения

Как создать бота в Телеграм: регистрация в @BotFather, токен, проверка через getMe, первое сообщение на curl и Python, команды и описание бота.

Что нового в Telegram Bot API 10.0–10.3: rich-сообщения, эфемерные сообщения и гостевой режим

Что нового в Telegram Bot API 10.0–10.3: rich-сообщения, эфемерные сообщения, гостевой режим, заявки на вступление — с примерами и чек-листом миграции.

Лимиты Telegram Bot API: сообщения в секунду, ошибка 429 и размеры файлов

Все лимиты Telegram Bot API в одном месте: сообщения в секунду, ошибка 429 и retry_after, платные рассылки, размеры файлов, длина текста и подписи.

Токен бота Telegram: как получить, где найти, как проверить и отозвать

Как получить токен бота Телеграм в @BotFather, где взять токен уже созданного бота, как проверить его через getMe и что делать, если токен утёк.

Вебхук для Telegram-бота: настройка setWebhook, проверка и удаление

Как настроить вебхук Телеграм-бота: требования к HTTPS и портам, setWebhook с secret_token, проверка через getWebhookInfo, удаление и частые ошибки.

Как узнать chat id в Telegram: пользователь, группа, канал и тема форума

Как узнать chat id в Telegram через getUpdates: личный чат, группа, супергруппа, канал и тема форума. Форматы id с -100 и что делать с пустым result.

Тестирование Telegram Mini App: от браузера до отладки на телефоне

Тестирование Telegram Mini App по шагам: mock-режим в браузере, HTTPS-туннель для localhost, тестовая среда, DevTools на телефоне и проверка initData.