Twitter/X Leads Scraper - Profile Email Finder avatar

Twitter/X Leads Scraper - Profile Email Finder

Deprecated

Pricing

from $14.00 / 1,000 leads

Go to Apify Store
Twitter/X Leads Scraper - Profile Email Finder

Twitter/X Leads Scraper - Profile Email Finder

Deprecated

Turn X/Twitter searches, hashtags, or handles into contactable author leads — collapse tweets to unique profiles, extract emails from bios + linked sites, follower/verified filters, 0-100 lead score, dedupe, and AI cold openers. Export CSV/JSON.

Pricing

from $14.00 / 1,000 leads

Rating

0.0

(0)

Developer

Flash Scrape

Flash Scrape

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

6 days ago

Last modified

Share

⚠️ RETIRED — this Actor returns no data

Retired 2026-08-09. Do not run it: it delivers zero rows on purpose.

Why. This Actor was a wrapper. Every run called two public Apify Store Actors (apidojo/tweet-scraper and apidojo/twitter-user-scraper) to get the tweets, the bio and the bio-link website. This account's Apify plan is not allowed to run public Store Actors, so those calls returned zero items to every buyer while the run still reported SUCCEEDED — a green run with an empty dataset. It also cannot be rebuilt to talk to X directly: X/Twitter profile and search data is not reachable without an API key or a logged-in session, so the bio, website and email columns described below cannot be filled honestly.

What it costs you. Nothing. Pricing is per delivered lead (the lead event); there is no priced actor-start event. The retirement stub pushes no rows and charges nothing, so a run costs $0.

Use instead: flash_scraper/local-business-leads — verified business contact data (name, website, email, phone, lead score).

Everything below describes the Actor as it was before retirement and is kept for reference only. It no longer runs.


Twitter/X Leads Scraper — search terms and hashtags into unique author profiles

Give this Actor search terms, hashtags, or @handles and get back one row per unique author instead of a noisy tweet timeline: handle, display name, bio, follower count, verified status, location, bio-link website, engagement rate, a 0–100 lead score, and — when the author actually published one — an email.

Built for founder and creator outreach, agency prospecting, partnership scouting, and CRM enrichment. No X/Twitter login or API key needed.

Two things to know before you run it, both covered in detail below:

  1. A profile with neither an email nor a website is delivered to you free. You are only ever charged for a lead that carries a contact channel. Filters run before billing, so filtering cuts your bill rather than just tidying the output.
  2. The email column is the thin one. X bios rarely print an address. Most emails have to be found by crawling the author's bio-link website, so authors with no bio link usually end up with no email. See How full is the email column? — including what we have and have not measured.

What you get

ColumnWhere it comes from
handle, name, profile_urlTweet author card or profile lookup
bioProfile lookup (description)
websiteProfile lookup — the profile's website field, or an expanded link from the bio text
email, email_status, extra_emailsAn address printed in the bio, or one found by crawling the bio-link website
followers, verified, verified_type, locationProfile lookup
engagement_rate, tweets_seenAveraged across the author's tweets that matched your search
lead_scoreComputed — see Lead score
linkedin, facebook, site_twitterFound while crawling the author's website
icebreakerOptional AI cold opener (your own API key, charged separately)
matched_termWhich of your search terms surfaced this author
contactabletrue when the row has an email or a website — the rows you are charged for

How it works

This Actor is a pipeline over two Apify Store data sources. Understanding the split matters, because it is where both the cost and the data quality come from.

Stage 1 — discovery (only when you give search terms or hashtags). apidojo/tweet-scraper returns tweets. Every matching tweet is collapsed to one row per unique author handle, and likes + retweets + replies are averaged across each author's collected tweets into an engagement_rate.

The tweet author object is a display card — handle, name, avatar, follower count, verified flags. It carries no bio and no website. That is the whole reason stage 2 exists.

Stage 2 — profile lookup (on by default). apidojo/twitter-user-scraper is queried with the handles that survived the cheap filters. Its output carries description (the bio) and the expanded website link. This is the only source of the bio text and the bio-link website, which are in turn the only sources of an email. With fetchProfiles off, the bio, website and email columns are empty on every row — and, because a row with no contact channel is never billed, such a run is mostly free and mostly useless.

Then, optionally, enrichEmails visits each author's bio-link website — home, /contact, /contact-us, /about — to pull a contact address plus LinkedIn/Facebook links. Link-in-bio pages (Linktree, Beacons, Stan) are followed one hop further, but only to domains matching the author's own name or handle, so a sponsor's address never lands in your list.

Handles skip stage 1 entirely. If you supply handles and no search terms, no tweets are bought at all — each handle is resolved by the flat-fee profile lookup. Buying a page of tweets for an account you already named by hand adds cost without finding a single new person. Turn on scanHandleTweets if you specifically want an engagement_rate for those handles.

Input

Provide at least one of searchTerms, hashtags, or handles. Every field is optional — an empty input runs the documented example search so a first API call still returns something.

FieldTypeDefaultDescription
presetstring""cold_email, founder_outreach, or creator_partnerships. Only fills settings you left at their default; anything you set yourself always wins.
searchTermsarrayKeywords/phrases to search. Matching tweets are collapsed to their authors.
hashtagsarrayHashtags with or without #; treated as extra search terms.
handlesarrayAccounts you already know. naval, @naval, x.com/naval and https://x.com/naval all work.
maxItemsinteger200How many tweets the keyword search scans. Not the number of leads. Clamped at 50,000.
maxLeadsinteger0Cap on profiles looked up and delivered. Applied before the paid profile lookup, so it bounds that cost too. 0 = no cap.
sortstring""Top, Latest, or Latest + Top. The tweet source recommends Top when a query returns thin results.
tweetLanguagestring""Restrict to one language so you do not pay for bios you cannot read. Blank returns every locale.
minimumFavoritesinteger0Skip tweets below this like count. Runs at the source, before any tweet is paid for — the cheapest spam filter available here.
postedWithinDaysinteger0Only search the last N days, to skip dormant accounts.
scanHandleTweetsbooleanfalseAlso buy tweets for named handles, purely to compute their engagement rate.
minFollowers / maxFollowersinteger0Follower band. Authors whose count could not be read are excluded whenever either bound is set.
onlyVerifiedbooleanfalseKeep only accounts with a check — legacy or X Premium (blue).
onlyWithWebsitebooleanfalseKeep only authors with a real bio link (a t.co shortener or a link back to X does not count).
onlyWithEmailbooleanfalseKeep only authors where an email was actually found. Expect it to cut hard.
fetchProfilesbooleantrueStage 2. Leave it on — it is where bio, website and email come from.
enrichEmailsbooleantrueCrawl each bio-link website for an address. Included in the per-lead price.
writeOpenersbooleanfalseWrite an AI cold opener per lead. Charged as a separate event. Needs your own key.
llmProvider / llmApiKey / llmModelstringopenai / — / —Your own OpenAI or Anthropic key. Used once per run, never stored.
{
"searchTerms": ["ai founder", "saas indie hacker"],
"hashtags": ["buildinpublic"],
"maxItems": 200,
"maxLeads": 25,
"minFollowers": 1000,
"onlyWithWebsite": true,
"sort": "Top",
"tweetLanguage": "en"
}

That example uses onlyWithWebsite rather than onlyWithEmail on purpose: a website is the realistic contact channel on X, and it is also what the email crawl needs to have any chance of finding an address.

Output

One row per unique author, sorted best lead first. Export to CSV, JSON, or Excel from the Output tab.

The block below shows the shape and types of a row — which keys exist and what goes in them. It is a schematic, not a row captured from a real run, and the values in it are not a claim about what any particular search will return.

{
"handle": "somefounder",
"name": "Some Founder",
"bio": "Building an AI tool for agencies. Ex-Google. hello@somestartup.com",
"email": "hello@somestartup.com",
"email_status": "found",
"website": "https://somestartup.com",
"followers": 24800,
"verified": true,
"verified_type": null,
"location": "Berlin",
"engagement_rate": 1.8,
"tweets_seen": 3,
"matched_term": "ai founder",
"profile_url": "https://x.com/somefounder",
"contactable": true,
"lead_score": 85
}

Rows where the website crawl found more also carry extra_emails (up to 5 more addresses) and any linkedin / facebook / site_twitter links from that site. site_twitter is the X account linked from the website — it is not always the same account as profile_url, which is why it has its own name. With writeOpeners on, eligible leads also get icebreaker.

Lead score

lead_score is the sum of five components that add to exactly 100:

ComponentPoints
Email found40
Website found15
Verified (legacy or blue)5
Follower band15 for 5k–500k, 10 for 1k–5k or 500k–2M, 5 for anything else non-zero
Engagement rate25 at ≥5%, 18 at ≥3%, 10 at ≥1%, 5 below that

The schematic row above scores 85: 40 email + 15 website + 5 verified + 15 follower band + 10 engagement (1.8% lands in the ≥1 bucket). A row with no email and no website tops out at 45, which is the point — the score is mostly a contactability score.

engagement_rate is kept to four significant digits rather than a fixed number of decimals, so a very large account's genuinely tiny rate reads as 3.909e-05 instead of collapsing to 0.0. A null there means "no engagement counts were available", which is scored differently from a measured zero.

Pricing

This Actor charges two pay-per-event prices. Exact figures are on the Pricing tab; at the time of writing:

EventFree planTop plans
lead — one contactable author delivered$0.02$0.014
opener — one AI cold opener written$0.03$0.021

Three things follow from that, and they are the honest version of "pay per result":

  • A lead with neither an email nor a website costs you nothing. It is still delivered, still scored, still in your CSV — just not billed. Rows removed by your filters are not delivered and not billed either.
  • The opener costs more than the lead. If you turn on writeOpeners, budget $0.05 per lead that gets one, not $0.02. You also pay your own OpenAI/Anthropic bill on top, since the openers are written with your key.
  • Delivery happens before the charge. Rows are written to the dataset and billed in the same operation, so a crash or a timeout can never leave you charged for leads that are not in your dataset. If you set a maximum total charge on the run, it truncates delivery to what fits your budget rather than handing over rows we cannot bill.

The upstream data sources are billed separately

This is the part most wrapper Actors do not tell you. This Actor starts two Apify Store Actors to get its data, and those runs carry their own published pay-per-event prices:

SourcePriceWhen you pay it
apidojo/tweet-scraper$0.0004 per tweet scannedOnly when you give search terms or hashtags
apidojo/twitter-user-scraper$0.004 per profile query + $0.0004 per profile returnedWhenever fetchProfiles is on (minimum 5 objects per run, imposed by that Actor)

So a run's total is roughly:

(tweets scanned x $0.0004) + (profiles looked up x $0.0044) + (contactable leads x $0.02)

Two consequences worth planning around:

  • Those upstream costs are incurred before your filters run, because filtering needs the data first. A run where onlyWithEmail matches nothing bills you $0 in leads but has already paid for the tweets and profiles it scanned. That is why maxItems and maxLeads exist, and why minimumFavorites, tweetLanguage and postedWithinDays — which filter at the source — are the cheapest filters here.
  • Start small. The Console form is pre-filled with maxItems: 50 and maxLeads: 25 precisely so your first run is cheap. Raise them once you have seen what your query actually returns.

Every run is bounded: this Actor passes an explicit spend cap to both upstream Actors derived from your own maxItems and maxLeads, and clamps maxItems at 50,000 tweets regardless of what you send.

Requirements

Your Apify plan must allow running Apify Store Actors. Both data sources are Store Actors, and this Actor calls them under your account. On a plan that does not permit that, the run fails with a clear message and charges you nothing — it does not quietly return an empty dataset.

This Actor requests limited permissions: it can run those two Store Actors and write to its own storages, and it cannot touch anything else in your Apify account.

Tips / FAQ

How full is the email column?

We are not publishing a fill-rate number, because we have not measured one on this build. The account this Actor is developed on cannot currently run public Store Actors, so we have not been able to complete an end-to-end run and count real rows. Quoting a percentage we did not measure would be a guess dressed up as data.

What we can tell you is mechanical, and it is what actually determines your result:

  • An email is found when the author printed one in their bio, or when one is published on the website they linked from their bio. There is no third source. X does not expose account emails, and this Actor does not guess or pattern-match addresses.
  • Therefore an author with no bio link and no address in their bio has no path to an email, and will come back with email_status: "missing".
  • onlyWithWebsite is the setting that most affects your outcome, because the website is what the email crawl works on.
  • Run it small firstmaxItems: 50, maxLeads: 25 — look at your own numbers for your own query, and scale from there. Different niches differ enormously; a query full of agencies and SaaS founders behaves nothing like one full of anonymous accounts.

Is maxItems the number of leads?

No — it is the number of tweets scanned before the author roll-up. How many unique authors a page of tweets contains depends entirely on the query, since one prolific account can own dozens of the tweets in a narrow search. Use maxLeads to cap the number of author profiles that are looked up and delivered.

Why authors instead of tweets?

Search results are tweets, but for outreach you need people. Every matching tweet is rolled up to its author, so the dataset is a deduped list of profiles. tweets_seen tells you how often each author matched.

How does deduplication work?

By handle only. An earlier version also collapsed rows sharing a website domain or an email, which silently deleted real, distinct people — two co-founders share a company domain, and any number of unrelated creators share github.com or substack.com as their bio link. The handle is the identity of a row here.

Why is verified true for accounts without a legacy checkmark?

Because X retired legacy verification in 2023 and almost every current check is X Premium. verified is true for either, and verified_type tells you which — blue, business, government, or null.

Why did writeOpeners produce nothing?

Either you left llmApiKey empty — in which case the run log and the run status both say so explicitly, and you were charged nothing — or the leads had empty bios. Openers are deliberately skipped for leads with no bio: an opener written from a display name alone is the generic filler a recipient deletes on sight, and it is not worth $0.03 to you. Openers are matched back to leads by handle, not by position, so a model that drops or merges an entry cannot shift every following opener onto the wrong person.

What happens if a data source fails halfway?

If the tweet search fails, the run fails — visibly, with the reason, and with nothing charged. If the profile lookup fails, the author rows found in stage 1 are still delivered, but without bios, websites or emails, which means none of them carry a contact channel and none of them are billed. If an upstream Actor times out after producing partial results, those results are used rather than thrown away, since they have already been paid for.

It reads public profile and tweet data only. Use the leads for legitimate outreach and follow X's terms plus anti-spam law (CAN-SPAM, GDPR).

Support: found a bug or need a feature? Open an issue on this Actor's Issues tab.