My WeChat Chat History, Finally Freely Queryable

A lot of people don’t realize this, but the chat history we generate every day on WeChat actually sits on our computer’s hard drive—encrypted. Want to back it up? Export it? Analyze it? You’re stuck without the key that unlocks it.

That’s exactly what wechat-exporter solves.

It does one thing directly: it takes your macOS WeChat local chat history and decrypts the entire thing into plain SQLite databases. After that, you can query, export, or analyze however you like. This post walks through what it does, how to use it, and what’s happening under the hood.


How Does WeChat Encrypt Local Chat History?

Let’s clear this up first: WeChat for Mac stores your chat history locally, but it’s all encrypted with SQLCipher—an encryption extension for SQLite. The database files are right there on your machine, but without the key, they’re just gibberish.

So where’s the key? When WeChat launches, the key ends up in memory. The tool works by re‑signing the WeChat app so it can be debugged and memory‑scanned, then pulls the encryption key from the running process. Once you have the key, SQLCipher decrypts the databases.

The principle is simple: if the key is in memory, it can be found. The tricky part is locating it. Every time WeChat updates, the memory layout changes, and the scanning tool has to adapt.


What Do You Need Before Getting Started?

Before diving in, check your environment. Saves you from hitting a dead end halfway through.

Requirement Details
OS macOS only. Windows users are out of luck for now.
WeChat version Installed and logged in at least once on your Mac
Chat history Your mobile chat history must be migrated/backed up to the Mac client
Runtime Claude Code or Codex (to run this skill)
Disk permission Terminal needs Full Disk Access

That last one trips people up. If you get permission errors later, it’s almost certainly because you skipped it.

How to set it: System Settings → Privacy & Security → Full Disk Access → add your Terminal (or iTerm2).


What Does the Key Extraction Process Involve?

The whole flow looks like a lot of steps, but it’s actually straightforward when you follow along. The skill itself guides you through everything.

First, install the skill. Two ways, pick one:

# Method 1: copy the file directly
cp SKILL.md ~/.claude/skills/wechat-exporter.md

# Method 2: create a directory (better if you plan to extend later)
mkdir -p ~/.claude/skills/wechat-exporter
cp SKILL.md ~/.claude/skills/wechat-exporter/skill.md

Note: this installs a skill for Claude Code. If you want it per‑project, replace ~/.claude/skills/ with <your-project>/.claude/skills/.

Then in Claude Code, type:

导出微信聊天记录

Or call the skill directly:

/wechat-exporter

After that, the automation kicks in. The skill does these things in order:

  1. Install dependencies – uses Homebrew to install sqlcipher, automatically if missing.
  2. Compile the scanning tool – downloads code from ylytdeng/wechat‑decrypt and builds it.
  3. Re‑sign WeChatsudo codesign --force --deep --sign - /Applications/WeChat.app. This needs admin rights; the skill prompts you to run it manually in the terminal.
  4. Extract the key – runs the scanner against the WeChat process to pull the encryption key. Also needs sudo, so manual intervention.
  5. Decrypt databases – once the key is obtained, it automatically decrypts all database files in bulk.
  6. Output summary – tells you how many databases were decrypted and where they’re saved.

You’ll need to type your sudo password twice. Everything else runs on autopilot.


After Decryption: How Do You Query Your Chats?

The decrypted databases land in ~/wechat‑decrypt‑macos/decrypted/ and look like this:

decrypted/
├── contact/
│   └── contact.db          # Contacts
├── message/
│   ├── message_0.db        # Message shards (split by time period)
│   ├── message_1.db
│   └── ...
├── session/
│   └── session.db          # Conversations list
└── ...

All of these are standard SQLite format. You can query them directly with sqlite3 or a GUI tool like DB Browser for SQLite.

I personally use the command line for quick checks:

sqlite3 ~/wechat‑decrypt‑macos/decrypted/message/message_0.db
.tables

Contacts Table

Inside contact.db, the contact table has a local_type field that tells you the relationship type:

local_type Meaning
1 Real friend (mutual add)
3 Had chat history but not necessarily friends
0 Service accounts, system notifications

This distinction is handy. For example, if you want to analyze chat frequency only with real friends, filter local_type = 1 and you won’t pollute the results with service accounts.

Message Tables

Message storage is a bit more involved. WeChat splits messages across multiple files (message_0.db, message_1.db, etc.) by time range. message_0.db is typically the main store for the most recent year.

Each contact’s messages live in a separate table named Msg_ followed by the MD5 hash of the contact’s username. For example, Msg_a6c47a9d3c7a8e3b....

A mapping table called Name2Id lets you connect usernames to table names:

import hashlib
import sqlite3

conn = sqlite3.connect("message_0.db")
for (username,) in conn.execute("SELECT user_name FROM Name2Id"):
    table = "Msg_" + hashlib.md5(username.encode()).hexdigest()
    print(f"{username}{table}")

Run that and you’ll see exactly which table holds each friend’s messages, then query that table directly.


Is There an Easier Way? – Register as an MCP Server

If you’re using Claude Code, wechat‑exporter can also register itself as an MCP Server.

That means after decryption, Claude Code can query the chat history database directly—you don’t need to write SQL. Just ask in plain English.

For example, you can ask:

  • “What did I talk about with John in the last month?”
  • “Summarize the key discussion points from my work group last week.”
  • “Search for messages containing ‘project delay’.”

Claude Code will go query the SQLite database and return the results to you.

This is a game‑changer for people who aren’t comfortable with SQL. And because Claude Code understands context, you can chain follow‑up questions, and it will refine the search based on previous results.


What If You Run Into Problems?

I hit a few snags myself. Here’s what to look out for.

HMAC Verification Failure

This error means SQLCipher tried to decrypt with the key but the checksum failed. The usual cause: config.json points to a WeChat account directory that doesn’t match the one currently logged in.

WeChat stores account directories under ~/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/ with numeric names—one per logged‑in account. Double‑check that you’re pointing at the active one.

0 keys Found (or Too Few)

If the scanner returns zero keys, or a suspiciously low number, WeChat likely updated and the memory offsets changed.

Fix: re‑sign WeChat again, then re‑run the memory scanner. You don’t need to reinstall WeChat; just re‑run the codesign command.

lldb Attach Fails

This is macOS security blocking you. By default, WeChat is protected and doesn’t allow debugger attachment. You must replace its signature with an ad‑hoc signature using codesign --force --deep --sign -. Without that, lldb can’t attach.

If you forget to re‑sign, the attach step will definitely fail. Run the command and try again.

Decrypted Databases Are Empty

You decrypted successfully but there’s no message content. I ran into this once. The culprit was the bundled server.py still reading from the encrypted database paths instead of the plaintext ones.

Fix: edit server.py to point to the decrypted/ directory, as described in the skill documentation.


Can You Use This in a Production Environment?

Let’s be realistic about scenarios.

Personal use: Absolutely fine. Back up your own chats, run personal analytics, build a knowledge base—it works great.

Enterprise use: Caution advised. WeChat chats may contain sensitive company information. Decrypted databases are stored in plain text, so you need to think about who has access and where they’re stored. Also, re‑signing WeChat might violate some corporate security policies.

And remember: every time WeChat auto‑updates, you’ll need to re‑sign and re‑extract the key. If your WeChat upgrades automatically, your decryption workflow has to be rerun.


Quick Reference: Complete Checklist

  1. Verify environment – macOS, WeChat for Mac logged in, history backed up, Terminal has Full Disk Access.
  2. Install the skill – place SKILL.md in ~/.claude/skills/.
  3. Trigger it – type /wechat‑exporter in Claude Code.
  4. Follow the prompts – enter sudo password when asked, wait for dependency installation and compilation.
  5. Re‑sign WeChat – run sudo codesign --force --deep --sign - /Applications/WeChat.app.
  6. Scan and extract key – run the scanner to get the encryption key.
  7. Auto‑decrypt – wait for all databases to be decrypted.
  8. Start querying – go to ~/wechat‑decrypt‑macos/decrypted/ and use any SQLite tool.
  9. (Optional) Register MCP Server – use plain English queries in Claude Code.

FAQ

Can I restore the decrypted databases back to my phone?

No. This tool only exports/decrypts; it does not import back into WeChat.

Does it still work after WeChat updates?

Possibly not without re‑signing and re‑extracting. If the scanner can’t find keys, watch the project for updates.

Will this break my WeChat?

Re‑signing only modifies the app signature, not your data or chat functionality. macOS may warn that WeChat is “damaged”—that’s expected; trust and run it anyway. To revert, simply re‑install WeChat from the App Store or official website.

Can I export voice messages and videos?

The exported SQLite databases contain text content and references to media file paths. The actual media files are stored elsewhere on disk, not inside the databases.

Is there a GUI?

The tool runs via command line + Claude Code skill—no standalone GUI. But you can use DB Browser for SQLite to browse the decrypted databases visually.

I don’t know SQL at all. Can I still use it?

Yes. After registering the MCP Server, Claude Code answers your questions in natural language—you never need to write a single SQL statement.


Final Thoughts

This tool addresses a real need: making your own chat data controllable and usable again. Encryption exists for privacy, but when you, the user, need to access your own data, that wall becomes a barrier.

wechat‑exporter opens a crack in that wall. Its value isn’t just the act of exporting—it’s giving you agency over your data, whether for backup, analysis, or migrating to other tools.

Of course, with great power comes great responsibility. The decrypted data is plain text and stored locally. Protecting it is just as important as protecting your WeChat account itself.