tgs sources list#

Enumerate all Telegram dialogs in your account — channels, supergroups, groups, users, and bots.

Usage#

tgs sources list [flags]

Flags#

FlagShortTypeDefaultDescription
--typestring[](all)Filter by type: channel, supergroup, group, user, bot (repeatable, comma-separated)
--with-statsboolfalseFetch expensive metrics (total/24h/first messages + full info) for every returned source
--limit-lint0Max records to return (1-500, 0=all)
--cursorstringPagination cursor from previous response
--folderstring""Filter to chats inside this folder (id or name), archived chats included; incompatible with --cursor
--archivedboolfalseInclude archived dialogs (ignored when --folder is set — a folder already includes its archived chats)
--max-waitint60Max seconds to wait on FLOOD_WAIT
--no-cacheboolfalseDisable peer and stats caches
--profile-pstringAccount profile name

Profile resolution order when --profile is not set: TGS_PROFILE env -> .tgs.yaml file -> "default".

Examples#

List all dialogs:

tgs sources list

Filter to channels and supergroups only:

tgs sources list --type channel,supergroup

Fetch stats for every source (slower — ~4 API calls per source):

tgs sources list --with-stats

Include archived dialogs:

tgs sources list --archived

List only chats inside the “Crypto” folder (archived members included):

tgs sources list --folder Crypto

Paginate through a large account:

# First page
tgs sources list --limit 50

# Next page using the cursor from the previous response
tgs sources list --limit 50 --cursor "eyJvIjo1MCwiZCI6MH0"

Output#

Returns a JSON object with a sources array, a total count, a returned count, and a cursor for pagination.

{
  "sources": [
    {
      "id": -1001234567890,
      "type": "channel",
      "title": "Durov's Channel",
      "username": "durov",
      "access": "public",
      "members_count": 1234567,
      "verified": true,
      "unread_count": 0,
      "last_message": {"id": 4321, "date": "2026-05-28T08:15:00Z"}
    },
    {
      "id": -1009876543210,
      "type": "supergroup",
      "title": "Go Programming",
      "username": "golang",
      "access": "public",
      "members_count": 78432,
      "has_topics": true,
      "unread_count": 5,
      "last_message": {"id": 120450, "date": "2026-05-28T07:42:11Z"}
    }
  ],
  "total": 287,
  "returned": 2,
  "cursor": "eyJvIjo1MCwiZCI6MH0"
}

total is the unfiltered count (all dialogs in the folder(s) walked), while returned is len(sources) after --type filtering and --limit trimming. With a --type filter you’ll typically see returned < total.

When --with-stats is set, each source also includes a stats object:

{
  "stats": {
    "total_messages": 12345,
    "messages_24h": 3,
    "first_message": {"id": 1, "date": "2015-08-26T10:00:00Z"}
  }
}

Source fields#

FieldTypeNotes
idintTelegram peer ID (negative for channels/groups)
typestringOne of channel, supergroup, group, user, bot
titlestringDisplay name
usernamestringPublic username without @; omitted if not set
accessstringpublic or private; omitted for users
members_countintMember/subscriber count; omitted if unavailable
descriptionstringBio or about text; only present with full info
has_commentsboolChannel has a linked discussion group; only present if true
linked_chat_idintID of the linked discussion group; only present if applicable
creation_datestringRFC3339 UTC timestamp of when a chat/channel was created; only present for channels/groups with --with-stats or via inspect
invite_linkstringPrimary invite link; present when available
first_namestringUser/bot first name; omitted for channels/groups
last_namestringUser last name; omitted if unset
phonestringE.164 phone digits (no +); omitted unless contact-visible
verifiedboolOfficial verified account; only present if true
scamboolMarked as scam by Telegram; only present if true
fakeboolMarked as fake by Telegram; only present if true
restrictedboolRestricted in some regions; only present if true
restricted_reasonstringFree-form restriction reason; omitted if absent
deletedboolDeleted user account; only present if true
archivedboolDialog is archived; only present if true
pinnedboolDialog is pinned; only present if true
savedboolThis is Saved Messages; only present if true
gigagroupboolBroadcast group (gigagroup); only present if true
has_topicsboolSupergroup with forum topics; only present if true
unread_countintUnread message count (always present, including 0)
last_messageobject{id, date} of the most recent message
statsobjectPresent only when --with-stats is set
stats_errorstringShort Telegram error code (e.g. CHANNEL_PRIVATE) when stats fetch failed; omitted on success

The cursor field is omitted from the JSON entirely when there are no more results (it is not present with value ""). Iterate with jq -r '.cursor? // empty' to terminate the loop cleanly.

Performance note#

By default, tgs sources list is fast — it reads dialogs from your account list. Adding --with-stats triggers roughly 4 additional API calls per source: channels.getFullChannel / messages.getFullChat / users.getFullUser for the full info, messages.search for the total count, plus paginated messages.getHistory calls for the 24-hour count and the first message. For accounts with hundreds of dialogs the full run can take several minutes. Stats for inactive sources (last message older than 7 days) are cached on disk and reused across runs.

Stats accuracy#

  • total_messages is the server-reported message count for the dialog.
  • messages_24h walks recent history (up to ~1000 messages) and counts those within the last 24 h; hyper-active peers are capped at that walking limit.
  • first_message is best-effort — for broadcast channels Telegram’s API may return no oldest message, in which case the field is omitted.

See Also#