How to find leads on Twitter
Finding leads on Twitter (X) takes four steps: search public posts for buying-intent phrases such as "any recommendations for" or "alternative to", keep the authors whose bios match your buyer, score them, and reply in public within 48 hours of the post.
Short answer: The best leads on X ask for a tool, leave a competitor or describe the problem you solve in public; bios and a rival's followers widen the pool. To run it as code, use Sorsa API: POST /search-tweets returns about 20 posts with full author profiles per request, from $0.07 per 1,000, and 100 free requests cover the first 2,000.
- Endpoint
POST /search-tweets- Page size
- about 20 posts per request
- Price
- from $0.07 per 1,000
#Where leads on Twitter come from
A lead on X is a public account that has shown a reason to buy: a post asking for a recommendation, a complaint about the tool it uses, or a bio that names the role you sell to. You don't need a following of your own to find these people, and you don't need their email address to start a conversation. To see who describes themselves as your buyer, the free Twitter Bio Search tool finds accounts by the words in their bios, right in the browser.
Twitter lead generation runs two ways. Inbound work, such as useful threads and a clear profile, pulls people toward you over months. Outbound work finds the people who already say they need something, today. This guide covers the second way, because it works from the first day and every step of it can run as code:
-
Search for intent. Run buying-intent searches for your category and your competitors' names, limited to the last few days.
-
Widen the pool. Add accounts whose bios name your buyer, a competitor's followers, members of relevant Communities and Lists, and people replying to posts in your niche.
-
Score and dedupe. Merge everything by user ID and give points for intent, role, a website in the bio and real activity.
-
Reply in public. Answer the hottest posts within a day or two with something useful, and let the reader reach you through your profile.
Every source feeds one pool keyed by user ID; the score decides who gets a reply today.
Paid formats are a separate channel. X stopped its Lead Generation Cards in 2017 and announced Lead Gen Ads in August 2026; both collect details from people who opt in to an ad. The method below finds people who never saw your ad.
#12 buying-intent searches that find people ready to buy
Buying intent shows up in six kinds of public posts, and two searches for each kind catch most of the ways people phrase it. The strongest signals are a direct request and a decision to leave a competitor, because the person has a budget and a deadline in mind.
| Signal | What the post sounds like | Strength |
|---|---|---|
| Asking for a tool | "Can anyone recommend invoicing software for a 10-person team?" | Highest |
| Leaving a competitor | "We're moving off our current tool next month, what else is out there?" | Highest |
| Ready to spend | "Happy to pay for something that chases late invoices for me." | High |
| Complaining about a competitor | "Our invoicing tool raised prices again." | High |
| Describing the problem | "Spent three hours chasing late invoices this week." | Medium |
| Talking to a competitor in public | A reply to the rival's account: "Still waiting on support for this." | Medium |
Asking for a tool
- What the post sounds like
- "Can anyone recommend invoicing software for a 10-person team?"
- Strength
- Highest
Leaving a competitor
- What the post sounds like
- "We're moving off our current tool next month, what else is out there?"
- Strength
- Highest
Ready to spend
- What the post sounds like
- "Happy to pay for something that chases late invoices for me."
- Strength
- High
Complaining about a competitor
- What the post sounds like
- "Our invoicing tool raised prices again."
- Strength
- High
Describing the problem
- What the post sounds like
- "Spent three hours chasing late invoices this week."
- Strength
- Medium
Talking to a competitor in public
- What the post sounds like
- A reply to the rival's account: "Still waiting on support for this."
- Strength
- Medium
Every search has three parts: the ask, your category or a competitor's name, and filters that strip out noise. lang:en keeps one language, -filter:retweets drops copies of the same post, within_time:7d keeps the last week, and -filter:links removes most promotional posts, since a genuine question rarely carries a link. Excluding the competitor's own handle with -from: keeps its marketing out of your results. The full list of filters is in our guide to Twitter search operators.
Type your category, one competitor and the problem in your buyers' words, and the builder writes all 12 searches. Paste any of them into X search to read the results by hand, or send them to the API in the next section.
Asking for a tool
asks("any recommendations" OR "can anyone recommend" OR "suggestions for") "invoicing software" -filter:links lang:en -filter:retweets within_time:7dneeds("looking for a" OR "in the market for" OR "need a good") "invoicing software" -filter:links lang:en -filter:retweets within_time:7dLeaving a competitor
switching"ExampleBooks" ("switching from" OR "moving off" OR cancelled OR canceling) -from:examplebooks_app lang:en -filter:retweets within_time:7dalternatives("alternative to ExampleBooks" OR "ExampleBooks alternative" OR "replacement for ExampleBooks") -from:examplebooks_app lang:en -filter:retweets within_time:7dReady to spend
budget("happy to pay" OR "willing to pay" OR "budget for") "invoicing software" lang:en -filter:retweets within_time:7dcomparing("ExampleBooks vs" OR "vs ExampleBooks") -from:examplebooks_app lang:en -filter:retweets within_time:7dComplaining about a competitor
pricing"ExampleBooks" (expensive OR "raised prices" OR "price increase") -from:examplebooks_app lang:en -filter:retweets within_time:7doutage"ExampleBooks" (down OR outage OR "not working") -from:examplebooks_app lang:en -filter:retweets within_time:7dDescribing the problem
problem"late invoices" ("spent hours" OR "so tired of" OR "every week") lang:en -filter:retweets within_time:7dhow-to("how do you" OR "how do I") "late invoices" -filter:links lang:en -filter:retweets within_time:7dTalking to a competitor in public
to-rivalto:examplebooks_app (help OR issue OR "still waiting") lang:en -filter:retweets within_time:7dat-rival@examplebooks_app ("anyone else" OR "is it just me") -from:examplebooks_app lang:en -filter:retweets within_time:7dTwo searches for each of the six signals, written for your market; each one runs as it is in X search or through the API.
Good to know
Read the first 20 results of a new search before you automate it. If more than a handful are vendors, jokes or job posts, tighten the category words or add exclusions such as
-hiringand-joband the names of other vendors in your space.
#Run the searches with Sorsa API
To run these searches every day without a browser, use Sorsa API, a Twitter (X) API and scraper: POST /search-tweets (opens in a new tab) takes the same operators as X's Advanced Search and returns about 20 posts per request, each with its author's full profile, from $0.07 per 1,000 posts. You need one API key in a header, with no X developer account and no OAuth, and every plan runs at 20 requests per second.
-
Get a key. Sign up and copy your API key from the dashboard. The first 100 requests are free and never expire.
-
Run one search. Send the query in the request body;
orderset tolatestreturns the newest posts first. Add the filters from the builder to the same query string.Terminal curl -X POST "https://api.sorsa.io/v3/search-tweets" \ -H "ApiKey: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "query": "\"any recommendations\" \"invoicing software\" lang:en", "order": "latest" }'Response200 OK { "tweets": [ { "id": "2116173807612858385", "full_text": "Can anyone recommend invoicing software for a small team?", "created_at": "2026-10-30T14:22:07Z", "lang": "en", "likes_count": 4, "retweet_count": 0, "reply_count": 7, "quote_count": 0, "view_count": 812, "is_reply": false, "user": { "id": "1710249922130870349", "username": "brightledger_studio", "display_name": "Brightledger Studio", "description": "Founder at Brightledger Studio. Design for fintech.", "location": "Austin, TX", "bio_urls": ["https://example.com"], "followers_count": 2140, "followings_count": 388, "tweets_count": 3912, "created_at": "2023-10-06T11:05:31Z", "verified": false, "protected": false } } ], "next_cursor": "DAADDAABCgABHV7Bk1OAJxEKAAIdXsDWr9ZQoAgAAwAAAAIAAA" } -
Run all 12 every morning. The script sends each search, follows
next_cursorfor up to three pages, and keeps one entry per account with every signal that account matched. Paste the searches from the builder intoSEARCHES.Python import requests BASE = "https://api.sorsa.io/v3" HEADERS = {"ApiKey": "YOUR_API_KEY"} TAIL = " lang:en -filter:retweets within_time:7d" # label -> search; paste all 12 from the builder above SEARCHES = { "asks": '("any recommendations" OR "can anyone recommend") ' '"invoicing software" -filter:links', "switching": '"ExampleBooks" ("switching from" OR "moving off" ' 'OR cancelled) -from:examplebooks_app', } def search(query, pages=3): body, posts = {"query": query + TAIL, "order": "latest"}, [] for _ in range(pages): r = requests.post(f"{BASE}/search-tweets", headers=HEADERS, json=body, timeout=30) r.raise_for_status() page = r.json() posts += page.get("tweets") or [] if not page.get("next_cursor"): break body["next_cursor"] = page["next_cursor"] return posts def add(pool, user, signal, post_url=None): lead = pool.setdefault(user["id"], {"user": user, "signals": set(), "posts": []}) lead["signals"].add(signal) if post_url: lead["posts"].append(post_url) pool = {} # one entry per account, keyed by user ID for signal, query in SEARCHES.items(): for post in search(query): user = post["user"] if not user.get("protected"): url = f"https://x.com/{user['username']}/status/{post['id']}" add(pool, user, signal, url) print(len(pool), "accounts matched")
A 429 response means more than 20 requests in one second: wait a second and send it again. A 403 means the key is missing or out of requests. Failed requests are never charged.
#Find your target audience on Twitter
Intent posts catch people at the moment of need; your target audience is the larger group that fits your buyer and may need you next quarter. Four sources build that group, and every one returns full or compact public profiles you can score with the same rules.
| Source | What it finds | Sorsa API endpoint | Per request |
|---|---|---|---|
| Bios | Accounts that name your buyer's role, niche or company type | POST /search-users | one page of profiles |
| A competitor's followers | People who already watch your category | GET /followers, GET /verified-followers | up to 200 profiles |
| Communities and Lists | People grouped by topic by themselves or by a curator | POST /community-members, GET /list-members | one page of members |
| People engaging with a post | Who replied to, quoted or reposted a post in your niche | POST /comments, POST /quotes, POST /retweeters | about 20 |
Bios
- What it finds
- Accounts that name your buyer's role, niche or company type
- Sorsa API endpoint
POST /search-users- Per request
- one page of profiles
A competitor's followers
- What it finds
- People who already watch your category
- Sorsa API endpoint
GET /followers,GET /verified-followers- Per request
- up to 200 profiles
Communities and Lists
- What it finds
- People grouped by topic by themselves or by a curator
- Sorsa API endpoint
POST /community-members,GET /list-members- Per request
- one page of members
People engaging with a post
- What it finds
- Who replied to, quoted or reposted a post in your niche
- Sorsa API endpoint
POST /comments,POST /quotes,POST /retweeters- Per request
- about 20
Search bios for the role you sell to
POST /search-users (opens in a new tab) finds accounts by a keyword or phrase in their profile, so a query such as "fractional CFO" or "Shopify agency" returns the people who describe themselves that way. The same search finds candidates for a hire: put the job title in the query instead of the buyer's role.
curl -X POST "https://api.sorsa.io/v3/search-users" \
-H "ApiKey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "fractional CFO"}'
Build a lead list from a competitor's followers
A competitor's followers are people who already pay attention to your category, which makes the list a strong base for prospecting. GET /followers (opens in a new tab) returns up to 200 of them per request with full profiles, so the followers of a 10K-follower account cost from $0.07 on Sorsa API against $100 on the official X API. GET /verified-followers (opens in a new tab) returns only the verified ones, a short list that skews toward companies and active professionals.
Keep only followers whose bios match your buyer, then score them. A follower shows interest, not intent, so a follower with no matching post should rank below anyone who asked for a tool. The full export with paging and CSV is in our Twitter followers API guide, and tracking rivals' growth over time is covered in the Twitter competitor analysis guide.
Pull members of Communities and Lists
People who join an X Community about your topic, or who sit on a curated List of your niche, have grouped themselves for you. POST /community-members (opens in a new tab) takes a Community ID or link and returns compact member profiles: handle, display name and verification. Enrich those with GET /info-batch (opens in a new tab), 100 accounts per request, to get bios and counts for scoring. GET /list-members (opens in a new tab) returns full profiles for every account on a List; the Twitter List API guide shows how to find good Lists and read them as one feed.
Collect the people engaging with a post in your niche
A post from an industry voice about the problem you solve gathers replies from people living with it. POST /comments (opens in a new tab) returns its replies 20 per request, sorted by relevance, recency or likes; POST /quotes (opens in a new tab) returns the posts that quoted it; POST /retweeters (opens in a new tab) returns the accounts that reposted it. Who liked a post is not public on X, so no API returns it: replies, quotes and reposts are the public traces of interest.
Add these sources to the same pool. An account found by two or more sources, for example a competitor's follower who also asked for a tool this week, goes to the top of the list.
def users(method, path, params, pages=5):
"""Page through an endpoint that returns {users, next_cursor}."""
params, found = dict(params), []
for _ in range(pages):
if method == "GET":
r = requests.get(f"{BASE}{path}", headers=HEADERS,
params=params, timeout=30)
else:
r = requests.post(f"{BASE}{path}", headers=HEADERS,
json=params, timeout=30)
r.raise_for_status()
page = r.json()
found += page.get("users") or []
if not page.get("next_cursor"):
break
params["next_cursor"] = page["next_cursor"]
return found
SOURCES = [
("bio", "POST", "/search-users", {"query": "fractional CFO"}),
("rival", "GET", "/followers", {"username": "examplebooks_app"}),
("list", "GET", "/list-members", {"list_id": "1850824826680246284"}),
]
for source, method, path, params in SOURCES:
for user in users(method, path, params):
if not user.get("protected"):
add(pool, user, source)
#Qualify and score every lead
Score each account from the public fields every profile carries, so the list sorts itself: intent first, then fit, then signs of a real, active person. The rubric below is a starting point; after your first 50 replies, raise the points of the signals that led to conversations.
| Signal | Field it comes from | Points |
|---|---|---|
| Asked for a tool, an alternative or a price, or is leaving a competitor | the matched post | +3 |
| Complained, described the problem or compared options (a how-to question: +1) | the matched post | +2 |
| A role word in the bio: founder, CEO, owner, head of | description | +2 |
| A website in the bio | bio_urls | +1 |
| Between 50 and 50K followers | followers_count | +1 |
| Older than 90 days with 100 or more posts | created_at, tweets_count | +1 |
| Found by two or more searches or sources | your pool | +2 |
Asked for a tool, an alternative or a price, or is leaving a competitor
- Field it comes from
- the matched post
- Points
- +3
Complained, described the problem or compared options (a how-to question: +1)
- Field it comes from
- the matched post
- Points
- +2
A role word in the bio: founder, CEO, owner, head of
- Field it comes from
description- Points
- +2
A website in the bio
- Field it comes from
bio_urls- Points
- +1
Between 50 and 50K followers
- Field it comes from
followers_count- Points
- +1
Older than 90 days with 100 or more posts
- Field it comes from
created_at,tweets_count- Points
- +1
Found by two or more searches or sources
- Field it comes from
- your pool
- Points
- +2
A score of 7 or more is a hot lead to answer today, 4 to 6 is warm and goes on a watch list, and anything lower is dropped. The follower band filters out both throwaway accounts and celebrities, who rarely reply to vendors. For a closer look at empty or automated accounts, the signals in our Twitter bot detection guide plug into the same function.
Add the scoring and the export to the same script. It writes leads.csv with the best accounts first, ready for a sheet or a CRM import.
import csv
import re
from datetime import datetime, timezone
ROLE = re.compile(r"\b(founder|co-founder|ceo|cfo|owner|head of)\b", re.I)
INTENT = {"asks": 3, "needs": 3, "switching": 3, "alternatives": 3,
"budget": 3, "pricing": 2, "outage": 2, "problem": 2,
"comparing": 2, "to-rival": 2, "at-rival": 2, "how-to": 1}
def score(lead):
u = lead["user"]
joined = datetime.fromisoformat(u["created_at"].replace("Z", "+00:00"))
age = (datetime.now(timezone.utc) - joined).days
points = max((INTENT.get(s, 0) for s in lead["signals"]), default=0)
points += 2 if ROLE.search(u.get("description") or "") else 0
points += 1 if u.get("bio_urls") else 0
points += 1 if 50 <= u.get("followers_count", 0) <= 50_000 else 0
points += 1 if age > 90 and u.get("tweets_count", 0) >= 100 else 0
points += 2 if len(lead["signals"]) >= 2 else 0
return points
with open("leads.csv", "w", newline="", encoding="utf-8") as f:
out = csv.writer(f)
out.writerow(["score", "tier", "handle", "bio", "website",
"signals", "post"])
for lead in sorted(pool.values(), key=score, reverse=True):
s, u = score(lead), lead["user"]
tier = "hot" if s >= 7 else "warm" if s >= 4 else "cold"
out.writerow([s, tier, u["username"], u.get("description", ""),
(u.get("bio_urls") or [""])[0],
" ".join(sorted(lead["signals"])),
(lead["posts"] or [""])[0]])
Compact profiles from POST /community-members have no bio or counts yet. Collect their IDs and send them to GET /info-batch in groups of 100 before scoring, so every account is judged on the same fields.
#Send scored leads to your CRM, Slack or a sheet
A lead list is useful only if someone acts on it the same day, so send the hot tier where your team already works. The CSV imports into any CRM or spreadsheet as it is. For a live feed, schedule the script once a morning and post each new hot lead to a Slack channel with the handle, the matched post, the signal and the score.
No-code tools run the same flow over plain HTTP: an HTTP module in Make, Zapier, n8n or Pipedream calls POST /search-tweets with your ApiKey header, and the next modules filter, score and route the results. Our guide to the Twitter API in n8n builds that workflow step by step.
Keep a file of the post IDs you have already seen and skip them on the next run, so nobody gets a second reply from your team. A useful CRM record holds the handle, the profile and post links, the signal, the score, the website from the bio and the date you found the lead.
#Reach out in public and stay within the rules
The reply that works on X is public, useful and short: answer the question that was asked, mention your product only if it fits, and let the person come to you. Before you reply, make sure your own profile says in one line who you help and links to a page that explains the offer, because every good reply sends people to your profile first.
Under a post such as "Can anyone recommend invoicing software for a small team?", a reply that works reads like advice from a peer: two things to look for at that size, such as automatic reminders and a client portal, then one line saying your product does both and you are happy to show it. A reply that fails is a bare link with a discount code, posted under every matching post the same hour.
The website in a lead's bio is the second route. A person who asked in public for a tool and lists a company site has given you a way to follow up that doesn't rely on direct messages.
Finding leads in public posts is ordinary research; the rules apply to what you store and how you contact people:
- Public data only. Work from posts and profiles anyone can see. Don't hunt for personal emails or phone numbers, and leave protected accounts out.
- No bulk messages. Don't send automated DMs, follows or likes from your account. Sorsa API is read-only by design, so it can't do any of that, and it never asks for your X login. Read X's automation rules (opens in a new tab) before you automate anything on your own account.
- Email has its own laws. If you email people in the EU or UK, you need a lawful basis under the GDPR, usually legitimate interest with a documented balancing test. Commercial email to people in the US must carry a working opt-out under the CAN-SPAM Act.
- Respect opt-outs. Delete a person's record when they ask, and don't resell or publish raw exports of other people's profiles.
#What a lead run costs
A lead run is cheap on Sorsa API because it is billed per request, and each request returns about 20 posts with their authors. A daily run of 12 searches, three pages each, reads about 720 posts a day, or about 21.6K a month. On the official X API those posts cost $108 a month at $0.005 per post, and from November 22, 2026 X also bills each post's author (opens in a new tab) as a user read at $0.010, which takes the same month to $324. On Sorsa API that month costs from $1.51 and fits inside the Starter plan with room left for an audience build.
Official X API
$500
for 100K posts
$0.005 per post
Sorsa API
from$7
for 100K posts
from $0.07 per 1,000
Every step of the job costs less per 1,000 results on Sorsa API than on the official X API, and the gap is widest on follower lists and profile lookups, which come 200 and 100 per request.
| Step of the lead run | Sorsa API, per 1,000 | Official X API, per 1,000 |
|---|---|---|
| Intent posts with their authors | from $0.07 | $5.00 ($15.00 from Nov 22) |
| A competitor's followers | from $0.007 | $10.00 |
| Profiles looked up in batches of 100 | from $0.014 | $10.00 |
Intent posts with their authors
- Sorsa API, per 1,000
- from $0.07
- Official X API, per 1,000
- $5.00 ($15.00 from Nov 22)
A competitor's followers
- Sorsa API, per 1,000
- from $0.007
- Official X API, per 1,000
- $10.00
Profiles looked up in batches of 100
- Sorsa API, per 1,000
- from $0.014
- Official X API, per 1,000
- $10.00
The official X API also needs a developer account and OAuth, and its pay-per-use plan stops at 3 million post reads a month; its pricing page (opens in a new tab) lists every rate. Sorsa API needs one key, and failed requests are never charged.
#Find your first leads today
Finding leads on Twitter comes down to searching for the moments people ask for help, adding the accounts that fit your buyer, and replying in public before anyone else does. For running that as code, Sorsa API gives you the searches, bios and follower lists behind one key: intent posts from $0.07 per 1,000 and follower lists from $0.007 per 1,000, at 20 requests per second. Your 100 free requests run all 12 searches from the builder about eight times.
#FAQ
What is the best API to find leads on Twitter?
Sorsa API is built for this job: one key returns buying-intent posts with full author profiles from $0.07 per 1,000, a competitor's followers from $0.007 per 1,000 and 100 profiles per batch request, at 20 requests per second on every plan. It needs no X developer account or OAuth, and it is read-only, so it never touches your X account. The first 100 requests are free.
Does Sorsa API give me prospects' email addresses?
No. Sorsa API returns public X data only: posts, bios, the links people put in their bios, follower counts and similar profile fields. It never returns email addresses or phone numbers. To follow up outside X, use the website a lead lists in the bio, or the contact tools you already use, once you have a lawful reason to contact that person.
Can I automate DMs or follows with Sorsa API?
No. Sorsa API is read-only by design: it can't post, reply, like, follow or send direct messages, and it never asks for your X login, so your account carries no risk from it. Use it to find and score leads, then reply in public yourself. If your product later needs to post from code, pair Sorsa API with the official X API for that side.
Are Twitter Lead Generation Cards still available?
No. Twitter launched Lead Generation Cards in 2013, stopped new ones on February 1, 2017 and stopped showing them on March 1, 2017. On August 25, 2026, X announced Lead Gen Ads, a paid form offered through X sales reps. Both collect details from people who opt in to an ad, while searching public posts finds people who already asked for a solution.
How do I find targeted Twitter followers in my niche?
Search bios for the words your niche uses, collect the followers of two or three accounts your niche already follows, and keep the profiles that match both. Accounts found by both routes are the best fit. With Sorsa API, bio search runs through POST /search-users, and a follower list comes 200 followers per request from $0.007 per 1,000.
What data do I get for each lead?
Each lead comes with the public profile X shows: handle, display name, bio, location text, links in the bio, follower and following counts, post count, account creation date and verification status. Leads found through a search also carry the matched post with its likes, replies and views. Emails, direct messages and protected accounts are never included.
#How we checked
On November 2, 2026 we compared every endpoint, parameter, page size and field in this guide with the live Sorsa API reference and the search operator list in our docs, and read the official X API pricing page and X's notice on billing expansions. We read the pages that rank in Google for "twitter lead generation" and "how to find leads on twitter" and asked ChatGPT and Google AI Mode the same questions. The requests and responses are written from the reference with demo accounts; we did not run them against live data for this article.
Sources
- X API pricing, docs.x.com (opens in a new tab)
- X Developer Community: pay-per-use expansions update (opens in a new tab)
- X Business: X launches Lead Gen Ads (August 25, 2026) (opens in a new tab)
- X blog: Lead Generation Card now available to all advertisers (2013) (opens in a new tab)
- Marketing Dive: Twitter to kill off lead generation campaigns (2016) (opens in a new tab)
- Sorsa API reference
- Sorsa API search operators (opens in a new tab)