# Twitter Lead Scraper (`maximedupre/twitter-lead-scraper`) Actor

Collect public X profiles from handles, profile URLs, or one keyword or niche query. Get structured lead fields such as bios, audience counts, public emails, websites, and links, or collect follower and following account identifiers. No X login or API key is needed.

- **URL**: https://apify.com/maximedupre/twitter-lead-scraper.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Lead generation, Social media, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 lead profiles

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### 🎯 Turn public X profiles into useful lead rows

Sales teams, lead researchers, and developers can turn public X handles, @handles, and profile URLs into structured lead data. Each saved lead profile has its public identity and can include a bio, audience counts, public contact fields, a website, published links, and first-match trace data when available. You can also find profiles with one keyword or niche query, or collect follower and following account identifiers.

- Collect follower usernames for a public X account with **[Twitter Followers Scraper](https://apify.com/maximedupre/twitter-lead-scraper/examples/twitter-followers-scraper)**.
- Collect the accounts a public X account follows with **[Twitter Following Scraper](https://apify.com/maximedupre/twitter-lead-scraper/examples/twitter-following-scraper)**.
- Find public email addresses in X profiles with **[Twitter Email Scraper](https://apify.com/maximedupre/twitter-lead-scraper/examples/twitter-email-scraper)**.
- Build a lead list from public X account references with **[Twitter Lead Scraper](https://apify.com/maximedupre/twitter-lead-scraper/examples/twitter-lead-scraper)**.
- Enrich one public X profile with **[Twitter Profile Scraper](https://apify.com/maximedupre/twitter-lead-scraper/examples/twitter-profile-scraper)**.

#### 📇 Public X lead profiles and relationship accounts

Use lead profile mode for account handles, @handles, profile URLs, or one keyword or niche query. Lead rows keep the canonical identity and, when available, the submitted reference or discovery query. They can also include the public bio and location, follower and following counts, posts, follower tier, public emails, primary email, public phone, website, published links, verification, protection, account creation time, and profile image when available. Use relationship account mode to save follower or following usernames or numeric public user IDs with the target and relationship type.

Each eligible account is saved at its first match. If the same account appears again from another handle, URL, query, ID, or submitted value, the later match is ignored. Trace fields describe only the first saved match.

#### ▶️ Choose a profile or relationship run

1. Choose `leadProfiles` to collect enriched public profiles, or `relationshipAccounts` to collect follower or following identifiers.
2. For lead profiles, choose account references or one keyword or niche query.
3. For relationship accounts, choose followers or following, add one or more targets, and choose usernames or numeric user IDs.
4. Add lead filters or set a work limit when you need a smaller collection.
5. Run the Actor and open the default dataset.

Leave `maxCandidates` empty to return all available results until the source is exhausted. Leave `maxRelationshipAccounts` empty to return all available results until the source is exhausted.

#### ⚙️ Input

Choose `leadProfiles` or `relationshipAccounts`. `profileSearch` fields are used for lead profiles, and `relationshipSearch` fields are used for relationship accounts. Fields for the other mode are ignored. The filters apply only to lead profiles.

**Input fields**

| Field | Type | What it does |
|---|---|---|
| `resultType` | string | Selects `leadProfiles` for enriched profiles or `relationshipAccounts` for follower and following identifiers. |
| `profileSearch` | object | Groups the source settings for lead profile collection. |
| `profileSearch.findProfilesBy` | string | Chooses submitted account references or one keyword or niche query. |
| `profileSearch.accountReferences` | string\[] | Adds public X handles, @handles, or profile URLs to enrich. |
| `profileSearch.keywordQuery` | string | Finds public X accounts or influencers from one keyword or niche query. |
| `profileSearch.maxCandidates` | integer | Sets an optional cap for the one query. Leave it empty to return all available results until the source is exhausted. |
| `relationshipSearch` | object | Groups the settings for follower or following collection. |
| `relationshipSearch.collectAccountsBy` | string | Selects public accounts that follow the target or public accounts that the target follows. |
| `relationshipSearch.relationshipTargets` | string\[] | Adds public X usernames or numeric public user IDs as relationship targets. Usernames may include or omit `@`. |
| `relationshipSearch.maxRelationshipAccounts` | integer | Sets an optional cap for each target. Leave it empty to return all available results until the source is exhausted. |
| `relationshipSearch.relationshipResultFormat` | string | Chooses usernames or numeric public user IDs for `accountIdentifier`. |
| `requireEmail` | boolean | For lead profiles, keeps only accounts that publish an email address. |
| `requireWebsite` | boolean | For lead profiles, keeps only accounts that publish a website. |
| `minFollowers` | integer | For lead profiles, keeps accounts with at least this many followers. |
| `maxFollowers` | integer | For lead profiles, keeps accounts with no more than this many followers. |
| `bioIncludeTerms` | string\[] | For lead profiles, keeps accounts whose bio mentions at least one chosen term. |
| `bioExcludeTerms` | string\[] | For lead profiles, removes accounts whose bio mentions at least one chosen term. |
| `locationContains` | string | For lead profiles, keeps accounts whose public location contains this text. |

**Example input**

This input is copied from a successful current-beta default-input run:

```json
{
  "resultType": "leadProfiles",
  "profileSearch": {
    "findProfilesBy": "accountReferences",
    "accountReferences": [
      "@apify"
    ]
  },
  "requireEmail": false,
  "requireWebsite": false,
  "relationshipSearch": {
    "collectAccountsBy": "followers",
    "relationshipResultFormat": "username"
  }
}
```

#### 🧾 Output

The default dataset contains one of two shapes, selected by `resultType`. Optional lead fields can be missing when the public source does not provide them.

**Lead profile**

| Field | Type | What it does |
|---|---|---|
| `recordType` | string | Is always `leadProfile` for this shape. |
| `userId` | string | Gives the canonical public X account identifier. |
| `username` | string | Gives the account username. |
| `displayName` | string | Gives the public display name. |
| `profileUrl` | string (URL) | Gives the canonical public X profile URL. |
| `submittedReference` | string (optional) | Keeps the handle or profile URL that first caused this row to be saved. |
| `discoveryQuery` | string (optional) | Keeps the keyword or niche query that first caused this row to be saved. |
| `bio` | string (optional) | Gives the public profile bio. |
| `location` | string (optional) | Gives the public profile location. |
| `followersCount` | integer (optional) | Gives the reported follower count. |
| `followingCount` | integer (optional) | Gives the number of accounts followed by this account. |
| `postsCount` | integer (optional) | Gives the reported public post or activity count. |
| `followerTier` | string (optional) | Gives the reported follower-size tier. |
| `emails` | array of strings (optional) | Lists public email addresses published by the account. |
| `primaryEmail` | string (email, optional) | Gives the primary public email address when present. |
| `phoneNumber` | string (optional) | Gives a phone number publicly published by the account. |
| `websiteUrl` | string (URL, optional) | Gives the resolved website URL published on the profile. |
| `publishedLinks` | array of strings (URLs, optional) | Lists other links published by the account. |
| `isVerified` | boolean (optional) | Says whether the source reports the account as publicly verified. |
| `isProtected` | boolean (optional) | Says whether the source reports the account as protected. |
| `createdAt` | string (date-time, optional) | Gives the account creation time reported by the source. |
| `profileImageUrl` | string (URL, optional) | Gives the public profile image URL. |

This complete lead row came from a successful current-beta run:

```json
{
  "recordType": "leadProfile",
  "userId": "1534392378890637314",
  "username": "jones_deakon",
  "displayName": "Deakon “showtime” jones",
  "profileUrl": "https://x.com/jones_deakon",
  "submittedReference": "https://x.com/jones_deakon",
  "bio": "Stillwater highschool, 6’2 190 Wr/CB coach: @chadcawood Email:deakonjones128@gmail.com co/2027 phone: 405-657-9283, ncaa id: 2403234469",
  "location": "Stillwater, OK",
  "followersCount": 1000,
  "followingCount": 2058,
  "postsCount": 393,
  "followerTier": "nano",
  "emails": [
    "deakonjones128@gmail.com"
  ],
  "primaryEmail": "deakonjones128@gmail.com",
  "phoneNumber": "405-657-9283",
  "websiteUrl": "https://t.co/dzHV0zWTlY",
  "publishedLinks": [
    "https://t.co/dzHV0zWTlY"
  ],
  "isVerified": true,
  "isProtected": false,
  "createdAt": "2022-06-08T04:30:36.000Z",
  "profileImageUrl": "https://pbs.twimg.com/profile_images/1967446812081455104/WFvhmDqx_normal.jpg"
}
```

**Relationship account**

| Field | Type | What it does |
|---|---|---|
| `recordType` | string | Is always `relationshipAccount` for this shape. |
| `relationshipType` | string | Says whether the account is a follower or a following account. |
| `relationshipTarget` | string | Gives the public username or numeric user ID used as the target. |
| `identifierType` | string | Says whether `accountIdentifier` contains a username or a numeric user ID. |
| `accountIdentifier` | string | Gives the collected public account username or numeric user ID. |

This complete relationship row came from a successful current-beta run:

```json
{
  "recordType": "relationshipAccount",
  "relationshipType": "followers",
  "relationshipTarget": "@apify",
  "identifierType": "username",
  "accountIdentifier": "FilipHorky"
}
```

#### 💳 Pricing

Pricing uses pay-per-event. The Store shows the current price for each event. An event is created only for its matching saved row.

**Lead profile**

One public X profile is saved to your dataset.

**Contact route**

A saved lead profile includes a public email address or website.

**Relationship account**

One public follower or following account identifier is saved to your dataset.

A run with no matching saved row does not create one of these row events.

#### 🔌 Integrations

Read the default dataset in Apify Console, use the Apify API, or export your rows for further work.

https://www.youtube.com/watch?v=bNACk1\_S\_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

#### ❓ FAQ

##### Can one run collect both profiles and relationships?

No. Choose one `resultType` for each run. Fields for the other mode are ignored, so run the Actor again when you need the other shape.

##### What happens when I leave a candidate or relationship limit empty?

The Actor returns all available results until the source is exhausted. This is not a promise that the source has more results or that every account can be returned.

##### What happens when the same account appears more than once?

The first eligible occurrence is saved. Later matches from another handle, URL, query, ID, or similar submitted value are ignored. The saved trace field describes only the first match.

##### Do relationship rows include full profile details?

No. A relationship row contains the relationship type, target, identifier type, and selected account identifier. Use lead profile mode when you need the enriched profile fields.

##### Are contact details guessed?

No. Email addresses, websites, and phone numbers come from public profile data. A value that the profile does not publish is left empty.

##### Can I use one keyword or niche query?

Yes. Choose `keywordQuery` in lead profile mode and enter one query. Profiles found by that query receive the same lead enrichment as profiles submitted directly.

##### Do I need an X login or API key?

No. The Actor reads publicly reachable X data and does not ask for an X login, password, or API key.

##### Why did my run return fewer rows than expected?

Filters and the available public source data can reduce the number of saved rows. A work limit is a cap, not a promise of a fixed number of rows.

### 📝 Changelog

**v0.0** (17-09-2026)

- Initial release.

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~twitter-lead-scraper/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- [Twitter Scraper](https://apify.com/maximedupre/twitter-scraper) to collect public X posts, profiles, and network members.
- [Twitter Organization Affiliates Scraper](https://apify.com/maximedupre/twitter-organization-affiliates-scraper) to map public accounts shown for X organizations.
- [Social Media Stats Checker](https://apify.com/maximedupre/social-media-stats-checker) to compare public X profile stats with other social platforms.
- [YouTube Lead Scraper](https://apify.com/maximedupre/youtube-lead-scraper) to find public creator email leads from YouTube.
- [Website Email Scraper](https://apify.com/maximedupre/website-emails-scraper) to find public emails on linked websites.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `resultType` (type: `string`):

Choose the kind of records to return. Lead profiles come from account references or one keyword or niche query. Relationship accounts come from followers or following.

## `profileSearch` (type: `object`):

Use Find profiles by to choose submitted account references or one keyword or niche query. The unused input is ignored when you run the other discovery method.

## `relationshipSearch` (type: `object`):

Use Collect accounts by to choose followers or following, then add public usernames or numeric user IDs as targets.

## `requireEmail` (type: `boolean`):

For lead profiles, keep only accounts that publish an email address. Leave this off to keep profiles with or without an email.

## `requireWebsite` (type: `boolean`):

For lead profiles, keep only accounts that publish a website. Leave this off to keep profiles with or without a website.

## `minFollowers` (type: `integer`):

For lead profiles, keep accounts with at least this many followers. Leave it empty to set no minimum.

## `maxFollowers` (type: `integer`):

For lead profiles, keep accounts with no more than this many followers. Leave it empty to set no maximum.

## `bioIncludeTerms` (type: `array`):

For lead profiles, keep accounts whose bio mentions at least one of these terms.

## `bioExcludeTerms` (type: `array`):

For lead profiles, remove accounts whose bio mentions at least one of these terms.

## `locationContains` (type: `string`):

For lead profiles, keep accounts whose public location contains this text. Leave it empty to set no location filter.

## Actor input object example

```json
{
  "resultType": "leadProfiles",
  "profileSearch": {
    "findProfilesBy": "accountReferences",
    "accountReferences": [
      "@apify"
    ]
  },
  "requireEmail": false,
  "requireWebsite": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

Open the result rows in the default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "resultType": "leadProfiles",
    "profileSearch": {
        "findProfilesBy": "accountReferences",
        "accountReferences": [
            "@apify"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/twitter-lead-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "resultType": "leadProfiles",
    "profileSearch": {
        "findProfilesBy": "accountReferences",
        "accountReferences": ["@apify"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/twitter-lead-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "resultType": "leadProfiles",
  "profileSearch": {
    "findProfilesBy": "accountReferences",
    "accountReferences": [
      "@apify"
    ]
  }
}' |
apify call maximedupre/twitter-lead-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maximedupre/twitter-lead-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/iSU0ZbRbdpEhJpoDZ/builds/UfN6SDmIjgXD3WTsy/openapi.json
