A backup that only restores inside an app is useful when you change phones. It
is much less useful when you need to search conversations, audit a date range,
prepare contact data, or feed a Dataset into Python.
For those jobs, the important question is not “Can I copy my Zalo account?” It
is: Which visible records do I need, and how do I export them with explicit
limits?
This guide covers four practical workflows: chat backup, contact export, group
roster, and a complete visible-account snapshot.
Disclosure: I built the Zalo Data Exporter used in this guide. If you sign
up or run it through links in this article, I may earn revenue from Apify at
no additional cost to you.
Choose one outcome, not every data type
| Goal | Preset | Main Dataset views |
|---|---|---|
| Back up accessible messages | conversationBackup |
Conversations, Messages |
| Export visible contacts | contactsAndProfiles |
Contacts and profiles |
| Export members from joined groups | groupRoster |
Groups, Group members, Profiles |
| Create one bounded visible-data snapshot | completeSnapshot |
All five record types |
Starting with one preset makes the first result faster to inspect and cheaper to
bound. A complete snapshot is useful only when you genuinely need all record
families together.
How authentication works
The first run generates a temporary QR in that run's Output. You scan and
approve it with the Zalo mobile app. After successful authentication, the Actor
stores an encrypted session separated by Apify user and accountAlias.
Later runs can reconnect automatically. A QR may still be required after
expiry, revocation, or a Zalo challenge. This is why “one QR forever” would be
the wrong promise.
Workflow 1: back up accessible conversations
Open Zalo Data Exporter
and choose 💬 Conversation backup.
Use a date and message limit that match the question you are trying to answer:
{
"exportMode": "conversationBackup",
"accountAlias": "main",
"messagesSince": "2026-07-01",
"maxConversations": 3,
"maxMessagesPerConversation": 200,
"includeMessageText": true,
"includeAttachmentMetadata": true
}
The unified Dataset returns conversation and message rows. Each conversation
includes a completeness status:
-
COMPLETE_TO_ZALO_WEB_START— Zalo returned the real start available on Zalo Web; -
PARTIAL_LIMIT— your date or message limit stopped the read; -
PARTIAL_ZALO_BOUNDARY— Zalo or a safety boundary stopped it first; -
FAILED— no safe history result was returned for that conversation.
This distinction matters. “The run succeeded” and “every conversation is
complete” are not the same statement.
Workflow 2: export contacts for a spreadsheet or CRM
Choose 👤 Contacts & profiles. The profile rows can include Zalo user ID,
display name, Zalo name, avatar URL, and relationship when those fields are
visible.
Use userId or recordKey as the stable key. Do not treat display names as
unique, and do not invent phone numbers or emails when Zalo leaves a field
empty.
Workflow 3: export joined-group members
Choose 👥 Group roster and start with one group and 100 members. The video
at the top demonstrates this workflow from QR to spreadsheet.
The Actor separates group, membership, and profile records so one person can
belong to multiple groups without corrupting your contact table.
Workflow 4: create a complete visible-account snapshot
Choose 📦 Complete visible-account snapshot only when your use case needs
contacts, profiles, groups, members, conversations, and messages together.
Set all limits explicitly. More record families mean more runtime, more Dataset
rows, and a higher possible charge.
Automate a bounded chat export with Python
Complete the first QR connection in the Apify Console, then call the saved
session from code:
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_API_TOKEN"])
run = client.actor("kazkn/zalo-member-profile-exporter").call(run_input={
"exportMode": "conversationBackup",
"accountAlias": "main",
"maxConversations": 3,
"maxMessagesPerConversation": 200,
"includeMessageText": True,
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
conversations = [x for x in items if x.get("recordType") == "conversation"]
messages = [x for x in items if x.get("recordType") == "message"]
print({"conversations": len(conversations), "messages": len(messages)})
Keep APIFY_API_TOKEN in an environment variable. Never paste it into the
article, source code, or an AI assistant.
CSV, Excel, or JSON?
Choose based on the next step:
- CSV for imports and simple pipelines;
- Excel for filtering, manual review, and sharing with spreadsheet users;
- JSON for APIs, nested metadata, and code;
- Dataset API for scheduled or event-driven workflows.
The Output tab exposes focused views, while API users can filter the unified
Dataset on recordType.
Privacy and product boundaries
Zalo Data Exporter is read-only. It has no path for sending messages, adding
friends, or changing group membership. It does not bypass authentication,
recover deleted messages, discover unjoined groups, or access mobile-only
encrypted archives.
Zalo can change private behavior, invalidate sessions, or require another
verification. Start with a non-critical account, conservative limits, and an
appropriate retention policy for exported membership and message data.
FAQ
Can I back up all Zalo messages?
The Actor can export accessible direct and joined-group history within your
date, message, time, and platform boundaries. It does not promise universal or
deleted-message recovery.
Can later runs run without a QR?
They can reuse the encrypted session for the same Apify user and
accountAlias. A new QR is required when the saved login expires or is revoked.
What happens when a QR expires?
The run reports QR_EXPIRED. Start a new run and scan the new code; the old QR
is intentionally deleted and cannot be reused.
How is the Actor priced?
It uses pay-per-event pricing for the run start and delivered record types.
Prices vary with the Apify subscription. The Console shows the maximum possible
charge before launch, so explicit small limits are the safest first step.
Start with the smallest useful export
Choose one preset, keep the starter limits, inspect the Dataset views, and only
then increase scope.
👉 Run a bounded Zalo export on Apify
Apify links in this article support the Actor's developer. Results depend on
what the connected account can see and the limits you configure.
Top comments (0)