作者:Sorsa 编辑部
更新于 2026 年 7 月:新增 100 次免费请求的起步额度,把价格改用每千批量费率来阐述,为 2026 年 4 月的按资源定价刷新了官方 X API 成本对比,并对照实时 API 重新核实了全部六种接口方法。
核心要点: 规模化在 X (Twitter) 上找目标受众,意味着以编程方式拉取用户列表,而不是滚动。六种 API 方法覆盖这件事:按关键词搜简介、实时推文意向、一个竞品的粉丝、一个社区的成员、已认证粉丝,以及帖子放大者。每一种都返回完整的公开资料,你随后去重、过滤并导出。
瓶颈很少在策略,而在于对数据的访问。X 在 UI 里显示寥寥几个粉丝就停止加载,官方 X API 又按资源计费:你读的每份粉丝资料花 $0.010,所以单次 1 万粉丝的拉取在你过滤任何人之前就约 $100。Sorsa API 这个替代 Twitter/X API 服务商,移除了两堵墙。其 /followers 接口按请求计费,每次请求返回最多 200 份完整资料,所以同样的 1 万个粉丝在 Pro 套餐上约十美分,而你只用单个 ApiKey 请求头认证,不必走一次 OAuth 握手和一个审批队列。下面每种技术都用一个接口,在任意套餐上以固定每秒 20 次请求运行。
本指南覆盖我们用来组建一个受众的六种方法、运行每一种的代码、如何合并和清洗结果、各要花多少钱,以及拿到列表后该做什么。
目录
- X 上的受众发现到底意味着什么?
- 找受众的六种方式,映射到各自回答的问题
- 技术 1:按人们简介里写的东西找账号
- 技术 2:抽取一个竞品的粉丝列表
- 技术 3:拉取一个社区的成员名册
- 技术 4:从推文搜索里挖实时意向
- 技术 5:单独挑出已认证粉丝
- 技术 6:捕获放大内容的账号
- 合并各来源并按交集打分
- 过滤掉机器人和死号
- 拉取一个受众对比官方 X API 要花多少钱?
- 拿到受众后该做什么
- 实战:一个 B2B SaaS 团队的受众组建
- 如何自己试试
- 常见问题
X 上的受众发现到底意味着什么? {#what-does-audience-discovery-on-x-actually-mean}
X (Twitter) 上的受众发现,是识别值得触达的具体账号,再把它们作为一个结构化、可过滤的列表收集起来的过程。它横跨三个重叠的群体:公开把自己描述成你受众的人、已经关注你所在领域内账号的人,以及此刻正积极发帖谈论你话题的人。
手动路线很熟悉。你打开高级搜索、手动建几个 Twitter 列表、浏览一个社区、记笔记。这对一次性查看有效。但一旦你需要几千个账号、用来甄别它们的数据点,以及一个下个月能重跑的流程,这套手动路线就崩溃了。没有导出按钮,UI 在几百个资料后停止加载,而且这一切都不可复现。
编程路线修好了这三个问题。每个发现问题都映射到一次 API 调用,返回完整的公开资料,以干净 JSON 呈现:简介、粉丝数、账号年龄、位置、认证状态。你规模化地收集、在代码里过滤,并导出到 CSV 或一个数据库。本指南余下部分就是这件事的实用版。
一个值得理清的区别:你的目标受众是你想触达的人,但这不总是已经关注你的人。下面的方法找的是前者,而不只是后者。
找受众的六种方式,映射到各自回答的问题 {#six-ways}
每种技术用一个不同的接口,回答一个不同的定向问题。单独跑一个,或组合几个并按交集打分(下面详述)。
| # | 回答的问题 | 接口 | 每请求资料数 |
|---|---|---|---|
| 1 | 谁在简介里自认为是你的目标画像? | /search-users | ~20 |
| 2 | 谁已经关注你领域里的某个账号? | /followers | 最多 200 |
| 3 | 谁加入了一个围绕你话题的社区? | /community-members | ~20 |
| 4 | 谁现在正在讨论你的话题? | /search-tweets | ~20 |
| 5 | 哪些已认证账号关注了一个目标? | /verified-followers | 最多 200 |
| 6 | 谁在放大你领域里的内容? | /retweeters、/quotes | ~20 |
所有示例都用 https://api.sorsa.io/v3 作为基础 URL 和 ApiKey 请求头。共享设置:
import requests, time
API_KEY = "YOUR_API_KEY"
BASE = "https://api.sorsa.io/v3"
AUTH = {"ApiKey": API_KEY} # GET 接口
POST_HEADERS = {**AUTH, "Content-Type": "application/json"} # POST 接口
技术 1:按人们简介里写的东西找账号 {#technique-1}
找那些自我宣告是你受众的人,最快的方式是搜索他们写的关于自己的东西。一个像 Solidity developer、growth marketer 或 oncology nurse 的关键词会匹配简介、显示名和用户名,所以认同某个角色的人直接浮现。当你的受众用一个头衔或细分领域给自己贴标签时,这是对的选择。
/search-users 接口接收一个查询并翻页遍历匹配。每条结果都是一份完整资料,所以你在代码里甄别候选、无需第二次查询。
def find_users_by_bio(query, max_pages=10):
users, cursor = [], None
for _ in range(max_pages):
body = {"query": query}
if cursor:
body["next_cursor"] = cursor
resp = requests.post(f"{BASE}/search-users", headers=POST_HEADERS,
json=body, timeout=30)
resp.raise_for_status()
data = resp.json()
users.extend(data.get("users", []))
cursor = data.get("next_cursor")
if not cursor:
break
time.sleep(0.1)
return users
users = find_users_by_bio("machine learning engineer")
这个模式在任何语言里都一样。同样的调用用 JavaScript:
async function findUsersByBio(query, maxPages = 10) {
const all = [];
let cursor = null;
for (let i = 0; i < maxPages; i++) {
const body = { query };
if (cursor) body.next_cursor = cursor;
const resp = await fetch("https://api.sorsa.io/v3/search-users", {
method: "POST",
headers: { ApiKey: "YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify(body),
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
const data = await resp.json();
all.push(...(data.users || []));
cursor = data.next_cursor;
if (!cursor) break;
await new Promise((r) => setTimeout(r, 100));
}
return all;
}
因为每条记录都携带完整资料,过滤是一次列表推导,而不是又一轮 API 调用:
qualified = [
u for u in users
if u.get("followers_count", 0) >= 1000
and u.get("tweets_count", 0) >= 100
and not u.get("protected", False)
]
要多词和操作符驱动的精确度,用于推文的同一套查询语法也适用。我们的 Twitter 搜索 API 指南深入介绍了操作符集。
技术 2:抽取一个竞品的粉丝列表 {#technique-2}
单一产出最高的受众信号,是谁已经关注了你领域里的一个账号。如果一个人关注你的直接竞品,他们已经预先甄别了自己:他们在意这个品类。/followers 接口返回那份列表,每次请求最多 200 份完整资料,这让它成为现有最具成本效率的发现调用。
def get_followers(username, max_pages=20):
followers, cursor = [], None
for _ in range(max_pages):
params = {"username": username}
if cursor:
params["next_cursor"] = cursor
resp = requests.get(f"{BASE}/followers", headers=AUTH,
params=params, timeout=30)
resp.raise_for_status()
data = resp.json()
followers.extend(data.get("users", []))
cursor = data.get("next_cursor")
if not cursor:
break
time.sleep(0.1)
return followers
followers = get_followers("competitor_handle", max_pages=20)
单个竞品是一个起点。同时关注你领域里好几个玩家的账号是一个更锐利的分层,因为交集信号说明的是真正的品类兴趣,而不是一次性的关注。拉几个种子,保留交集:
from collections import Counter
competitors = ["competitor_a", "competitor_b", "competitor_c"]
follower_sets = {h: {f["id"] for f in get_followers(h, max_pages=10)}
for h in competitors}
all_ids = [uid for ids in follower_sets.values() for uid in ids]
overlap = {uid for uid, c in Counter(all_ids).items() if c >= 2}
端到端走一个 5000 万粉丝的账号很少值得。对约 50 万粉丝以上的账号,拉前 50 到 100 页(1 万到 2 万份资料)通常是近期、活跃受众的一个有代表性的样本。关于粉丝和关注抽取更深入的处理,包括受保护账号和采样的边缘情况,见我们关于抽取 Twitter 粉丝的指南。
技术 3:拉取一个社区的成员名册 {#technique-3}
X 社区是按话题界定的分组,这意味着成员资格已经被自选的兴趣过滤过。拉取你细分领域里一个社区的名册,交给你一个自愿加入那个确切主题的受众。/community-members 接口接受数字社区 ID 或完整 URL。
def get_community_members(community_id, max_pages=20):
members, cursor = [], None
for _ in range(max_pages):
body = {"community_link": community_id}
if cursor:
body["next_cursor"] = cursor
resp = requests.post(f"{BASE}/community-members", headers=POST_HEADERS,
json=body, timeout=30)
resp.raise_for_status()
data = resp.json()
members.extend(data.get("users", []))
cursor = data.get("next_cursor")
if not cursor:
break
time.sleep(0.1)
return members
社区结果是紧凑资料(id、用户名、显示名、图片、认证、受保护)。要用粉丝数、简介和账号年龄给这些资料做信息增补以便过滤,把收集到的 ID 传过批量资料接口,它接收最多 100 个 ID,算作一次请求。相关的列表和社区接口在我们的 X 列表与社区 API 指南里覆盖。
技术 4:从推文搜索里挖实时意向 {#technique-4}
其他技术按人们是谁或关注谁来找他们。推文搜索按他们此刻在说什么来找他们。今天发 "looking for a CRM recommendation" 的人,是一类不同、且往往更有价值的受众:他们不同于仅仅符合静态画像的人,因为意向是新鲜的。搜索推文,再抽取唯一作者。
def find_active_voices(query, min_followers=100, max_pages=10):
seen, voices, cursor = set(), [], None
for _ in range(max_pages):
body = {"query": query, "order": "latest"}
if cursor:
body["next_cursor"] = cursor
resp = requests.post(f"{BASE}/search-tweets", headers=POST_HEADERS,
json=body, timeout=30)
resp.raise_for_status()
data = resp.json()
for tw in data.get("tweets", []):
u = tw.get("user", {})
uid = u.get("id")
if uid and uid not in seen and u.get("followers_count", 0) >= min_followers:
seen.add(uid)
voices.append({
"username": u.get("username"),
"followers": u.get("followers_count", 0),
"bio": u.get("description", ""),
"sample_tweet": (tw.get("full_text") or "")[:160],
})
cursor = data.get("next_cursor")
if not cursor:
break
time.sleep(0.1)
return voices
voices = find_active_voices(
'("need a CRM" OR "looking for a CRM") lang:en -filter:retweets')
查询字符串是这个技术物有所值之处。几个浮现意向的模式:
| 目标 | 查询 |
|---|---|
| 某品类的购买意向 | "need a [category]" OR "looking for [category]" lang:en -filter:retweets |
| 对竞品的不满 | "[competitor]" (frustrated OR broken OR "switching from") -from:[competitor] |
| 迁移意向 | "migrating from [tool]" OR "switching from [tool]" lang:en |
| 求推荐 | ("any recommendation" OR "anyone use") [topic] lang:en |
| 痛点讨论 | "struggling with" OR "how do you handle" [topic] lang:en |
完整的操作符集,包括官方 API 悄悄丢弃的互动筛选,在我们的 Twitter 搜索操作符速查表里。
技术 5:单独挑出已认证粉丝 {#technique-5}
对公关名单、记者触达、投资人研究或网红核查,一个受众里高知名度的那一片比原始数量更要紧。/verified-followers 只返回关注一个目标的已认证账号,与 /followers 有相同的形态和分页。
def get_verified_followers(username, max_pages=10):
verified, cursor = [], None
for _ in range(max_pages):
params = {"username": username}
if cursor:
params["next_cursor"] = cursor
resp = requests.get(f"{BASE}/verified-followers", headers=AUTH,
params=params, timeout=30)
resp.raise_for_status()
data = resp.json()
verified.extend(data.get("users", []))
cursor = data.get("next_cursor")
if not cursor:
break
time.sleep(0.1)
return verified
verified = get_verified_followers("openai")
verified.sort(key=lambda u: u.get("followers_count", 0), reverse=True)
按触达排序,你就得到一个现成的候选短名单,收录某个目标轨道里最有影响力的账号。关于在单个粉丝列表之外寻找和甄别有影响力账号,我们的面向任意细分领域的网红 API覆盖了更广的工作流。
技术 6:捕获放大内容的账号 {#technique-6}
在你领域里转推和引用推文的人,是一类已经行动、而不只是潜水的受众。两个接口覆盖放大。/retweeters 返回转帖了一条推文的用户。/quotes 返回完整的引用推文,其中包括引用的用户加上他们的评论,对带情感标签的触达有用。
def get_retweeters(tweet_link, max_pages=10):
users, cursor = [], None
for _ in range(max_pages):
body = {"tweet_link": tweet_link}
if cursor:
body["next_cursor"] = cursor
resp = requests.post(f"{BASE}/retweeters", headers=POST_HEADERS,
json=body, timeout=30)
resp.raise_for_status()
data = resp.json()
users.extend(data.get("users", []))
cursor = data.get("next_cursor")
if not cursor:
break
time.sleep(0.1)
return users
def get_quoters(tweet_link, max_pages=10):
quotes, cursor = [], None
for _ in range(max_pages):
body = {"tweet_link": tweet_link}
if cursor:
body["next_cursor"] = cursor
resp = requests.post(f"{BASE}/quotes", headers=POST_HEADERS,
json=body, timeout=30)
resp.raise_for_status()
data = resp.json()
quotes.extend(data.get("tweets", []))
cursor = data.get("next_cursor")
if not cursor:
break
time.sleep(0.1)
return quotes
引用推文是推文对象,而不是用户对象:通过 tweet["user"] 取到引用账号,通过 tweet["full_text"] 取到他们的评论。完整的互动集(回复、引用、转推者)在我们的 Twitter 互动 API 指南里覆盖。
合并各来源并按交集打分 {#combine}
每种技术覆盖一个不同的盲点,所以最强的分层,是那些在不止一个来源里出现的账号。跑几种方法,按用户 ID 去重,并按每个账号出现在多少个来源里排名:
def score_by_source(by_source):
"""by_source: {source_name: [user objects]} -> 去重的用户,带 source_count。"""
index = {}
for source, users in by_source.items():
for u in users:
uid = u["id"]
index.setdefault(uid, {"user": u, "sources": set()})["sources"].add(source)
result = []
for entry in index.values():
u = entry["user"].copy()
u["source_count"] = len(entry["sources"])
u["sources"] = sorted(entry["sources"])
result.append(u)
result.sort(key=lambda r: (-r["source_count"], -r.get("followers_count", 0)))
return result
combined = score_by_source({
"followers_competitor_a": followers,
"bio_ml_engineer": users,
"intent_crm": voices,
"community_indie_hackers": get_community_members("1966045657589813686"),
})
出现在两个或更多来源里的账号,通常是列表里价值最高的部分。一个关注你竞品、用你的目标角色描述自己、而且本周发了意向推文的人,比任何单一信号本身都是更强的线索。
过滤掉机器人和死号 {#filter}
原始发现输出总带着噪音:机器人、被弃用的账号,以及养号资料。因为每个接口都返回完整资料,一个可复用的过滤器无需额外调用就清洗整个列表:
from datetime import datetime, timezone, timedelta
def is_quality_account(user, min_followers=500, min_tweets=100, max_following_ratio=10):
if user.get("protected", False):
return False
if user.get("followers_count", 0) < min_followers:
return False
if user.get("tweets_count", 0) < min_tweets:
return False
followers = user.get("followers_count", 1)
if user.get("followings_count", 0) > followers * max_following_ratio:
return False
created = user.get("created_at")
if created:
try:
dt = datetime.fromisoformat(created.replace("Z", "+00:00"))
if dt > datetime.now(timezone.utc) - timedelta(days=30):
return False
except ValueError:
pass
if not (user.get("description") or "").strip():
return False
return True
qualified = [u for u in combined if is_quality_account(u)]
一个失衡的关注对粉丝比、一个空简介、一个崭新账号,以及近乎零的推文,是最便宜的机器人破绽。把阈值调到你的细分领域。关于给虚假和不活跃账号打分更深入的一遍,见我们关于审计虚假粉丝的指南。
拉取一个受众对比官方 X API 要花多少钱? {#cost}
受众发现天生就是读密集型的:每个项目数千份资料,往往按计划刷新。这恰恰是计费模型决定账单的那种负载。官方 X API 按抓取的资源计费,所以每份资料都是一个单独的可计费单位。一个按请求计费的 Twitter/X API 则不同:一次粉丝请求以一次调用的价格返回最多 200 份资料。
| 官方 X API(按量付费) | Sorsa API | |
|---|---|---|
| 计费模型 | 按抓取的资源 | 按请求(固定) |
| 10,000 份粉丝资料 | 10,000 次读取 @ $0.010 = ~$100 | ~50 次请求 @ $0.00199(Pro)= ~$0.10 |
| 每请求资料数 | 1(各计费) | 最多 200(/followers,算作 1) |
| 认证 | OAuth 2.0 + Bearer 令牌,已批准的开发者账号 | 单个 ApiKey 请求头,无需审批 |
| 速率限制 | ~300 请求/15 分钟,因接口而异 | 每秒 20 次请求,每个套餐 |
| 套餐 | 按量付费,200 万帖子读取月度上限 | Starter $49 / Pro $199 / Enterprise $899 每月 |
差距在规模上叠加。在官方 API 上拉 1 万个竞品粉丝加 1 万份简介搜索资料约为 2 万次用户读取、约 $200,还没过滤。同样两次拉取,在一个采用按请求定价的服务商的 Pro 套餐上,落在一个月度请求预算之内。完整的逐服务商成本拆解见我们的 Twitter API 替代方案对比。(官方 X API 数字反映 2026 年 4 月更新后生效的按资源定价;我们自己的费率在每个套餐上都是按请求计费。)
拿到受众后该做什么 {#what-next}
一份账号列表是原材料,而不是结果。价值真正显现的地方:
- 触达和获客。 过滤、去重后的资料成为一份优先排序的联系名单。意向和交集分数告诉你先触达谁。我们的 X 获客工作流正建在这份输出之上,在 X 上找线索的实用指南则走一遍甄别过滤器。
- 内容策略。 你收集的简介、反复出现的短语和样本推文,映射出你受众实际使用的语言。在钩子和话题串里镜像他们的措辞,而不是靠猜。
- 竞品和受众对标。 对比你的粉丝和一个对手的交集,或追踪一个竞品的受众随时间如何增长,用 X 竞品追踪。开发者侧的方法在我们的 Twitter 竞品分析指南里。
- 按地理估算市场规模。 按国家聚合受众,好在你投入预算之前看清哪些市场是真的。方法在我们的 Twitter 受众地理指南里。
无论目的地是什么,导出都是同一步。如果你宁愿跳过代码,同样的资料可以通过我们的把 X 数据导出到 Google Sheets详解直接进一张电子表格。下面的代码片段把任意技术的输出写入 CSV:
import csv
def export_users_to_csv(users, output_file="audience.csv"):
fields = ["user_id", "username", "display_name", "description",
"followers_count", "followings_count", "tweets_count",
"location", "verified", "created_at"]
with open(output_file, "w", newline="", encoding="utf-8") as f:
w = csv.DictWriter(f, fieldnames=fields)
w.writeheader()
for u in users:
w.writerow({
"user_id": u.get("id", ""),
"username": u.get("username", ""),
"display_name": u.get("display_name", ""),
"description": (u.get("description") or "").replace("\n", " "),
"followers_count": u.get("followers_count", 0),
"followings_count": u.get("followings_count", 0),
"tweets_count": u.get("tweets_count", 0),
"location": u.get("location", ""),
"verified": u.get("verified", False),
"created_at": u.get("created_at", ""),
})
实战:一个 B2B SaaS 团队的受众组建 {#in-practice}
一个约 12 人的 B2B SaaS 营销团队,在手动跑了两个季度触达之后转向了这个方法。他们的流程是一名研究者把用户名从高级搜索复制进一张电子表格,这每周约几百个账号封顶,且不产出甄别数据。他们把这套流程重建成一条数据管道。先抽取三个最接近竞品的粉丝,再为他们买家所持的两个职位跑一次简介搜索。接着对一个在位工具搜索迁移意向推文,最后合并并按交集打分。命中两个或更多来源的账号,成为一份几千个合格资料的排名触达名单,每周刷新。
让他们意外的部分是成本这一行。他们在官方 X API 上跑这个体量的原计划,让读取负载在过滤之前就每月要花数百美元。把数据层迁到一个按请求计费的 Twitter 爬虫,同样的拉取就放进了一个不到 $200 的月度套餐内。对这样的读密集型工作,一个按请求计费的模型比按资源计费便宜最高 50 倍,因为一次粉丝请求以一个单位的价格返回最多 200 份资料。
如何自己试试 {#getting-started}
你可以先不写代码就测试这里每种技术。无代码的 Sorsa Playground 通过一个 UI 运行同样的接口:挑一种方法、设页数、预先看到请求成本,并下载结果。当你准备好把它脚本化时,快速上手几分钟就让你有一个可用的请求。
设置是一个单一的 ApiKey 请求头,没有开发者账号审核、没有 OAuth 流程;头 100 次请求免费:一份无需绑卡、永不过期、覆盖全部 40 个接口的一次性额度(最多可覆盖 1 万条推文或 2 万份资料)。资料拉取从每 1,000 份 $0.01、推文从每 1,000 条 $0.02 起,每个套餐都保持固定每秒 20 次请求,这在一次 200 份资料的粉丝调用上是每秒最多 4,000 份资料。对更大或定时的受众组建,定价页面有按请求计费的明细和一个计算器。
常见问题 {#faq}
如何在 Twitter (X) 上找到你的目标受众? 在 X 上找目标受众,意味着把值得触达的具体账号作为一个结构化列表收集起来,而不是滚动 App。实用的方法是简介和推文关键词搜索、抽取一个竞品的粉丝、抓取一个社区的成员,以及收集转推相关帖子的账号。一个 API 把这些作为你能过滤和导出的完整资料返回。
能按简介里的关键词找 Twitter 用户吗? 能。为一个关键词搜索简介、显示名和用户名,会浮现那些用一个角色或细分领域自我认同的账号,比如 "Solidity developer" 或 "growth marketer"。一个用户搜索接口就做这件事,把每个匹配作为一份完整资料返回,包括粉丝数和账号年龄。这样你在代码里甄别候选,无需第二次查询。
如何拿到一个竞品的粉丝列表? 一个竞品的粉丝可通过一个粉丝接口访问,它把公开粉丝列表作为完整资料返回,每次请求最多 200 份。所以一份 1 万粉丝的列表约需 50 次调用。拉几个竞品,保留同时关注两个或更多的账号,就产出一个比任何单个账号更锐利、更有品类兴趣的分层。
有没有对受众拉取速率限制更好的 X API 替代方案? 有。Sorsa API 是一个为读密集型工作打造的 Twitter/X API 替代方案,所有套餐统一 20 次/秒,没有按接口窗口。它按请求计费,而不是按资源,所以一次粉丝调用以一个单位额度返回最多 200 份资料,而设置只是一个单一 API 密钥,无审批队列。
拉取 1 万份粉丝资料要花多少钱? 在官方 X API 上,1 万份粉丝资料作为 1 万次资源读取,每次 $0.010 计费,约 $100。在一个按请求计费的模型上,同样的 1 万份资料约需 50 次请求、每次 $0.002,约十美分,因为一个粉丝接口每次请求返回最多 200 份资料。
能不写代码就在 X 上找受众吗? 能。Sorsa Playground 通过一个网页界面运行这些发现接口:选一种方法(如用户搜索或粉丝抽取)、设拉多少页、运行前看到请求成本,并导出结果。它用的是与 API 相同的数据,头 100 次请求免费、无需绑卡,所以在你投入一个套餐之前,一次初始受众拉取不花钱。
审校:Keksich(Sorsa 创始人,X API 研究者)
本指南是怎么写成的:这六种方法是我们在构建并运营 Sorsa 替代 Twitter/X API 时对着实时 X 数据层运行的那些,而这里每个接口、参数和按请求行为都在本次修订中对照 Sorsa API 文档重新核查。成本对比用的是官方 X API 在其 2026 年 4 月更新后公布的按资源定价,与我们自己已发布的费率交叉核对。于 2026 年 6 月 11 日核实。