How to Turn a Competitor's Social Engagers Into an Outbound List in Claude
Turn a competitor's social post engagers into a qualified outbound list with a real API pipeline you run in Claude, and decide if a data API beats your signal tool.
Published
Jun 19, 2026
Written by
Manmohit Grewal
Reviewed by
Nithish
Read time
7
minutes

How to Turn a Competitor's Social Engagers Into an Outbound List in Claude
A fractional GTM engineer we spoke with wanted one specific thing from his data provider. Find everyone engaging on a competitor's posts, Clay's in his case, then turn that into people he can actually reach. That is the whole play, and it works because the people reacting to and commenting on a rival's posts are telling you, in public, that they care about the exact problem you solve. This guide shows you how to build that as a real API pipeline you run inside Claude, from pulling the engagers to shipping a qualified list, and how to decide whether a data API beats the signal tool you already pay for.
The engineer we talked to runs almost his whole sales process inside an AI coding agent. He did not want another point tool. He wanted to describe the job, watch the API calls go out, get a sheet back, and reverse-engineer the run into his own stack. You can try the same thing on a free Crustdata account, with 100 credits to get started. We will move through the pipeline quickly, then spend the most time on the harder half of the job, turning raw engagers into a short, scored list and running a coverage check so you know the data is worth committing to.
Why are a competitor's post engagers worth outbound?
When someone likes or comments on a competitor's post, they are paying attention to that space right now, which a list bought by title and headcount can never tell you. They are in the consideration phase already, leaving a public signal of interest. A B2B marketer on Reddit put it plainly, that engagement on a competitor's content consistently converts better than a funding-announcement follow-up, because you are meeting people at the moment they are thinking about the problem.
Not every engager is equal, though. Commenters carry more intent than people who only tapped a reaction, because they took the time to say something. Likers still convert when they are senior, fit your profile, and show a pattern of engaging with the same kind of pain. That difference is worth carrying through the whole pipeline, because it changes who you contact first and what you say. The same engagement list also doubles as a way to find subject-matter experts when you are hiring rather than selling.
How do you pull and enrich a competitor's post engagers?
The most auditable way to build this is to call the API directly, so you can see every request and read every response. The run has three steps, and you can wire all three into one script. One note up front on what the data is. The engagement is public reactions and comments, retrieved live at the moment you ask, so treat each pull as a point-in-time read rather than a permanent record. The professional network's own API does not expose post engagement to third-party apps, which a GTM engineer building this for a client flagged on Reddit, so a purpose-built data API is how you retrieve it.
Find the competitor's posts
Start with the posts themselves. The Social Post search endpoint finds recent posts that mention a competitor's company page, or that the company authored, scoped to a recency window. Capture each post's share_url and uid, because those are how you pull the engagers next.
import requests HEADERS = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json", "x-api-version": "2025-11-01", } # 1. Find recent posts mentioning a competitor's company page. # COMPETITOR_PAGE is the competitor's company profile URL on the network. COMPETITOR_PAGE = "https://www.example.com/company/your-competitor/" search = requests.post( "https://api.crustdata.com/social_post/professional_network/search/live", headers=HEADERS, json={ "date_posted": "past-week", "limit": 10, "filters": [ {"field": "MENTIONING_COMPANY", "value": [COMPETITOR_PAGE]} ], }, ) posts = search.json() # top-level array of posts post_urls = [p["share_url"] for p in posts]
import requests HEADERS = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json", "x-api-version": "2025-11-01", } # 1. Find recent posts mentioning a competitor's company page. # COMPETITOR_PAGE is the competitor's company profile URL on the network. COMPETITOR_PAGE = "https://www.example.com/company/your-competitor/" search = requests.post( "https://api.crustdata.com/social_post/professional_network/search/live", headers=HEADERS, json={ "date_posted": "past-week", "limit": 10, "filters": [ {"field": "MENTIONING_COMPANY", "value": [COMPETITOR_PAGE]} ], }, ) posts = search.json() # top-level array of posts post_urls = [p["share_url"] for p in posts]
import requests HEADERS = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json", "x-api-version": "2025-11-01", } # 1. Find recent posts mentioning a competitor's company page. # COMPETITOR_PAGE is the competitor's company profile URL on the network. COMPETITOR_PAGE = "https://www.example.com/company/your-competitor/" search = requests.post( "https://api.crustdata.com/social_post/professional_network/search/live", headers=HEADERS, json={ "date_posted": "past-week", "limit": 10, "filters": [ {"field": "MENTIONING_COMPANY", "value": [COMPETITOR_PAGE]} ], }, ) posts = search.json() # top-level array of posts post_urls = [p["share_url"] for p in posts]
High-volume access to Social Post search is an enterprise endpoint, so you self-serve it by contacting gtm@crustdata.co for a key. The search returns post-level totals like total_reactions and total_comments, but not the list of people. You get those in the next step.
Pull the engagers
For each post, call the Social Post enrich endpoint with the share_url and ask for reactors and comments. Keep max_reactors at 100 or below and each reactor comes back with a full profile, the title, employer, headline, and location. Above 100 you get basic engagement data only, so for richer pulls you capture the profile URLs here and enrich them properly in step three.
# 2. For each post, pull the people who reacted and commented engagers = [] for url in post_urls: enrich = requests.post( "https://api.crustdata.com/social_post/professional_network/enrich/live", headers=HEADERS, json={ "social_post_url": url, "fields": "reactors,comments", "max_reactors": 100, "max_comments": 50, }, timeout=90, # reactor/comment pulls can take 30-60s ) post = enrich.json()["posts"][0] for r in post.get("reactors", []): engagers.append({"profile_url": r["profile_url"], "engagement": r.get("reaction_type", "REACTION"), "source_post": url}) for c in post.get("comments", []): engagers.append({"profile_url": c["commenter_profile_url"], "engagement": "COMMENT", "source_post": url})
# 2. For each post, pull the people who reacted and commented engagers = [] for url in post_urls: enrich = requests.post( "https://api.crustdata.com/social_post/professional_network/enrich/live", headers=HEADERS, json={ "social_post_url": url, "fields": "reactors,comments", "max_reactors": 100, "max_comments": 50, }, timeout=90, # reactor/comment pulls can take 30-60s ) post = enrich.json()["posts"][0] for r in post.get("reactors", []): engagers.append({"profile_url": r["profile_url"], "engagement": r.get("reaction_type", "REACTION"), "source_post": url}) for c in post.get("comments", []): engagers.append({"profile_url": c["commenter_profile_url"], "engagement": "COMMENT", "source_post": url})
# 2. For each post, pull the people who reacted and commented engagers = [] for url in post_urls: enrich = requests.post( "https://api.crustdata.com/social_post/professional_network/enrich/live", headers=HEADERS, json={ "social_post_url": url, "fields": "reactors,comments", "max_reactors": 100, "max_comments": 50, }, timeout=90, # reactor/comment pulls can take 30-60s ) post = enrich.json()["posts"][0] for r in post.get("reactors", []): engagers.append({"profile_url": r["profile_url"], "engagement": r.get("reaction_type", "REACTION"), "source_post": url}) for c in post.get("comments", []): engagers.append({"profile_url": c["commenter_profile_url"], "engagement": "COMMENT", "source_post": url})
Enrich the people
Now you have a list of engagers tied to the posts they touched. Engager extraction runs on the enterprise Social Post endpoints above. The enrichment half runs on the public Person Enrich API, so any reader can self-serve it. Batch the profile URLs (up to 25 per request) and pull firmographics and a business email.
# 3. Enrich the engagers for company, title, and business email (public endpoint) urls = list({e["profile_url"] for e in engagers}) # dedupe first profiles = requests.post( "https://api.crustdata.com/person/enrich", headers=HEADERS, json={"professional_network_profile_urls": urls[:25], "fields": ["business_email"]}, ).json() # each entry has matched_on, a confidence_score, and full person_data
# 3. Enrich the engagers for company, title, and business email (public endpoint) urls = list({e["profile_url"] for e in engagers}) # dedupe first profiles = requests.post( "https://api.crustdata.com/person/enrich", headers=HEADERS, json={"professional_network_profile_urls": urls[:25], "fields": ["business_email"]}, ).json() # each entry has matched_on, a confidence_score, and full person_data
# 3. Enrich the engagers for company, title, and business email (public endpoint) urls = list({e["profile_url"] for e in engagers}) # dedupe first profiles = requests.post( "https://api.crustdata.com/person/enrich", headers=HEADERS, json={"professional_network_profile_urls": urls[:25], "fields": ["business_email"]}, ).json() # each entry has matched_on, a confidence_score, and full person_data
That is the full round-trip, from a competitor's post to enriched people you can sequence. Everything after this is about narrowing the pile down to the few who matter.
How do you run the same pull conversationally in Claude?
A Claude Code agent with Crustdata's MCP server configured can run that same search-then-enrich loop conversationally, so you describe the job in plain language instead of writing the orchestration yourself. You point the agent at a competitor's company page, ask it to pull the engagers on the last week of posts, enrich them, and drop the result into a sheet. It makes the same API calls under the hood, on the same data, so the only real choice is how much you want to build by hand.
The version the engineer we spoke with wanted does one extra thing. Alongside the sheet, the agent writes a record of every API call it made, the endpoints, the parameters, and what came back. In our own testing that technical appendix is what makes the run reproducible. You read it once, understand exactly what the agent did, and lift the calls straight into your own code when you are ready to own the pipeline. The conversational run is the fast way to prototype, and the appendix is how you graduate it into production.
How do you turn raw engagers into a qualified list?
A raw engager pull is noisy. The same person reacts to three competitor posts in a week, half the list is outside your profile, and some profiles will not resolve to a contact. The real work is turning that pile into a short, scored list you can hand to a sequence.
Dedupe before you enrich
Resolve identities and remove duplicates before you spend a single enrichment credit. If someone commented on three of your competitor's posts, you want a single row for them and you do not want to pay to enrich them three times, as one practitioner put it. Dedupe on the profile URL, keep the strongest engagement signal you saw for that person, and carry the source posts as a list.
Expect a real match rate
Enrichment never resolves every profile. The Person Enrich response gives you a confidence_score between 0 and 1 on each match, and some inputs come back with no match at all. Filter on the score, accept that a clean list is smaller than the raw pull, and move on. Chasing a 100% match rate wastes more time than the missing rows are worth.
Filter to your profile and score the rest
Now keep only the people who fit, by title, company size, and industry, and rank what is left. Score commenters above passive reactors, and lift anyone senior who keeps showing up around the same problem. The output is a small set of columns you wire straight into a sequence:
name and profile URL: who they are and where to verify them.
company, title, and employer company id: the firmographics your sequencing tool branches on.
engagement type and source post: what they did and which competitor post they did it on, so your opener can reference it while the signal is still warm.
score and business email: your priority order and the address to send to.
This is the same broad play covered in our guide to turning social post engagers into an outbound pipeline and the deeper breakdown of reactions and comments as leads. Those pieces cover the general sales play. This one covers running it as an API pipeline inside Claude and deciding which data layer to trust.
A two-person bootstrapped SaaS described this exact approach on Reddit, pulling customers off a much larger incumbent by working what they called the right fifty people that week rather than a giant list. They reach out within 72 hours while the signal is warm and reference what the person engaged with. You can build the enrichment side of this on the free tier before you commit to anything bigger.
Is a data API as good as my signal SaaS tool?
This is the question the engineer we spoke with actually had to answer. He already paid for signal tools, and he was not going to swap one for another on a vendor's word. So he ran a check. You can run the same one before you commit, and it takes an afternoon.
Run a coverage check before you commit
Take the same set of competitor posts, say ten of them, and pull the engagers from both your incumbent signal tool and the data API. Then compare. Count how many people both sources return, how many each one returns that the other misses, and spot-check the quality of the unique names on each side. The data API passes when it returns the incumbent's set plus a meaningful tail of names the incumbent missed, at a quality you would actually contact. The engineer's read after his own test was that coverage came in a couple of points better than AI Ark, comparable to Apollo, with higher quality on the matches.
What a result looks like
The shape of the comparison matters more than any single number. A coverage check on ten posts tends to look like this:
Source | Engagers returned | Unique to this source | Usable after spot-check |
|---|---|---|---|
Incumbent signal tool | 180 | 24 | most |
Data API | 205 | 49 | most |
Overlap | 156 | n/a | n/a |
The number that decides it is the unique tail at usable quality. If the API gives you the incumbent's coverage and a real set of names the incumbent never surfaced, it earns a place in the workflow.
The credit math
Size the test against real costs so the comparison is honest. Social Post search costs 1 credit per post returned, or 3 with exact keyword matching. Social Post enrich costs 5 credits per post for reactors or comments, and 10 for both. Person Enrich is 1 credit for the base profile, plus 1 for a business email, up to 7 for the full set. So a ten-post coverage check, pulling both reactors and comments and enriching the matches, runs in the low hundreds of credits. The free tier ships with 100 credits, which covers a first pass on a handful of posts, and you can check the pricing before you scale the run.
Run it alongside until the numbers earn the swap
The engineer's plan was to run the data API next to his existing providers while keeping both, and poll it on demand rather than commit to a usage projection up front. Another GTM team we spoke with did the same when moving off a pricier enrichment tool, running the cheaper option in parallel and only switching once the coverage held up across their own posts. That is the safe way to do it. Let the coverage check and a few weeks of real runs make the decision, then swap when the data has earned it.
How do you keep it running as an ongoing signal?
The hardest part of doing this by hand is that you would have to check every competitor post every day. You can hand that to a schedule instead. Point the Watcher API at the competitor post URLs you care about, poll them on a cadence, and let new engagers flow into the same sheet your sequence already reads from. The manual monitoring that is easy to start and hard to keep up becomes a background job that keeps your list fresh.
Turning this into your own outbound list
The engager list a competitor generates every time they post is real buying signal, and it usually goes unworked. You do not need a big list to act on it. You need the few people this week who are already thinking about the problem you solve, pulled, deduped, scored, and reached while the signal is warm.
So start small. This week, run the coverage check on ten of your top competitor's posts on the free tier, and see how many usable names you get that your existing tool misses. This quarter, wire the winning path into a Watcher schedule so the list refreshes itself, and build the conversational run in Claude so a teammate without your code can repeat it. The pipeline is short enough that a product lead and one engineer can build a working version in an afternoon.
Crustdata is the data layer for GTM engineers building signal-based outbound they own. Come and see what a competitor's engagement looks like across your own target list. Start free with 100 credits at crustdata.com, or contact gtm@crustdata.co for enterprise social-post access and higher limits.
Frequently asked questions
Can I see who engaged with a competitor's post? Yes. The Social Post enrich endpoint returns the reactors and commenters on a given post, each with their public profile, when you pass the post URL and ask for the reactors,comments fields. It covers public engagement only, retrieved live at the time you call it.
Is turning competitor engagers into outreach allowed? You are working with public engagement that people left in the open, and an API pipeline avoids the account risk of browser-automation scrapers. Respect the platform's terms and the consent rules in your outreach channel, the same as any cold-outreach program, and keep your sending compliant.
How much does this cost? Social Post search is 1 credit per post, enrich is 5 to 10 credits per post depending on whether you pull reactors, comments, or both, and Person Enrich is 1 to 7 credits per profile. A ten-post test run comes to the low hundreds of credits, and the free tier includes 100 credits to start.
How do I reach the engagers once I have the list? Lead with the post they engaged with while the thread is still active, and contact commenters before passive reactors. A short message that names what they reacted to reads as relevant rather than cold, which is the whole reason engagement-based outreach beats a list pulled by title and headcount.
Why use a data API instead of a scraper? Browser scrapers run against the platform's restrictions and get more fragile as those tighten, so they need constant upkeep. An API pipeline is auditable, portable into your own stack, and built to pull engagers without credentialing your account. It is the data layer for teams that want a signal pipeline they can run and trust on a schedule.
Products
Popular Use Cases
Competitor Comparisons
Use Cases
95 Third Street, 2nd Floor, San Francisco,
California 94103, United States of America
© 2026 Crustdata Inc.
Products
Popular Use Cases
Competitor Comparisons
Use Cases
95 Third Street, 2nd Floor, San Francisco,
California 94103, United States of America
© 2025 CrustData Inc.
Products
Popular Use Cases
Competitor Comparisons
Use Cases
95 Third Street, 2nd Floor, San Francisco,
California 94103, United States of America
© 2026 Crustdata Inc.


