01Location
- /data/data/org.telegram.messenger/files/cache4.db (+ cache4.db-wal, cache4.db-shm)
- /data/data/org.telegram.messenger/files/account<N>/cache4.db (additional accounts)
02Questions it answers
- Which dialogs (users, groups, channels, secret chats) exist in the local cache?
- Which messages were cached, in which direction and with which read state?
- When did message status or dialog activity last change according to the cache?
03Format and versions
| Format | SQLite in WAL mode; current source opens it with PRAGMA secure_delete = ON. Tables include messages_v2 (mid, uid, read_state, send_state, date, data BLOB, out, ttl, media …), dialogs (did, date, unread_count, last_mid, inbox_max, outbox_max, pinned …), users, chats, enc_chats and contacts. BLOBs hold Telegram objects in binary TL serialisation, each starting with a 32-bit constructor. |
|---|---|
| Applies to | Anglano et al. (2017) studied Telegram 3.15–3.18, when the table was named messages; current open-source code creates messages_v2 and sets LAST_DB_VERSION 179. Secondary accounts use files/account<N>/. |
04Key fields
| Field | What it tells you |
|---|---|
| messages_v2.uid | Dialog id (DID) the message belongs to. |
| messages_v2.out | 1 if the message was sent by the user, 0 if received. |
| messages_v2.read_state / send_state | In the 2017 study: read_state 2 delivered-not-read, 3 delivered-and-read; send_state 0 sent, 1 pending. |
| messages_v2.data | Serialized Message object (text, media, action, from/to ids). |
| dialogs | One row per conversation: last_mid (last sent or received message), unread_count (received but unread). |
| enc_chats | Secret chats; the dialog id is enc_chats.uid shifted left by 32 bits. |
| users / chats / contacts | Serialized user and chat objects; contacts.mutual = 1 if the local user is also in the contact's list. |
05Timestamps
| Field | Encoding | Note |
|---|---|---|
| messages_v2.date | Unix epoch, seconds | Described in the 2017 study as the last modification of the message status, not necessarily the send time; e.g. 1491738135 = 2017-04-09 11:42:15 UTC. |
| dialogs.date | Unix epoch, seconds | Time of the last operation in the conversation (sending, reception, deletion, etc.). |
Decode raw values with the Timestamp decoder and convert local wall-clock times with the Local time to UTC.
06Examination workflow
- Collect cache4.db with its -wal/-shm files for every account folder.
- Record the schema version and actual table names before querying.
- Decode data BLOBs with a TL-aware parser matched to the app version.
- Link messages to dialogs, users and chats; flag secret-chat dialog ids.
07Interpretation pitfalls
- cache4.db is a client cache of cloud data; absence of a message locally does not mean it never existed.
- The 2017 study recovered deleted records until VACUUM; current code enables secure_delete, which zeroes deleted content.
- Column semantics come from a study of older versions; re-validate on the version under examination.
09Sources
- Forensic analysis of Telegram Messenger on Android smartphones (Digital Investigation 23, 2017, author copy) C. Anglano, M. Canonico, M. Guazzone · checked 2026-10-14
- Telegram for Android — MessagesStorage.java Telegram (DrKLO/Telegram on GitHub) · checked 2026-10-14
- Telegram for Android — gradle.properties (APP_PACKAGE) Telegram (DrKLO/Telegram on GitHub) · checked 2026-10-14
- SQLite — PRAGMA statements (secure_delete) SQLite · checked 2026-10-14
- SQLite — Write-Ahead Logging SQLite · checked 2026-10-14