Use cases / Social and community
9 min readTurn competitor commenters on LinkedIn into a qualified lead list
200 competitor commenters in, 54 decision makers with a current work email out, and a person reads 36 profiles instead of 200. The comment is the trigger, never the opener.
$ Set up https://www.routergrowth.com/SKILL.md, then pull the comments under the busiest post on [competitor page] and [competitor page], read every commenter, drop the vendors' staff, keep [our buyers], and show me the rows you are unsure about. Do not send anything.
On this page
The people commenting under your competitors' posts this week are the warmest list you do not own. They spent time reading about the problem you solve, in public, with a timestamp. A database gives you a VP with the right title; a comment section gives you a VP with the right title who was in the conversation on Tuesday.
The catch is the noise. Under any vendor's launch post, a third of the commenters work for the vendor, a third are investors, students, journalists and people cheering, and the rest are the buyers. Reading 200 profiles to find the 50 is the afternoon nobody has. This guide is the run that removes it: pull the threads, read every commenter, let a judge model sort buyers from staff from noise, check that the enrichment record is the person's current job, and hand a human the rows the model is unsure about. Nothing sends without you.
We ran it on our own market on 17 September 2026: 8 competitor threads, 200 commenters, 54 decision makers with a current work email, 36 profiles read by a person. The full run with every miss is in the article; the recipe below has the parts you change in brackets.
Which threads do you pull?
Three to eight LinkedIn posts under [the accounts your buyers already follow]: your competitors' company pages, their founders, the tools your buyers pay for, the creators in your category. Pick the post with the most replies on each account; a funding announcement or a product launch under a founder's name draws ten times the comments of the company page.
curl -X POST https://api.routergrowth.com/v1/run \
-H "Authorization: Bearer $ROUTERGROWTH_API_KEY" \
-d '{"capability": "social.posts",
"input": {"platform": "linkedin", "handle": "https://www.linkedin.com/in/[founder]/", "limit": 4}}'
Each post comes back with its reply count. Take the busiest one per account and pull the comments:
curl -X POST https://api.routergrowth.com/v1/run \
-H "Authorization: Bearer $ROUTERGROWTH_API_KEY" \
-d '{"capability": "social.comments",
"input": {"url": "https://www.linkedin.com/posts/[the post]", "limit": 130}}'
Comments carry the author, the profile URL and the text. Drop company-page commenters (the URL says /company/) for free, and dedupe on the profile URL across every thread: the same twenty people comment under everything a vendor posts.
What do you check before paying for a profile?
Run the free dedupe first. history with the list of profile URLs says who your workspace already enriched or contacted, and returns the reusable result instead of buying it twice.
curl -X POST https://api.routergrowth.com/v1/history \
-H "Authorization: Bearer $ROUTERGROWTH_API_KEY" \
-d '{"subjects": ["https://www.linkedin.com/in/...", "https://www.linkedin.com/in/..."]}'
Then one person.enrich per new commenter. The default route reads the public profile: headline, current title, current company, location, the about text. That is all the judge needs, and it is the cheapest call in the run.
How does the judge sort buyers from staff from noise?
Write two things down before the model sees a row. They are the whole prompt.
The buyer brief. One paragraph: [who buys or runs what you sell: the titles, the seniority, the company shape, and the edge cases you count in, such as agency founders who run it for clients]. Write it like a rubric, not a persona. The exclusion list. [The vendors, partners and certified experts you never want to email], plus the noise you always drop: investors, students, recruiters, journalists, individual contributors outside the buying function.
Then three typed questions per profile, to a judge model that returns probabilities instead of prose (we used TypeSafe's Jev; the harness is open, and your agent can ask the same three questions of any model that returns a probability):
- Which group is this person in: buyer, excluded, or off-ICP.
- Does this person work for, create content for, or hold a certification from anyone on the exclusion list, yes or no.
- How closely does this profile match the brief, on three levels you describe in words.
The policy lives in your code, not in the model. Exclusion probability above 0.8 drops the row before any paid lookup. Group confidence above 0.8 keeps or drops on its own. Below 0.5 goes to a human. Everything in between is a review band you size by how many rows your team will read on a Monday.
On our 200 rows the exclusion question caught 37 of 38 vendor employees and partners. The group question agreed with our hand labels on 167 of 200, and 94% of the time where it was confident. The disagreements were not random: they were the two groups our own brief was vague about, founders of training businesses and freelancers who call themselves by the buyer's title. Your first run's disagreements are the sentences your brief is missing.
Is the enrichment record the person's current job?
For every buyer, pull the enrichment record with the email: person.enrich pinned to the Apollo route returns the current title, company, domain and a work email with its status. Then ask one more yes-or-no question over the two records: does the provider's record describe the same job as the profile's current role.
curl -X POST https://api.routergrowth.com/v1/run \
-H "Authorization: Bearer $ROUTERGROWTH_API_KEY" \
-d '{"capability": "person.enrich", "routing": {"provider": "apollo"},
"input": {"profile_url": "https://www.linkedin.com/in/[buyer]"}}'
People change jobs faster than databases refresh. On our 90 records, 17 were a job behind, and 7 of those came with a valid-looking email at the old employer. Those are the sends that bounce or land in an ex-employee's inbox, and a handful a week is what turns a warm sending domain into a cold one. The judge gave every one of the 17 a probability under 0.13; a keep threshold at 0.3 with a review band up to 0.7 caught all of them and asked a human about four rows. Add one rule in code the model cannot see: the email's domain must match the company's domain.
What do you send, and what do you never say?
Verify every kept email with contact.verify before it touches your sending domain. Keep valid, drop invalid, hold catch-all and unknown and say so.
Then the rule that makes the play work: the comment is the trigger, never the opener. Nobody gets "saw you commented under their post". The signal decided who is on the list; the message offers something useful about the problem they were reading about, and asks one question. One LinkedIn note per buyer from your connected account with linkedin.invite, one email per verified contact with email.send, both behind a human gate.
Run the same threads every Monday and it stops being a campaign and becomes a channel. Every competitor with a comment section is a source, and so is every creator your buyers follow.
What did one run produce?
Eight threads on our own market, 17 September 2026:
- 230 comments, 7 company pages dropped for free, 200 new people.
- 82 buyers surfaced out of 92 we had labelled by hand: 61 kept by the model, 21 held for a human, 10 lost.
- 61 with a current employer confirmed against their record, 54 with a current work email, 34 of them founders or C-level.
- 13 stale records blocked before an email went out, 5 with a valid-looking address at a previous employer.
- 36 profiles read by a person, not 200. Four record pairs, not 90.
If one in ten of the 54 replies, that is five conversations. If one in three of those books, that is two meetings from one brief.
Run it as an agent
routergrowth run -c social.posts -i '{"platform":"linkedin","handle":"https://www.linkedin.com/in/[founder]/","limit":4}'
routergrowth run -c social.comments -i '{"url":"https://www.linkedin.com/posts/[the post]","limit":130}'
routergrowth history --file urls.txt
routergrowth run -c person.enrich -i '{"profile_url":"https://www.linkedin.com/in/[commenter]"}'
routergrowth run -c person.enrich --provider apollo -i '{"profile_url":"https://www.linkedin.com/in/[buyer]"}'
routergrowth run -c contact.verify -i '{"email":"[email]"}'
The brief we hand the agent, with the parts you change in brackets:
Pull the last 3 posts from these LinkedIn pages: [competitor 1], [competitor 2], [a creator our buyers follow]. On each, take the post with the most replies and pull its comments. Drop company pages and anyone on [our exclusion list]. Read every remaining commenter and keep only [our buyer brief]. Dedupe against what we already contacted. For each buyer, pull the enrichment record and keep it only when its company is a current role on the profile and the email is on that domain. Verify every email. Draft one note per buyer without naming the post. Show me the rows you were unsure about, then the receipt. Do not send anything.
Sign up, get $1 of credit, and the first thread in this guide costs less than that.
What does each call cost?#
Prices below are the starting price per successful call. /v1/inspect returns the exact figure before the run and reserves it against your balance; failures and unbilled no-matches release the hold in full.
| Capability | What it returns | From | Providers |
|---|---|---|---|
| social.posts | Recent public posts for a social handle. | $0 | |
| social.comments | Comments on one public post URL (YouTube, TikTok, Instagram, LinkedIn, Reddit): text, author, likes, replies, time. | $0.002 | |
| person.enrich | Full professional profile from a public LinkedIn profile URL or a work email: name, headline, about, location and the complete role history. | $0.005 | |
| contact.find | Find a professional email from a person and company. | $0.016 | |
| contact.verify | Verify deliverability of a professional email: valid, invalid, or unknown, with catch-all and mail-server details. | $0.002 | |
| linkedin.invite | Send a connection request from your connected account, with an optional note (300 characters). Already connected or already invited comes back as a miss, never as a duplicate send. | $0.009 | |
| email.send | Send an email from one of your inboxes, or reply within a thread. You are the sender of record: consent and unsubscribe handling are yours. | $0.004 | |
One prepaid balance covers every row. Capabilities marked coming soon are listed but not yet executable.
FAQ#
Is it allowed to build a lead list from LinkedIn comments?
The comments are public and the capabilities return what is publicly visible, through providers who handle collection; nothing behind a login. What you do next is governed by platform terms and by data protection law where the contact lives, which in the EU means a lawful basis before you send. Public availability is not consent, and the guide's rule of never referencing the comment is also the polite one.
Why not just filter by job title?
Because a title does not tell you who works for the vendor, who is a certified partner, or who is a freelancer wearing the buyer's title. Under a launch post the vendor's own team comments more than anyone, and they match a title filter perfectly. The exclusion question is the one that saves the paid lookups.
Do I need a judge model, or can my agent do the sorting?
Your agent can read and decide, one frontier call per row, and that is what most teams do today. A judge model that returns probabilities is cheaper by two orders of magnitude and, more usefully, tells you which rows it is unsure about, so a person reads a fifth of the list instead of all of it. Either way, write the buyer brief and the exclusion list first; they are the whole prompt.
How do I know an enrichment record is stale?
Compare the record's company with the current company on the public profile, and treat a mismatch as a previous job until a person says otherwise. On our run 17 of 90 records were a job behind, 7 with a valid-looking email at the old employer. Add a code rule the model cannot see: the email's domain must match the company's domain.
What API pulls the comments under a LinkedIn post?
social.comments takes one public post URL on LinkedIn (also YouTube, TikTok, Instagram and Reddit) and returns the comments with author, profile URL, text and time as JSON, priced per comment at the limit you request. social.posts on a LinkedIn profile or company page returns the recent posts with their reply counts, which is how you pick the busiest thread.
How do I turn LinkedIn commenters into verified emails?
person.enrich on the public profile for the title and company, person.enrich pinned to the Apollo route for the current domain and a work email, contact.find on the domain for the ones Apollo has no address for, and contact.verify on every address before it goes near a sending domain. history first, so you never buy a record twice.
Run this today
Sign up, get $1 of credit, and the first call in this guide costs a fraction of a cent. One key, one balance, price shown before every call.
Get started →Keep reading
Social profile, post and comment data (X, Reddit, LinkedIn, TikTok, Instagram, YouTube)
Public profiles and recent posts for personalization that survives contact with a reader, plus the keyword search that finds people with the problem.
Outbound · 6 minWaterfall email enrichment without the waterfall bill
The thing enrichment platforms charge a platform fee to orchestrate, as one call with one price and no credits to pre-buy.
Outbound · 7 minContact enrichment: email finder, verification and company data
The four calls behind a CRM row that is actually actionable, and the cache policy that keeps them from being expensive.




Install the skill once and Claude Code, Codex, Cursor and the rest discover these capabilities, check the price, then run them.
Install the agent skill →Reading this as an agent? This guide as markdown: /use-cases/competitor-commenters-to-leads.md · every guide: /use-cases/llms.txt · RSS