CommunicationOS

Telegram·28 July 2026·7 min read·Adam Albastov

How to Export Telegram Chat History: Desktop, JSON and the API

Export Telegram chats from the desktop client, choose between HTML and JSON, work with the 24 hour security wait, and pull large supergroups through the MTProto API without tripping flood limits.

The short answer

Telegram Desktop is the only official client with a built-in export tool, and it writes your chats to HTML or JSON files. A first full-account export triggers a security delay before the download starts. A single chat exports straight away from the chat options menu. Large group histories and scheduled runs need a script written against the Telegram MTProto API, because the standard Bot API cannot read historical messages.

Export everything from Telegram Desktop

The desktop app on macOS, Windows, and Linux holds the export engine. The web client and the iOS and Android apps do not have the feature.

Download Telegram Desktop from desktop.telegram.org. Sign in with your phone number and complete the two-step verification code.

  1. Open the left sidebar menu and click Settings.
  2. Click Advanced.
  3. Scroll down the Advanced page and click Export Telegram data.
  4. Select the message types to include. Tick Personal chats, Bot chats, Private groups, Only my channels, Public groups, and Public channels according to what you need.
  5. Tick the media types to save. The options cover Photos, Video files, Voice messages, Video messages, Stickers, Animated GIFs, and generic Files.
  6. Set the size limit slider for downloaded media. The slider caps the size of one file, and the top of its range depends on your client version, so read what it says before you commit. Media above the value you pick is skipped, and the message text referring to it still lands in the export. That is how a transcript ends up full of attachments that are not there.
  7. Choose the export format at the bottom of the window: Human-readable HTML or Machine-readable JSON.
  8. Set the date range to limit how far back the export reaches. Leave it open for the full history.
  9. Choose an output folder on your local drive.
  10. Click Export.
Telegram Desktop Export Folder/
├── css/
├── js/
├── images/
├── video_files/
├── voice_messages/
├── chats/
│   ├── chat_01/
│   │   └── messages.html (or result.json)
│   └── chat_02/
└── export_results.html

The output folder holds the selected assets and an index file. With HTML selected, opening export_results.html in a browser shows the chat list with styling, avatars, and embedded media players. With JSON selected, Telegram writes a single result.json in the root folder holding the structured data for every selected chat.

Export one chat

A full account export covers every chat you tick and waits out the security delay described below. Export a single conversation when you only need the records from one client or one group.

  1. Open the direct message, group, or channel in Telegram Desktop.
  2. Click the three vertical dots in the top right corner of the chat window.
  3. Select Export chat history.
  4. Choose the media formats, size limits, and date range for this chat.
  5. Choose HTML or JSON.
  6. Click Export.

A single chat export runs immediately. It does not trigger the account-wide security delay that Telegram applies to full account dumps.

The 24 hour wait

Telegram blocks a first full-account export request made from a new desktop session.

The app shows a dialog saying the export was requested from a new device. Telegram sends a service notification to your active mobile sessions warning that data has been requested and that the export stays locked for 24 hours. The delay exists so that you can terminate a session you do not recognise.

Telegram Desktop settings and support tickets cannot bypass the delay. When historical records are wanted for a legal or operational deadline, request the export a day before you plan to download the files. Keep the desktop client installed and signed in while the timer runs. After the countdown expires, reopen Export Telegram data and trigger the export again to start the download.

HTML or JSON

Feature HTML export JSON export
Primary reader People, including legal reviewers Developers and ingestion pipelines
Media assets Linked locally for browser viewing Referenced by relative disk path
Scale Slow to search across many files Fast to index in a database
Script parsing Needs DOM parsing, such as BeautifulSoup Native deserialization
Output layout Split into numbered pages per chat Single file or structured objects
Legal review Layout matches the chat interface Raw data needs processing first

Run both formats in two passes when storage allows. The HTML build gives a reviewer an interface with context, and the JSON export feeds an analytics database or a search index.

What the JSON contains

The JSON export puts your conversations under a root object holding account metadata and an array of chat objects.

{
  "name": "Exported Data",
  "about": "Telegram personal data export",
  "chats": {
    "list": [
      {
        "name": "Northstar launch",
        "type": "private_group",
        "id": 1492049102,
        "messages": [
          {
            "id": 10420,
            "type": "message",
            "date": "2025-05-14T09:06:01",
            "date_unixtime": "1747206361",
            "from": "Maya Chen",
            "from_id": "user8912401",
            "text": "Legal needs another week. Please move the launch to Thursday, 12 June."
          },
          {
            "id": 10421,
            "type": "message",
            "date": "2025-05-15T11:32:45",
            "date_unixtime": "1747301565",
            "from": "Alder Studio",
            "from_id": "user4410924",
            "text": [
              "The new checklist is at ",
              {
                "type": "link",
                "text": "https://files.example.com/northstar/checklist-v3"
              },
              " with the date changed."
            ]
          }
        ]
      }
    ]
  }
}

The message body breaks naive parsing scripts. A plain-text message puts a string in the text field. A message holding links, mentions, bold formatting, code blocks, or emoji turns text into an array of mixed elements, where plain runs are strings and formatted runs are objects with a type and a text attribute. Every message also carries a text_entities array, which is always a list of objects, so reading from that field instead of text saves you the type check.

A script that expects text to be a string will crash on the first formatted message. Ingestion code has to inspect the type of the field before writing to a database.

Groups, supergroups and channels

Small groups behave differently from supergroups. Telegram publishes the limits: a basic group holds up to 200 people, and passing that limit, or enabling advanced permissions, upgrades the group into a supergroup with a capacity of up to 200,000 members.

A supergroup loads history from the server in pages, so a long-running supergroup means a long run of sequential requests. The desktop client slows while it works through the backlog, and the flood limits described below apply to the run.

Telegram channels allow unlimited subscribers and carry the same volume problem. On a public channel with a large media archive, the media download rather than the message text is what sets the length of the run.

Secret chats appear in no export. Telegram ties a secret chat to specific devices with end-to-end encryption over MTProto, and those messages never reach Telegram's cloud servers. Telegram Desktop does not support secret chats at all, so a desktop export job cannot include them.

Exporting through the API

Scheduled exports, continuous backups, and bulk extraction without manual clicks need the Telegram MTProto API.

The Bot API cannot do historical extraction. A bot created through BotFather receives only the messages sent after it joined the group, and it cannot query chat history from before its join date.

For complete history, create an MTProto user client:

  1. Log in to my.telegram.org with your phone number.
  2. Go to API development tools.
  3. Fill out the application form to generate an api_id and an api_hash.
  4. Install an MTProto client library in Python, such as Telethon or Pyrogram.

The script below uses Telethon to walk backward through a chat history and handle rate limit blocks:

import asyncio
import json
from telethon import TelegramClient
from telethon.errors import FloodWaitError
from telethon.tl.types import Message

api_id = 1234567
api_hash = 'your_api_hash_here'
chat_target = 'northstar_launch'

client = TelegramClient('export_session', api_id, api_hash)

async def dump_history():
    await client.start()
    chat = await client.get_input_entity(chat_target)
    records = []

    try:
        async for message in client.iter_messages(chat, limit=None):
            if isinstance(message, Message) and message.text:
                records.append({
                    "id": message.id,
                    "date": message.date.isoformat(),
                    "sender_id": message.sender_id,
                    "text": message.text
                })
    except FloodWaitError as err:
        print(f"Hit rate limit. Sleeping for {err.seconds} seconds.")
        await asyncio.sleep(err.seconds)

    with open("chat_dump.json", "w", encoding="utf-8") as f:
        json.dump(records, f, indent=2, ensure_ascii=False)

if __name__ == "__main__":
    with client:
        client.loop.run_until_complete(dump_history())

The script connects to Telegram as your own user account, walks every message in the named chat, and appends the text and sender IDs to a list before writing to disk.

Rate limits in practice

Telegram protects its servers with dynamic rate limits, known as flood limits, and publishes no fixed requests-per-second figure.

Passing the allowed rate raises a FloodWaitError carrying an integer. That integer is the number of seconds to wait before the next request.

A script that ignores the error and keeps calling the endpoint risks having its session deactivated or its phone number banned. Catch the exception in your network layer and pass the returned value straight into your sleep timer before resuming pagination.

For the same job on another platform, read the guide to Discord server exports.

Keeping the archive instead of exporting it

An exported folder is static. It does not change when a client revises terms, sends a follow-up document, or deletes a message in an active group thread.

Connecting your accounts to CommunicationOS keeps an index that updates as messages arrive, and Telegram sits in the same search as WhatsApp, Signal, Discord, and email. The JSON this article describes is also an input. Upload result.json with its media directories and those chats join the same index, so a supergroup you already paid the flood limits to extract does not have to be extracted a second time. You can run a data export when a legal team wants offline files, without a security lockout or a custom API script in the way. The pricing plans show what each tier indexes.

Bring your message history into one inbox

Connect an account for new messages, then upload an archive or authorise a supported migration for earlier history. Voice notes are transcribed and document text is read on the way in.

No card required. We reply with an onboarding slot and a connection guide.

Talk to us