# Twitter Profile Scraper (X) (`sfoln/x-profile-lookup`)

Scrape X (Twitter) profiles by handle, URL or user ID: followers, following, post count, bio, website, location, verification, join date and pinned posts, one JSON record per account. Suspended accounts are flagged. $1 per 1,000 profiles; invalid handles are free.

- Family: Social media data
- Categories: Social media, Lead generation, Automation
- Availability: on request (private on Apify). Email contact@sfoln.com with subject "Access request: Twitter Profile Scraper (X) (sfoln/x-profile-lookup)" before calling; calls fail until it is public.
- JSON: https://www.sfoln.com/actors/x-profile-lookup.json
- MCP: https://mcp.apify.com?tools=sfoln/x-profile-lookup
- REST (sync): POST https://api.apify.com/v2/actors/sfoln~x-profile-lookup/run-sync-get-dataset-items
- REST (async): POST https://api.apify.com/v2/actors/sfoln~x-profile-lookup/runs

Twitter Profile Scraper (X) looks up X (Twitter) accounts by handle, profile URL or numeric user ID and returns one normalized profile record per account: follower and following counts, total posts, bio with expanded links, website, location, blue-check and verification type, join date, avatar and banner, pinned posts and automation labels. Built for influencer vetting, CRM enrichment, audience research and AI agents that need a quick, structured answer about an account.

## Price per delivered record

| Event | Price | Per 1,000 | Charged for |
| --- | --- | --- | --- |
| X profile (`x-profile-looked-up`) | $0.001 | $1 / 1,000 | Charged once per X (Twitter) handle or user id for which a profile was returned, or for which the upstream confirmed the account does not exist or is suspended/unavailable. |

Pay-per-event, USD, billed by Apify; no platform usage charge. Only records with status `ok` are charged. Cap a run with `maxTotalChargeUsd`. Apify free plan: up to 10 per run.

## Run

```bash
curl -X POST "https://api.apify.com/v2/actors/sfoln~x-profile-lookup/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"handles":["apify","https://x.com/NASA"]}'
```

MCP client configuration:

```json
{
  "mcpServers": {
    "apify": {
      "type": "http",
      "url": "https://mcp.apify.com?tools=sfoln/x-profile-lookup"
    }
  }
}
```

Example prompt: Look up the X profiles @apify and @NASA and compare their followers, post counts, verification and join dates.

## Input

Paste X (Twitter) handles or profile URLs, and/or numeric user ids. Each account produces one dataset record with a normalized profile and a `status` field.

| Field | Type | Default | Meaning |
| --- | --- | --- | --- |
| `handles` | array | — | Handles or profile URLs: X handles (with or without @) or profile URLs such as https://x.com/nasa, one per line. Duplicates are removed. Accounts on the Apify free plan can process up to 10 profiles per run (handles and user ids together). |
| `userIds` | array | — | Numeric user ids: Optional numeric X user ids (e.g. 11348282), one per line. Looked up in addition to the handles. |
| `maxItems` | integer | `5000` | Max profiles: Safety cap on the number of profiles looked up in this run. |
| `concurrency` | integer | `3` | Concurrency: Parallel upstream lookups (1–5). |
| `includeRaw` | boolean | `false` | Include raw upstream response: Attach the unmodified TwitterAPI.io payload to each record under `raw` (larger output). |

Example input:

```json
{
  "handles": [
    "apify",
    "https://x.com/NASA"
  ]
}
```

## Output

One record per input item with `status` (`ok` is charged; `not_found`, `error`, `skipped_*` are free) and `charged`. The run stores an `OUTPUT` summary record.

| Field | Type | Meaning |
| --- | --- | --- |
| `input` | string | object | Input: The input item this record corresponds to. |
| `status` | string | Status: ok \| not_found \| error \| skipped_invalid \| skipped_budget \| skipped_free_plan |
| `charged` | boolean | Charged: Whether this record incurred a pay-per-event charge. |
| `chargedEvent` | string | Charged event: Pay-per-event event charged for this record. |
| `source` | string | Source: Upstream data source (twitterapi = TwitterAPI.io). |
| `fetchedAt` | string | Fetched at: ISO timestamp. |
| `error` | object | Error: code / message when status is not ok. |
| `warnings` | array | Warnings: Non-fatal notes (e.g. stopped early). |
| `found` | boolean | Found: true when a live profile was returned. |
| `handle` | string | null | Handle: @handle without @. |
| `userId` | string | null | User id: Numeric user id. |
| `name` | string | null | Name: Display name. |
| `bio` | string | null | Bio: Profile description with t.co links expanded. |
| `location` | string | null | Location: Free-text location. |
| `url` | string | null | Website: Website link from the profile (expanded). |
| `profileUrl` | string | null | Profile URL: https://x.com/<handle> |
| `followers` | integer | null | Followers: Follower count. |
| `following` | integer | null | Following: Following count. |
| `tweets` | integer | null | Posts: Total posts incl. replies and reposts (statusesCount). |
| `likes` | integer | null | Likes given: Posts this account liked (favouritesCount). |
| `mediaCount` | integer | null | Media: Media posts count. |
| `isBlueVerified` | boolean | null | Blue check: Has a blue check (X Premium). |
| `verifiedType` | string | null | Verified type: e.g. Business, Government; null for none. |
| `profileImageUrl` | string | null | Avatar URL: Profile picture URL. |
| `coverImageUrl` | string | null | Banner URL: Header image URL. |
| `createdAt` | string | null | Joined: Account creation time (ISO 8601). |
| `isAutomated` | boolean | null | Automated: Labelled as an automated account. |
| `automatedBy` | string | null | Automated by: Operator handle for automated accounts. |
| `canDm` | boolean | null | Open DMs: Accepts direct messages from anyone. |
| `possiblySensitive` | boolean | null | Sensitive: Profile marked possibly sensitive. |
| `withheldInCountries` | array | Withheld in: Country codes where the account is withheld. |
| `pinnedTweetIds` | array | Pinned post ids: Ids of pinned posts. |
| `unavailable` | boolean | Unavailable: Account suspended / deactivated / otherwise unavailable. |
| `unavailableReason` | string | null | Unavailable reason: e.g. suspended. |
| `unavailableMessage` | string | null | Unavailable message: Message shown by X. |

Example record:

```json
{
  "input": "NASA",
  "found": true,
  "handle": "NASA",
  "userId": "11348282",
  "name": "NASA",
  "bio": "There's space for everybody. ✨",
  "location": "Pale Blue Dot",
  "url": "https://www.nasa.gov/",
  "profileUrl": "https://x.com/NASA",
  "followers": 89123456,
  "following": 178,
  "tweets": 72015,
  "likes": 16432,
  "mediaCount": 28761,
  "isBlueVerified": true,
  "verifiedType": "Government",
  "profileImageUrl": "https://pbs.twimg.com/profile_images/…_normal.jpg",
  "coverImageUrl": "https://pbs.twimg.com/profile_banners/11348282/1696976373",
  "createdAt": "2007-12-19T20:20:32.000Z",
  "isAutomated": false,
  "automatedBy": null,
  "canDm": false,
  "possiblySensitive": false,
  "withheldInCountries": [],
  "pinnedTweetIds": [
    "1843000000000000000"
  ],
  "unavailable": false,
  "unavailableReason": null,
  "unavailableMessage": null,
  "status": "ok",
  "charged": true,
  "chargedEvent": "x-profile-looked-up",
  "source": "twitterapi",
  "fetchedAt": "2026-10-14T10:00:00.000Z"
}
```

## Related

- [Twitter (X) Account Audit – Engagement](https://www.sfoln.com/actors/x-account-overview.md) (`sfoln/x-account-overview`)
- [Twitter Followers Scraper (X)](https://www.sfoln.com/actors/x-followers.md) (`sfoln/x-followers`)
- [Twitter Following Scraper (X)](https://www.sfoln.com/actors/x-following.md) (`sfoln/x-following`)

Publisher: SFOLN LLC, contact@sfoln.com. Catalogue: https://www.sfoln.com/catalog.json. Agent guide: https://www.sfoln.com/agents.md.
