Rich-сообщения и разметка
С июня 2026 года Telegram поддерживает rich-сообщения: заголовки, таблицы, списки, сворачиваемые блоки, медиа внутри текста и кнопки между абзацами.
Режим и синтаксис
У каждого шаблона есть режим и синтаксис. Значения по умолчанию задаются для чата в разделе «Общие», у отдельного шаблона их можно поменять в редакторе.
| Rich (по умолчанию) | Text | |
|---|---|---|
| Что это | Rich-сообщение Telegram | Классическое сообщение |
| Длина | До 32 768 символов | До 4096 символов, подпись к медиа — до 1024 |
| Элементы | Все из каталога ниже | Строчное форматирование, цитаты, блоки кода, одно медиа. Остальное упрощается |
| Кнопки | Под сообщением и внутри текста | Только под сообщением |
| Синтаксис | Что это |
|---|---|
| Markdown (по умолчанию) | Rich Markdown Telegram: совместим с GitHub Flavored Markdown и допускает HTML-вставки |
| HTML | Rich HTML Telegram: теги из каталога ниже. Неизвестный тег — ошибка invalid_markup |
Где режим не выбирается
Некоторые тексты Telegram всегда показывает без разметки: всплывающие уведомления на нажатие кнопки (до 200 символов), описания команд в меню, надписи на кнопках, вопросы и варианты опросов.
Порядок обработки
- Движок выполняет островки
{{ }},{% %},{# #}и получает строку разметки. - Значения из данных при подстановке экранируются под синтаксис шаблона.
- В режиме Rich строка уходит в Telegram, и он сам разбирает разметку. В режиме Text бот переводит ее в классический формат.
Поэтому в статическом тексте шаблона вы пишете разметку свободно, а данные подставляете через {{ }} или функции разметки.
Строчная разметка
| Элемент | Markdown | HTML | Функция | В режиме Text |
|---|---|---|---|---|
| Жирный | **т**, __т__ | <b>, <strong> | bold(t) | жирный |
| Курсив | *т*, _т_ | <i>, <em> | italic(t) | курсив |
| Подчеркнутый | <u>т</u> | <u>, <ins> | underline(t) | подчеркнутый |
| Зачеркнутый | ~~т~~ | <s>, <strike>, <del> | strike(t) | зачеркнутый |
| Спойлер | ||т|| | <tg-spoiler> | spoiler(t) | спойлер |
| Маркер | ==т== | <mark> | mark(t) | жирный |
| Верхний индекс | <sup>т</sup> | <sup> | sup(t) | как есть |
| Нижний индекс | <sub>т</sub> | <sub> | sub(t) | как есть |
| Моноширинный | `т` | <code> | code(t) | моноширинный |
| Ссылка | [т](https://…) | <a href="…"> | link(t, url) | ссылка |
| Почта, телефон | [т](mailto:…), [т](tel:…) | <a href="mailto:…"> | link(t, url) | ссылка |
| Упоминание | [т](tg://user?id=…) | <a href="tg://user?id=…"> | mention(member), {{ member }} | ссылка |
| Кастомный эмодзи |  | <tg-emoji emoji-id="…"> | custom_emoji(id, запасной) | так же |
| Дата у зрителя |  | <tg-time unix="…" format="…"> | datetime(value, format) | так же |
| Формула | $x^2$ | <tg-math> | math(expr) | моноширинный исходник |
| Сноска | текст[^1] и [^1]: … | <a href="#1"> и <tg-reference name="1"> | — | «[1]» и тексты сносок в конце |
| Якорь | <a name="x"></a>, [т](#x) | то же | anchor(name) | пропадает |
| Кнопка в строке | <tg-button …> | <tg-button type style …> | inline_button(…) | уходит в клавиатуру |
__текст__ — жирный
В Telegram __текст__ делает текст жирным, а не подчеркнутым. Для подчеркивания пишите <u>…</u>. Редактор подсказывает такие места.
Блоки
| Элемент | Markdown | HTML | Функция | В режиме Text |
|---|---|---|---|---|
| Заголовок 1–6 | # … ###### | <h1> … <h6> | heading(t, size) | жирная строка |
| Абзац | пустая строка | <p> | — | абзац |
| Блок кода | ```lang | <pre><code class="language-lang"> | pre(t, lang) | блок кода |
| Цитата | > т | <blockquote>…<cite>автор</cite> | quote(t, credit) | цитата |
| Раскрывающаяся цитата | — | <blockquote expandable> | quote(t, credit, true) | раскрывающаяся цитата |
| Выноска | — | <aside>…<cite> | pullquote(t, credit) | цитата |
| Разделитель | --- | <hr/> | divider() | строка ——— |
| Подвал | — | <footer> | footer(t) | курсивная строка |
| Список | - т, * т, + т | <ul><li> | list(items) | строки • т |
| Нумерованный список | 1. т | <ol start type reversed> | list(items, 'ordered') | строки 1. т |
| Чек-лист | - [ ] т, - [x] т | <li><input type="checkbox" checked> | checklist(items) | строки ☐ т / ☑ т |
| Таблица | | a | b | + строка |---| | <table bordered striped compact>, <caption>, <th>, <td colspan rowspan align> | table(rows, opts) | моноширинная таблица |
| Сворачиваемый блок | <details><summary>…</summary> | то же | details(summary, content) | раскрывающаяся цитата с жирным заголовком |
| Формула-блок | $$…$$ | <tg-math-block> | math_block(expr) | блок кода |
| Ряд кнопок | — | <tg-button-row align> | button_row(buttons, align) | кнопки уходят в клавиатуру |
В ячейках таблицы работает только строчная разметка. В таблице — до 20 столбцов.
Медиа
| Элемент | Markdown | HTML | Функция |
|---|---|---|---|
| Фото |  | <img>, <figure>…<figcaption> | photo(url, caption, spoiler) |
| Видео, GIF |  | <video> | video(…), animation(…) |
| Аудио, голосовое |  | <audio> | audio(…), voice(…) |
| Документ |  | <tg-document> | document(url, caption) |
| Коллаж | <tg-collage>…</tg-collage> | то же | collage(media, caption) |
| Слайдшоу | <tg-slideshow>…</tg-slideshow> | то же | slideshow(media, caption) |
| Карта | — | <tg-map lat long zoom/> | map(lat, long, zoom, caption) |
- Медиа подключаются только по ссылке
https://. Тип Telegram определяет сам по ссылке и содержимому. - Медиа в rich-сообщении — отдельный блок, не внутри абзаца.
- У бота должно быть право отправлять медиа в чат, иначе сообщение не отправится, а ошибка попадет в диагностику.
- Загрузки файлов в панели нет: используйте ссылки на картинки, размещенные в интернете.
# Итоги недели
{{ photo('https://example.com/week.jpg', 'Лучший матч недели') }}
{{ collage([photo('https://example.com/1.jpg'), photo('https://example.com/2.jpg')], 'Скриншоты участников') }}Флаги сообщения
| Флаг | Что делает |
|---|---|
| Справа налево (RTL) | Rich-сообщение для языков с письмом справа налево |
| Не превращать ссылки автоматически | Telegram не будет сам делать ссылками адреса, @username, #хэштеги, $тикеры, /команды, телефоны и номера карт |
Флаги задаются переключателями в редакторе шаблона.
Режим Text
В режиме Text бот сам упрощает то, что классическое сообщение показать не может:
| Rich | Text |
|---|---|
| Заголовок | Жирная строка |
| Списки | Строки с • или 1. |
| Чек-лист | Строки с ☐ и ☑ |
| Таблица | Моноширинный текст с выровненными столбцами |
| Сворачиваемый блок | Раскрывающаяся цитата с жирным заголовком |
| Разделитель | Строка ——— |
| Подвал | Курсивная строка |
| Маркер | Жирный |
| Формула | Моноширинный исходник |
| Первое медиа | Медиа сообщения |
| Остальные медиа | Ссылки |
| Коллаж, слайдшоу | Первое медиа |
| Карта | Ссылка на карту |
| Кнопки в тексте | Кнопки под сообщением |
| Сноски | «[n]» и тексты сносок в конце |
| Якоря | Удаляются |
Если есть медиа, а текст длиннее 1024 символов, бот отправит медиа без подписи и текст вторым сообщением.
Экранирование
Все, что выводится через {{ }}, экранируется под синтаксис шаблона:
- HTML —
&,<,>,"заменяются на сущности; - Markdown — перед знаками разметки ставится обратный слэш,
<заменяется на<.
Благодаря этому имя участника *Анна* будет показано со звездочками, а не курсивом, и не сломает остальное сообщение.
Не экранируются:
- результаты функций разметки:
bold,link,table,photo,mention…; - объекты с собственным видом: участник выводится упоминанием.
Ловушки Markdown
В трех местах подстановка через {{ }} может сломать разметку, и редактор предупреждает об этом (markdown_context_escape):
| Где | Используйте вместо |
|---|---|
Внутри строки таблицы | {{ x }} | | table() или table_of() |
Внутри ссылки [текст]({{ url }}) | link(текст, url) |
В атрибутах HTML-тегов <img src="{{ url }}"> | photo(url) |
Безопасные ссылки
Ссылки из данных допускаются только со схемами https, http, tg, mailto, tel. Любые другие (например, javascript:) бот отбрасывает, а функция выводит просто текст. Медиа — только https.
Лимиты
| Режим | Лимиты итогового сообщения |
|---|---|
| Rich | До 32 768 символов (с учетом текста эмодзи и исходников формул), до 500 блоков (включая вложенные, пункты списков и строки таблиц), вложенность до 16, до 50 медиа, до 20 столбцов в таблице, 1–8 кнопок в ряду внутри текста |
| Text | До 4096 символов, подпись к медиа — до 1024 |
Бот проверяет лимиты до отправки. Если сообщение не помещается, вызвавший получит ошибку message_too_long или rich_limit_exceeded.
Сборка сообщения из кода
Для сложных случаев сообщение можно собрать методами и отправить из шаблона:
{% do chat.createMessage()
.heading('Турнир клуба', 2)
.paragraph('Регистрация открыта до пятницы.')
.photo('https://example.com/tournament.jpg')
.footer('Удачи!')
.send() %}