How it works

Walking message ids

A bot cannot ask Telegram “give me my last N messages” the way a user client can. What it can do is fetch messages by id with messages.getMessages. So the dumper walks the id space in batches (200 by default), fetching each batch and writing out whatever comes back. Ids that were never used, or whose messages were deleted or expired, come back as MessageEmpty and are skipped.

  • Upwards (default) starts at id 1 and climbs. Simple, but it burns through long runs of empty low ids on a busy bot.

  • Downwards (--down) first probes for the highest live id (trying powers of 10 up to 10⁹), then walks down from there. Far more productive on an active bot.

An all-empty batch normally ends the walk. --lookahead N keeps it scanning N more batches past the gap, for histories that are sparse but not finished.

Note

Telegram does not keep bot history forever. Empirically only the last few hundred thousand messages stay reachable — in testing a busy bot exposed roughly the last 500K before messages.getMessages returned only MessageEmpty for older ids. If a bot has processed more traffic than that, the older history is gone server-side and no flag will bring it back.

Resolving users

For every message, the dumper resolves the other party’s profile — for incoming messages and for the bot’s outgoing replies — via users.getFullUser, saving the profile and (unless --no-photos) their avatars. Each user is resolved once per run.

Groups and privacy mode

messages.getMessages only returns the bot’s private message history. Basic-group and supergroup history needs per-channel calls that bots generally can’t make, so it is not dumped by the id walk.

Groups are reachable live instead. If the bot has been added to a group or supergroup and its privacy mode is disabled, it receives all group messages — not just commands and replies — and --listen-only captures them in real time. With privacy mode enabled (the default) the bot only sees commands, mentions, and replies. Group messages in the history are tagged [from:USER][group:CHAT] (see Output layout).

Known limits

  • A run can stop before the history is fully dumped. A batch that comes back entirely empty — because users deleted their messages, or because old ids were pruned server-side — can end the walk early. Raise --lookahead to scan past empty stretches, or prefer --down, which is much less affected by gaps.

  • Group / supergroup *history* is not dumped, only captured live (see above).