前言
私域运营中,给微信好友打标签是精细化分层的第一步:哪些是高意向客户、哪些是已购买用户、哪些来自某次活动——标签体系直接决定后续精准触达的效率。然而微信官方客户端没有开放批量标签接口,靠人工逐一操作既耗时又出错。本文基于 WechatApi 个人微信API 提供的好友标签接口,从原理到实战完整拆解调用流程,帮你把"打标签"这件事自动化落地。
一、微信好友标签的底层原理
微信个人号对联系人标签的存储方式与企业微信截然不同。企业微信有标准的 Open API,而个人微信的标签数据本质上存储在本地 SQLite 数据库中(ContactLabel 表),并通过 Protobuf 协议与服务端同步。
普通第三方框架要实现标签操作,只有两条路:一是逆向 Android 包并 Hook 内存,稳定性极差且随版本更新频繁失效;二是基于 iPad 协议 还原微信 iOS 客户端的通信报文,在协议层面直接发送"创建标签/给联系人打标签"指令,与官方客户端行为完全一致,这也是 WechatApi 所采用的方案。
iPad 协议的优势在于:
- 运行于服务器端,不依赖真实手机
- 协议层报文加密,规避普通爬虫特征
- 同一账号可同时挂载多台设备中的一台,不触发多端登录警告
- 标签、备注、分组等好友管理功能全部原生支持
正因为底层协议层的打通,WechatApi 才能稳定地对外暴露好友标签相关的 HTTP 接口,让开发者无需关心协议细节,直接用 JSON 调用即可。
二、接口调用前的准备工作
在开始写代码之前,需要完成以下几项准备:
2.1 注册并获取鉴权凭据
前往 WechatApi 控制台 注册账号并创建设备,完成后会得到两个核心凭据:
| 凭据字段 | 说明 | 使用位置 |
|---|---|---|
VideosApi-token | 账户级鉴权 Token,每次请求必须带在 Header | HTTP 请求头 |
appId | 设备 ID,标识当前登录的微信账号实例 | 请求体 JSON |
这两个参数缺一不可。VideosApi-token 放在 Header 做账户鉴权,appId 放在 Body 里指定操作的是哪一台设备(一个账号下可能挂多台微信)。
2.2 确认好友 wxid
标签操作的目标是具体联系人,接口需要传入对方的 wxid(微信唯一 ID,非微信号)。可先调用获取好友列表接口拿到 wxid,也可以在获取消息事件时从发送方字段中提取。
2.3 规划标签体系
建议在动手前先把标签分层设计好,例如:
- 来源层:活动A、渠道B、自然流量
- 意向层:高意向、中意向、已成交
- 行为层:7日活跃、30日沉默、已退群
提前规划好,后续的自动化打标逻辑才能有条不紊。标签名称在微信中属于字符串,接口创建时直接传名称即可,不需要提前在后台维护枚举值。
三、标签管理接口详解
WechatApi 围绕好友标签提供了一套完整的 CRUD 接口,核心包括:创建标签、获取标签列表、给联系人打标签(添加/移除)、删除标签。所有接口均为 HTTP POST + JSON Body,Base URL 指向你的 API 服务端。
3.1 创建标签
在给好友打标签之前,需要先确保标签存在。如果标签不存在,调用创建接口:
pythonimport requests
API_BASE = "https://your-api-host" # 替换为实际服务地址
TOKEN = "your_videos_api_token" # 控制台获取的 VideosApi-token
APP_ID = "your_app_id" # 设备 ID
def create_label(label_name: str) -> dict:
url = f"{API_BASE}/label/create"
headers = {
"Content-Type": "application/json",
"VideosApi-token": TOKEN
}
payload = {
"appId": APP_ID,
"labelName": label_name
}
resp = requests.post(url, json=payload, headers=headers, timeout=10)
return resp.json()
result = create_label("高意向客户")
print(result)
# {"ret": 200, "msg": "success", "data": {"labelId": 3}}
返回的 data.labelId 是后续打标签时的引用 ID,建议在本地维护一张"标签名→labelId"的映射表,避免重复创建。
3.2 获取标签列表
pythondef get_label_list() -> list:
url = f"{API_BASE}/label/list"
headers = {"Content-Type": "application/json", "VideosApi-token": TOKEN}
payload = {"appId": APP_ID}
resp = requests.post(url, json=payload, headers=headers, timeout=10)
data = resp.json()
if data.get("ret") == 200:
return data["data"]["labels"]
return []
labels = get_label_list()
# [{"labelId": 1, "labelName": "潜在客户"}, {"labelId": 3, "labelName": "高意向客户"}]
实际使用中,建议程序启动时先拉一次标签列表缓存在内存里,后续按名称查 ID,避免每次打标签都先查一遍。
3.3 给好友添加标签
这是核心操作。接口支持一次给一个联系人传入多个 labelId,实现批量打多标签:
json{
"appId": "your_app_id",
"wxid": "wxid_xxxxxxxxxxxxxxx",
"labelIds": [1, 3]
}
对应的 Python 封装:
pythondef add_labels_to_contact(wxid: str, label_ids: list) -> dict:
url = f"{API_BASE}/label/addContact"
headers = {"Content-Type": "application/json", "VideosApi-token": TOKEN}
payload = {
"appId": APP_ID,
"wxid": wxid,
"labelIds": label_ids
}
resp = requests.post(url, json=payload, headers=headers, timeout=10)
return resp.json()
# 示例:给某好友同时打"高意向客户"和"潜在客户"两个标签
result = add_labels_to_contact("wxid_abc123456", label_ids=[1, 3])
print(result)
# {"ret": 200, "msg": "success", "data": {}}
3.4 移除好友标签
移除标签与添加标签的参数结构完全一致,只是接口路径不同:
bashPOST /label/removeContact
Content-Type: application/json
VideosApi-token: your_videos_api_token
{
"appId": "your_app_id",
"wxid": "wxid_xxxxxxxxxxxxxxx",
"labelIds": [3]
}
返回体结构:
json{
"ret": 200,
"msg": "success",
"data": {}
}
ret 为 200 表示操作成功。非 200 时,msg 字段会包含具体错误描述,常见错误如 contact not found(好友不存在)或 label not found(标签 ID 不存在)。
四、批量自动化打标签实战
单次调用解决了单人打标签,真实业务场景更多是"批量导入名单 → 自动打标签"。以下是一个完整的实战脚本思路:
场景:从 CSV 文件读取一批 wxid 名单,全部打上"活动0613"标签。
pythonimport csv
import time
import requests
API_BASE = "https://your-api-host"
TOKEN = "your_videos_api_token"
APP_ID = "your_app_id"
HEADERS = {"Content-Type": "application/json", "VideosApi-token": TOKEN}
def ensure_label(label_name: str) -> int:
"""确保标签存在,返回 labelId"""
# 先查列表
resp = requests.post(f"{API_BASE}/label/list",
json={"appId": APP_ID}, headers=HEADERS, timeout=10)
for item in resp.json().get("data", {}).get("labels", []):
if item["labelName"] == label_name:
return item["labelId"]
# 不存在则创建
resp = requests.post(f"{API_BASE}/label/create",
json={"appId": APP_ID, "labelName": label_name},
headers=HEADERS, timeout=10)
return resp.json()["data"]["labelId"]
def batch_tag(csv_path: str, label_name: str):
label_id = ensure_label(label_name)
print(f"标签 [{label_name}] ID = {label_id}")
with open(csv_path, newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
wxid = row["wxid"].strip()
if not wxid:
continue
result = requests.post(
f"{API_BASE}/label/addContact",
json={"appId": APP_ID, "wxid": wxid, "labelIds": [label_id]},
headers=HEADERS, timeout=10
).json()
status = "OK" if result.get("ret") == 200 else result.get("msg")
print(f" {wxid}: {status}")
time.sleep(0.3) # 适当限速,避免频率过高
if __name__ == "__main__":
batch_tag("contacts.csv", "活动0613")
脚本关键点说明:
ensure_label先查后建,幂等安全,不会重复创建同名标签time.sleep(0.3)是必要的限速保护,每秒不超过 3 次调用,符合接口 QPS 建议- 每条记录独立打印状态,方便排查哪些 wxid 失败
实际项目中可以把这个脚本包装成定时任务:每天凌晨从 CRM 数据库拉取当天新增联系人,按来源渠道自动打对应标签,完全免去人工操作。这正是 微信 SCRM 场景下自动化运营的典型落地方式。
五、接口参数速查表
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
VideosApi-token | Header | string | 是 | 账户鉴权 Token,控制台获取 |
appId | Body | string | 是 | 设备 ID,标识具体微信实例 |
wxid | Body | string | 是(打标签时) | 好友的微信唯一 ID |
labelName | Body | string | 是(创建标签时) | 标签名称,最长建议 ≤20 字 |
labelId | Body | int | 是(操作标签时) | 标签数字 ID,由创建接口返回 |
labelIds | Body | array\<int\> | 是(打/移除标签时) | 支持同时传多个,批量操作 |
返回体统一结构:
| 字段 | 类型 | 说明 |
|---|---|---|
ret | int | 200=成功,其他=失败 |
msg | string | 成功时为 "success",失败时为错误描述 |
data | object | 具体业务数据,部分接口为空对象 |
六、常见问题与注意事项
6.1 标签上限问题
微信个人号对联系人标签数量有隐性限制,通常单账号不超过 200 个标签,单个联系人打标上限约 20 个。超出后接口会返回错误,建议定期清理无效标签,保持标签体系精简。
6.2 wxid 获取方式
打标签接口需要 wxid 而非微信号。wxid 获取方式:
- 调用好友列表接口,返回体中每条记录包含
wxid字段 - 接收到对方消息时,消息事件推送体中的
fromWxid即为对方 wxid - 发消息给对方后,在发送记录中也能找到
注意:通过搜索微信号查找用户后,需先完成加好友流程才能拿到 wxid,陌生人的 wxid 无法直接获取。
6.3 标签操作的延迟同步
标签修改通过 iPad 协议发送后,通常在 1-3 秒内同步到微信服务端,但在手机客户端上的展示可能有 5-10 秒的延迟。自动化流程中不需要等待同步完成,接口返回 200 即可认为操作成功,继续处理下一条。
6.4 账号安全建议
虽然 WechatApi 基于 iPad 协议 风险较低,但高频操作仍需注意:
- 批量打标签建议控制在每分钟 60 次以内
- 避免在凌晨 0-6 点大批量操作,模拟正常人类使用节奏
- 不同设备账号错峰执行任务,分散系统压力
对于需要跨账号管理、多设备协同的私域场景,可以参考 微信二次开发 的整体方案设计,从架构层面把标签管理纳入统一的自动化工作流。
6.5 错误重试机制
生产环境建议加入简单的重试逻辑:
pythonimport time
def safe_add_label(wxid: str, label_ids: list, max_retry: int = 3) -> bool:
for attempt in range(max_retry):
try:
result = requests.post(
f"{API_BASE}/label/addContact",
json={"appId": APP_ID, "wxid": wxid, "labelIds": label_ids},
headers=HEADERS, timeout=10
).json()
if result.get("ret") == 200:
return True
print(f"第{attempt+1}次失败: {result.get('msg')}")
except Exception as e:
print(f"第{attempt+1}次异常: {e}")
time.sleep(1 * (attempt + 1)) # 指数退避
return False
网络抖动、服务端短暂超时都可以通过重试解决,三次重试失败后记录到日志人工跟进即可。
小结
微信好友打标签接口的核心要点可以归纳为三条:先建标签拿 ID、用 wxid 指定目标、labelIds 数组支持批量。整个调用链路清晰:HTTP POST + JSON Body,Header 带 VideosApi-token 鉴权,Body 带 appId 指定设备,返回统一的 {"ret":200,...} 结构,对接成本极低。
WechatApi 基于 iPad 协议的稳定性,让标签管理这类高频操作可以放心地跑在自动化流程里,无论是活动跟进、客户分层还是渠道归因,都能在代码层面优雅实现。如需进一步了解完整接口文档,可访问 开发文档中心 查阅全部接口规范;如需快速接入评估,注册控制台 后即可获取测试凭据开始调试。
