Ссылка на профиль Telegram по ID: tg://user?id= в Telegraf
Почему tg://user?id= не работает для ссылок на профиль других пользователей в Telegram ботах на Telegraf. Ограничения API, альтернативы: t.me/username, text_mention, deep links и примеры кода.
Можно ли отправить в сообщении бота ссылку на профиль другого пользователя по его Telegram ID (tg://user?id=…)? Использую telegraf, отправляю так:
bot.command('profile', async ctx => {
await ctx.reply(
`<a href="tg://user?id=12345">Профиль</a>`,
{ parse_mode: 'HTML' }
);
});
Это работает только если указан id текущего аккаунта — для других пользователей ссылка не открывается. Как правильно сформировать ссылку на профиль по id, чтобы она работала для других пользователей, или есть ли ограничения Telegram/клиентов, из-за которых это невозможно? Какие альтернативы существуют (username, t.me/username, deep link и т.п.)?
Короткий ответ: нет — отправить надёжную публичную ссылку на профиль другого пользователя только по его числовому Telegram ID (tg://user?id=…) нельзя: клиенты Telegram в большинстве случаев игнорируют такой deep‑link, а он применяется в ограничённых сценариях Bot API. В Telegraf вместо этого используйте публичный username (https://t.me/username / tg://resolve?domain=…), или — если username отсутствует — создавайте внутри чата кликабельное упоминание через Bot API (MessageEntity type text_mention) либо отправляйте контакт / просите пользователя поставить username.
Содержание
- Ссылка на профиль по ID (tg://user?id=…)
- Почему это не работает для других пользователей
- Альтернативы: t.me/username и deep links
- Упоминание по ID в Bot API / Telegraf (text_mention)
- Практические советы и примеры кода для Telegraf
- Источники
- Заключение
Ссылка на профиль по ID (tg://user?id=…)
Ваш пример кода:
bot.command('profile', async ctx => {
await ctx.reply(
`<a href="tg://user?id=12345">Профиль</a>`,
{ parse_mode: 'HTML' }
);
});
Работает ли это? Частично — но не так, как вы, возможно, ожидаете. Официальная документация по deep links описывает разные схемы (t.me/…, tg://resolve?.. и т.п.), и отмечает, что поведение схем вроде tg://user?id=… ограничено и не гарантируется клиентами на всех платформах — такие ссылки в ряде случаев игнорируются клиентом и не открывают профиль другого пользователя https://core.telegram.org/api/links. Обсуждения разработчиков показывают, что tg://user?id= чаще используется в контексте Bot API для внутренних упоминаний, но не служит универсальной публичной ссылкой на профиль https://stackoverflow.com/questions/40048452/telegram-bot-how-to-mention-user-by-its-id-not-its-username. Практические статьи и генераторы ссылок подчёркивают, что для браузера и большинства клиентов надёжнее использовать https://t.me/username или tg://resolve?domain=username https://umnico.com/blog/telegram-link-generator/.
Почему это не работает для других пользователей
Коротко — потому что такое поведение заложено в реализации клиентов и в API:
- Клиенты (особенно web/desktop) часто игнорируют
tg://user?id=…или не интерпретируют его как публичную ссылку. В мобильном приложении поведение тоже неоднородно. tg://user?id=не создаёт «публичную» человечески-читаемую ссылку вида t.me/username — это внутренний deep‑link, и он не предназначен для массового внешнего распространения. См. документацию по deep links https://core.telegram.org/api/links.- Для безопасности и приватности Telegram не даёт простой универсальной привязки «по id → публичная страница», если у пользователя нет username. Numeric ID не заменяет публичное имя.
- Отсюда наблюдаемое вами поведение: ссылка может работать для аккаунта, к которому привязана сессия (то есть вы «открываете себя»), но не для произвольного третьего пользователя.
Резюмируя: по ID создать кросс‑платформенную кликабельную ссылку на профиль — нельзя. Лучше ориентироваться на username или на упоминания внутри чата.
Альтернативы: t.me/username и deep links
Самая простая и надёжная альтернатива — ссылка по username:
- Публичный профиль: https://t.me/username — работает во всех клиентах и в браузере.
- Внутри приложения можно использовать tg://resolve?domain=username, но https://t.me/… более кросс‑платформенный.
Пример для Telegraf (если у пользователя есть username):
// самый надёжный вариант — https://t.me/username
bot.command('profile', async ctx => {
const username = 'targetusername'; // достаёте заранее
await ctx.replyWithHTML(`<a href="https://t.me/${username}">Открыть профиль</a>`);
});
Или через inline-кнопку (удобно в ботах):
const { Markup } = require('telegraf');
bot.command('profile', async ctx => {
const username = 'targetusername';
await ctx.reply('Профиль:', Markup.inlineKeyboard([
Markup.button.url('Открыть в Telegram', `https://t.me/${username}`)
]));
});
Если username отсутствует — публичной ссылки нет. Есть редкие «временные/спец» ссылки (вроде некоторых contact‑link flows), но они используются в узких сценариях и не являются заменой t.me для общего доступа https://umnico.com/blog/telegram-link-generator/.
Упоминание по ID в Bot API / Telegraf (text_mention)
Что делать, если у пользователя нет username, но вам нужно сделать кликабельное упоминание внутри чата? Bot API поддерживает сущность MessageEntity типа text_mention, которая создаёт кликабельное упоминание и «связывает» текст с User‑объектом (в интерфейсе это выглядит как ссылка на профиль внутри Telegram). Ограничения:
- Бот должен иметь User‑объект целевого пользователя (обычно это возможно, если пользователь писал боту или находится в том же чате).
- Это не даёт внешней публичной URL — упоминание работает внутри сообщений Telegram.
Пример (через bot.telegram.sendMessage):
const name = 'Иван Иванов';
await bot.telegram.sendMessage(ctx.chat.id, name, {
entities: [
{
type: 'text_mention',
offset: 0,
length: name.length,
user: { id: 12345, is_bot: false, first_name: 'Иван' }
}
]
});
Важно: если бот не может подтвердить User (пользователь никогда не взаимодействовал с ботом и не в чате), сервер может не принять такого «вручную подставленного» User‑объекта или упоминание не будет работать как ссылка. Обсуждение этого подхода есть в сообществе разработчиков https://stackoverflow.com/questions/40048452/telegram-bot-how-to-mention-user-by-its-id-not-its-username.
Практические советы и примеры кода для Telegraf
Что рекомендую делать в рабочем боте:
- Храните username, когда пользователь взаимодействует с ботом. Тогда вы сможете генерировать
https://t.me/usernameдля внешних ссылок. - Для пользователей без username используйте внутри чата
text_mention, но учитывайте, что это работает только при наличии User‑объекта. - Если нужно поделиться контактной информацией — отправляйте
sendContact(ctx.replyWithContact) с номером телефона (если он у вас есть и пользователь разрешил). Это не профиль, но рабочая альтернатива. - Не пытайтесь «форсить» tg://user?id для внешних ссылок — это ненадёжно и будет ломаться на большинстве клиентов.
Конкретный пример: комбинированный обработчик
bot.command('profile', async ctx => {
const userId = 12345; // ваш id цели
const username = await lookupUsernameById(userId); // ваша логика БД / кэш
if (username) {
// Надёжный вариант — публичный t.me
return ctx.replyWithHTML(`<a href="https://t.me/${username}">Открыть профиль</a>`);
}
// Попробуем создать text_mention (если у бота есть информация о user)
const displayName = 'Пользователь';
try {
await bot.telegram.sendMessage(ctx.chat.id, displayName, {
entities: [{
type: 'text_mention',
offset: 0,
length: displayName.length,
user: { id: userId, is_bot: false, first_name: displayName }
}]
});
} catch (e) {
// fallback: простое уведомление
await ctx.reply('Профиль недоступен: у пользователя нет username, а упоминание невозможно.');
}
});
Небольшая ремарка: вместо ручной подстановки user можно пытаться вызвать Bot API методы (например, getChat(user_id)), но такие вызовы работают только если бот имеет доступ к информации о пользователе (пользователь взаимодействовал с ботом или находится в том же чате). Проверяйте ответы API и обрабатывайте ошибки.
Источники
- Официальная документация по deep links в Telegram: https://core.telegram.org/api/links
- Обсуждение поведения tg://user?id на Stack Overflow: https://stackoverflow.com/questions/40048452/telegram-bot-how-to-mention-user-by-its-id-not-its-username
- Практическая заметка и генератор ссылок (сразбором типов ссылок): https://umnico.com/blog/telegram-link-generator/
Заключение
tg://user?id=… не даёт универсальной публичной ссылки на профиль другого пользователя — клиенты Telegram и Bot API применяют такие схемы в ограничённом контексте, и поведение нестабильно. Для внешних ссылок используйте https://t.me/username (или tg://resolve?domain=... внутри приложения). Если у пользователя нет username, от вас остаются два реалистичных пути: упоминание внутри чата через text_mention (требует наличия User‑объекта) или отправка контакта/запрос на установку username. В Telegraf проще и надёжнее опираться на username и хранить его, когда пользователь взаимодействует с ботом.