Back to Blog

How to Export Telegram Group Members to CSV (Step-by-Step Guide)

May 10, 2026·

Open the group in Telegram Web, run the extension, and get a CSV of names, usernames, user IDs and roles — no bot, no code.

This is the Telegram Scraper extension — install it here.

If you've landed here, you probably want one thing: a clean CSV of the members of a Telegram group, ready to drop into a spreadsheet, a CRM, or an analysis script. Good news — that's a 60-second job once you pick the right tool. Bad news — Google is full of tools that promise more than Telegram actually allows, and a few that will quietly route your data through someone else's server.

This guide covers three methods that respect Telegram's API boundaries: a manual approach for tiny groups, a Python script for technical users, and a browser extension for everyone in between. If you want the short path, the Telegram group member export runs on Telegram Web and writes CSV directly — there is a 3-minute walkthrough on YouTube showing it with no bot and no code. Pick before you scroll.

Method comparison — pick before you scroll

Method Setup time Group-size ceiling Coding required Privacy
Manual copy 0 min ~50 members No Local
Telethon (Python) 30–60 min Unlimited Yes Local
Mastros extension 2 min Unlimited No Local
Cloud scraper SaaS 5 min Unlimited No Their servers

Most readers want method 3. Method 2 is the right answer if you're going to do this on a recurring schedule with custom shaping. Method 1 is for the founders chat. Cloud scrapers are an anti-pattern; we'll get to why.

Spreadsheet view of an exported member list

What "exporting members" actually means

Before you wire up a single tool, get the vocabulary right. Telegram "member export" isn't a single button — it's shorthand for pulling the participant list of a chat you're already in, with whatever fields Telegram's API has decided to expose for that chat.

What you reliably get: display name, @username (when set), numeric user ID, role (member / admin / creator), join date when the API surfaces it, and bio. What's gated: phone numbers (only visible to your contacts), last-seen timestamps (privacy-toggled by each user), and anything inside private supergroups you don't belong to.

If a tool promises "all phone numbers, all groups, no membership required," close the tab. That's scraping someone else's data through someone else's server, and you're going to inherit their problems — legal, ethical, and operational.

TOS and the access boundary

Telegram's terms allow you to use the API to access data your account already has access to. The line is membership: a group you're in, fine; a group you're not, off-limits. Every legitimate method below respects that line.

This is a feature, not a limitation. The reason Telegram's API ecosystem is so mature — Telethon, Pyrogram, GramJS, every third-party client — is that the platform draws a clear line and lets developers do anything inside it. The trade is honored on both sides.

Method 1 — Manual copy (only for tiny groups)

Open the group in Telegram Desktop, click the header, scroll the member list, select all, copy. You get names — no IDs, no usernames, no role. This works for a 12-person founders chat. It does not work for a 4,000-person community.

Time to pull 50 members: 90 seconds. Time to pull 4,000: don't. If you're under 50, this is the right call — no installs, no credentials, no learning curve. Above that, Telegram Desktop won't even render the full list at once; it lazy-loads as you scroll, and select-all gives you a partial result without warning.

Method 2 — Python + Telethon

If you're comfortable with a terminal, Telethon gives you the most control. You'll need API credentials from my.telegram.org — register an "application," copy the api_id and api_hash, and keep them in a .env file you don't commit.

Then about 30 lines of code:

from telethon.sync import TelegramClient
from telethon.tl.functions.channels import GetParticipantsRequest
from telethon.tl.types import ChannelParticipantsSearch
import csv

api_id   = 1234567
api_hash = 'YOUR_HASH'
target   = 'your_group_username'  # or chat ID

with TelegramClient('session', api_id, api_hash) as client:
    offset, all_users = 0, []
    while True:
        chunk = client(GetParticipantsRequest(
            channel=target,
            filter=ChannelParticipantsSearch(''),
            offset=offset, limit=200, hash=0))
        if not chunk.users:
            break
        all_users.extend(chunk.users)
        offset += len(chunk.users)

    with open('members.csv', 'w', newline='', encoding='utf-8-sig') as f:
        w = csv.writer(f)
        w.writerow(['id','username','first_name','last_name','phone','bio'])
        for u in all_users:
            w.writerow([u.id, u.username or '', u.first_name or '',
                        u.last_name or '', u.phone or '', ''])

The first run prompts for your phone number and a verification code; Telethon writes a session file so subsequent runs are silent. Watch out for FloodWaitError on groups over ~10K — Telegram throttles fast pulls. Add a time.sleep(2) between batches and you're fine. For groups over ~100K, page through ChannelParticipantsSearch with rotating prefixes ('a', 'b', …) since the API caps a single search at 10,000 results.

Pyrogram is a credible alternative; the code shape is similar. Use whichever your team already knows.

Method 3 — Mastros (browser extension, no code)

Install the Telegram Scraper, open Telegram Web, navigate to the group, click Export. The extension reads the same structured data a Python script would pull from the API, but through the Telegram Web session you're already signed into. No credentials to register or manage, no servers to trust, no Python environment to maintain — and no setup step at all.

Output is the same CSV shape as the script above, plus role and join date, and Mastros writes UTF-8 with BOM by default so Excel doesn't mangle non-Latin scripts or emoji.

If you need to export multiple groups, queue them and the extension batches them with built-in dedupe across files — useful when the same user is in three of your communities and you want one row per person, not three.

A note on the cloud-scraper category: services that ask you for a phone number, log into your Telegram account on their server, pull the data, and email you a file are doing exactly what an extension does — but on a box you don't control. If they get breached, your account session lives in someone else's logs. Pass.

What the CSV actually looks like

Here's the header row Mastros produces:

user_id,username,first_name,last_name,role,join_date,bio,phone,is_premium,is_bot

Quick notes on each column:

  • user_id — numeric, stable, the only field you should join on. Usernames change.
  • username — without the @. Empty for users who haven't set one.
  • rolecreator, admin, or member. Useful for segmenting moderators out.
  • join_date — ISO 8601. Often empty in groups that pre-date Telegram's tracking.
  • bio — quoted, with newlines flattened to spaces.
  • phone — usually empty. Only populated when both you and the user have each other in contacts.
  • is_premium / is_bot — booleans. Strip bots from your audience analysis.

UTF-8 with BOM. Bios with commas are quoted. Newlines inside bios are escaped, not preserved — spreadsheets hate raw newlines in cells.

Multi-group batch extraction with dedupe

If you run several communities, you'll end up wanting one master list, deduplicated by user_id, with a column noting which group(s) each person belongs to. Mastros has this built in: select multiple groups in the queue, choose "merge with source tag," and the output adds a groups column with comma-separated group names per row.

The Python equivalent: pull each group to its own CSV, then in pandas:

import pandas as pd, glob

dfs = [pd.read_csv(f).assign(group=f.replace('.csv','')) for f in glob.glob('*.csv')]
all_rows = pd.concat(dfs)
merged = (all_rows.groupby('user_id')
          .agg(username=('username','first'),
               first_name=('first_name','first'),
               groups=('group', lambda s: ','.join(sorted(set(s)))))
          .reset_index())
merged.to_csv('master.csv', index=False)

What to do with the file

You have a CSV. Now what?

Dedupe by user_id, never username. People rename themselves. The numeric ID is permanent for the lifetime of the account.

Segment by role. Moderators get different messaging than members. Strip bots before any audience analysis.

Enrich against your CRM by handle. If you've got a HubSpot or Notion list with Telegram handles in a column, an xlookup against the export tells you which community members are already in your funnel.

If you're running outreach, throttle hard and respect bios that say "no DMs." The cheapest way to burn a community is to treat the export as a lead list. The members didn't opt in to your sales motion when they joined the group — they opted into the topic. Cold-DM at scale and you'll be banned by both Telegram and the community itself within a week.

Push to your warehouse. For ongoing analytics, the right pattern is: weekly Mastros export → object store → dbt model → BI tool. The CSV is a serializable handoff between Telegram and the rest of your stack; treat it like any other source data.

A note on what Telegram doesn't expose

You will never get, through any legitimate method:

  • Phone numbers of users who don't share contacts with you.
  • Direct messages of users you haven't messaged with.
  • Users from groups you aren't a member of.
  • Activity logs ("X was last active at Y") for users who hide their last-seen.

Tools that claim otherwise are either lying or doing something Telegram will eventually shut them down for. Build on the legitimate surface and your pipeline keeps working when the next privacy crackdown lands.


Try it → Install the Telegram Scraper free, export your first group in under two minutes, and pipe it straight into your spreadsheet, CRM, or warehouse. Free for groups under 5K members.

FAQ

Can I export members from a Telegram group I'm not in?

No. Telegram's API only exposes data your account already has access to, and membership is the line: a group you're in is fine, a group you're not in is off-limits. Every legitimate method respects that boundary. Any tool promising "all groups, no membership required" is either lying or routing your credentials through someone else's server.

Does the export include phone numbers?

Usually not. The phone column exists, but it is only populated when you and that user have each other saved as contacts — that is a Telegram privacy rule, not a tool limitation. The same applies to last-seen timestamps, which each user can hide.

How many members can I export at once?

Manual copy tops out around 50 before Telegram Desktop's lazy-loading gives you a partial list without warning. Telethon and the Mastros extension are both unlimited, but Telethon throttles with FloodWaitError on groups over ~10K (add a short sleep between batches), and a single participant search caps at 10,000 results — above ~100K you page through with rotating letter prefixes.

Do I need Telegram API credentials to export members?

Only for the Python route. Telethon needs an api_id and api_hash registered at my.telegram.org. The Mastros browser extension needs neither — it reads through the Telegram Web session you are already signed into, so there is nothing to register, store, or rotate.

Will Excel mangle non-Latin names and emoji in the CSV?

No. The file is written as UTF-8 with a BOM, which is what tells Excel to decode it correctly. Bios containing commas are quoted, and newlines inside bios are flattened to spaces because spreadsheets handle raw newlines in cells badly.

Should I dedupe the list by username or user ID?

Always by user_id. It is numeric and stable for the lifetime of the account, whereas people rename themselves and usernames get reused. Username is for display; the ID is the only field you should join on.

Related reading