Telegram Desktop
Media Cache
Overview
The Telegram Desktop media cache is the most forensically accessible artifact in a Telegram installation. When a user views or downloads photos, videos, voice messages, documents, or stickers in Telegram, the application writes these files to cache directories within tdata/user_data/. Unlike the rest of the tdata/ hierarchy — which is TDF$ encrypted and unreadable without the user's credentials — the cached media files are typically stored in their native binary format, directly readable with standard forensic tools.
This makes the media cache the primary source of message content evidence in a Telegram Desktop investigation. Even when TDF$ decryption is unavailable, an investigator can recover the photos and documents that a user received or sent, analyze their content, and use their timestamps to build a timeline.
Cache files have opaque hex-string filenames (e.g., a3f4b2c1d0e5f6a7) with no extensions. MIME type and media classification must be inferred from the file's magic bytes. macfor detects content type using the first 512 bytes of each file with Go's net/http.DetectContentType.
Cache Directory Locations
Primary Account (Account 1)
| Cache Location | Distribution | Path |
|---|---|---|
| Primary cache | Standalone | ~/Library/Application Support/Telegram Desktop/tdata/user_data/cache/ |
| Primary cache | App Store | ~/Library/Containers/ru.keepcoder.Telegram/Data/Library/Application Support/Telegram Desktop/tdata/user_data/cache/ |
| Media cache | Standalone | ~/Library/Application Support/Telegram Desktop/tdata/user_data/media_cache/ |
| Media cache | App Store | ~/Library/Containers/ru.keepcoder.Telegram/Data/Library/Application Support/Telegram Desktop/tdata/user_data/media_cache/ |
Additional Accounts
Telegram Desktop's multi-account support uses user_data#N/ directories for accounts 2 and 3 (and potentially beyond):
| Account | Cache Path (relative to tdata/) |
|---|---|
| Account 2 | user_data#2/cache/, user_data#2/media_cache/ |
| Account 3 | user_data#3/cache/, user_data#3/media_cache/ |
macfor checks all of these directories during collection.
Cache File Format
| Property | Details |
|---|---|
| Filename format | Opaque hex string, no extension (e.g., a3f4b2c1d0e5f6a7) |
| File format | Native binary format of the media (JPEG, PNG, MP4, PDF, OGG, etc.) |
| Encryption | Typically not encrypted — readable directly |
| Metadata | No embedded metadata within the cache filename |
Because filenames are opaque, the only way to determine what a cached file contains is to examine its content. Magic bytes at the start of the file identify the format.
MIME Type Detection
macfor reads the first 512 bytes of each cache file and passes them to net/http.DetectContentType to infer the MIME type. The detected MIME type is then used to classify the media into a category:
| Detected MIME Type | Media Type Classification |
|---|---|
image/* (e.g., image/jpeg, image/png, image/webp) | photo |
video/* (e.g., video/mp4, video/webm) | video |
audio/* (e.g., audio/ogg, audio/mpeg) | voice |
application/x-tgsticker | sticker |
application/* (e.g., application/pdf, application/zip) | document |
| Other / unrecognized | unknown |
Media Cache Record Fields
Each file in the media cache produces a telegram_media_cache record with the following fields:
| Field | Type | Description |
|---|---|---|
file_path | string | Full path to the cached file on the source system |
file_name | string | Base filename (opaque hex string) |
mime_type | string | Inferred MIME type from magic bytes |
size | integer | File size in bytes |
mod_time | string | Modification timestamp (RFC 3339) |
media_type | string | Classification: photo, video, voice, sticker, document, or unknown |
user | string | macOS username |
variant | string | "standalone" or "appstore" |
skipped | boolean (optional) | true if file was skipped due to size limit |
skip_reason | string (optional) | Reason for skipping (e.g., "exceeds 100 MB limit") |
Example records:
{
"file_path": "/Users/alice/Library/Application Support/Telegram Desktop/tdata/user_data/cache/a3f4b2c1d0e5f6a7",
"file_name": "a3f4b2c1d0e5f6a7",
"mime_type": "image/jpeg",
"size": 142688,
"mod_time": "2025-11-02T14:37:22Z",
"media_type": "photo",
"user": "alice",
"variant": "standalone"
}
{
"file_path": "/Users/alice/Library/Application Support/Telegram Desktop/tdata/user_data/cache/b8e2d4f1a7c3e059",
"file_name": "b8e2d4f1a7c3e059",
"mime_type": "application/pdf",
"size": 2097152,
"mod_time": "2025-10-29T09:12:44Z",
"media_type": "document",
"user": "alice",
"variant": "standalone"
}
{
"file_path": "/Users/alice/Library/Application Support/Telegram Desktop/tdata/user_data/cache/d9f1c3e2a4b5d6e7",
"file_name": "d9f1c3e2a4b5d6e7",
"mime_type": "application/octet-stream",
"size": 157286400,
"mod_time": "2025-11-10T18:05:31Z",
"media_type": "unknown",
"user": "alice",
"variant": "standalone",
"skipped": true,
"skip_reason": "exceeds 100 MB limit"
}
Size Limits and Collection Options
Media caches can grow very large. A user who has actively used Telegram for months may accumulate gigabytes of cached media. macfor enforces a configurable file size limit during media collection:
| Option | Default | Description |
|---|---|---|
skip_media_cache | false | When true, skips all media cache collection |
max_media_file_size_mb | 100 | Maximum file size in MB to collect; 0 = unlimited; -1 = unlimited |
Files that exceed the size limit are not copied into the evidence container, but a telegram_media_cache record is still emitted with skipped: true and the file path, size, and timestamps. This ensures the investigator knows large files exist even if they were not collected.
To collect all media regardless of size:
macfor-pro collect --plugin messaging.telegram \
--option max_media_file_size_mb=-1 \
--output ./evidence.zip
To skip media cache entirely (for a fast metadata-only collection):
macfor-pro collect --plugin messaging.telegram \
--option skip_media_cache=true \
--output ./evidence.zip
Evidence Container Layout
Collected media files are stored in the evidence container under:
artifacts/messaging.telegram/files/{username}/{variant}/
The directory structure mirrors the original path relative to the cache directory. Original filenames are preserved.
Forensic Analysis Notes
Timestamp significance: The modification timestamp on a cached media file records approximately when the file was last written to disk by Telegram Desktop. For received media, this approximates when the user viewed or downloaded the item. For photos taken and sent via Telegram, the modification time reflects when the file was written to cache — which may be after the send event.
Cache eviction: Telegram Desktop evicts old cache files when the cache exceeds internal size thresholds. Older files are deleted first. An absence of cached media does not prove no media was received — only that Telegram's cache manager has evicted it. The presence of cached media files proves the user was active on Telegram during the period covered by those timestamps.
Sticker and animated content: Sticker packs are cached as individual image or animation files. Large numbers of sticker files in the cache indicate active use of sticker packs, which are a Telegram-specific feature.
Document evidence: When a user receives a document (PDF, archive, executable) via Telegram, the file is cached in the media cache before or instead of the user's Downloads folder. Cached documents with suspicious MIME types (executables, archives, scripts) are of particular interest in malware delivery and data exfiltration investigations.
Voice messages: Voice messages appear as audio/ogg files (Telegram uses OGG/Opus encoding). Their presence indicates voice communication occurred on the device.
Cross-referencing with other artifacts: The modification timestamps on media cache files can be correlated with:
- Apple Messages or Mail timestamps for the same time period
- KnowledgeC application usage events for Telegram Desktop
- FSEvents entries recording file creation in the cache directories
macfor Collection
The media cache is collected by default as part of the messaging.telegram plugin.
# Default collection includes media cache
macfor-pro collect --plugin messaging.telegram --output ./evidence.zip
# Collect with no size limit
macfor-pro collect --plugin messaging.telegram \
--option max_media_file_size_mb=-1 \
--output ./evidence.zip
# Skip media cache for a faster metadata-only run
macfor-pro collect --plugin messaging.telegram \
--option skip_media_cache=true \
--output ./evidence.zip