# X / Twitter Account Origin Intelligence (`arjun_code/x-twitter-account-origin-scraper`) Actor

Extract X/Twitter account origin signals by screen name, including account\_based\_in, app/source, username change count, last username change time, and public profile metadata

- **URL**: https://apify.com/arjun\_code/x-twitter-account-origin-scraper.md
- **Developed by:** [Arjun AI](https://apify.com/arjun_code) (community)
- **Categories:** Agents, Social media, SEO tools
- **Stats:** 13 total users, 8 monthly users, 97.4% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 account profile analyzeds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## X Twitter Account Origin Intelligence

Extract account-origin signals and public profile metadata from X/Twitter by screen name.

Most profile scrapers focus on biographies and follower counts. This Actor also returns harder-to-find account provenance fields, including:

- `account_based_in` - the country or region associated with the account
- `source` - the signup or application source reported by X
- `username_changes.count` - the number of recorded username changes
- `username_changes.last_changed_at_msec` - the latest recorded username-change time
- `created_country_accurate` - whether X marks the creation-country signal as accurate
- `rest_id` - the account's numeric X user ID

Use it for account provenance checks, OSINT research, risk review, creator research, lead enrichment, and social media monitoring.

### Quick start

Enter one or more X/Twitter screen names in the Actor input and click **Start**:

```json
{
  "screenNames": [
    "fxtrader",
    "@elonmusk",
    "https://x.com/axiaisacat"
  ]
}
```

Each input can be a plain username, an `@handle`, or a full `x.com`/`twitter.com` profile URL. The Actor converts every accepted format to a plain username before requesting X. Duplicate accounts are removed after normalization, so `fxtrader`, `@fxtrader`, and `https://x.com/fxtrader` are queried only once.

### Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `screenNames` | `string[]` | Yes | One account per item as `fxtrader`, `@fxtrader`, or `https://x.com/fxtrader`. Empty and duplicate values are ignored. |

The Actor uses Apify Proxy by default. Proxy settings and account credentials are managed internally and are not part of the public Actor input.

### Output

Each requested account is stored as one item in the default dataset. A result contains the requested screen name and a nested `profile` object:

```json
{
  "screen_name": "goocarlos",
  "profile": {
    "account_based_in": "United States",
    "source": "United States App Store",
    "created_country_accurate": true,
    "rest_id": "14046502",
    "username_changes": {
      "count": "1",
      "last_changed_at_msec": "1664180698550"
    },
    "user_created_at": "Wed Feb 27 04:22:21 +0000 2008",
    "description": "CEO & Founder",
    "entities": {
      "description": {}
    },
    "is_blue_verified": true,
    "business_account": {},
    "creator_subscriptions_count": 0,
    "has_graduated_access": true,
    "favourites_count": 2754,
    "followers_count": 27422,
    "friends_count": 923,
    "listed_count": 349,
    "location": "San Jose, CA",
    "media_count": 487,
    "user_name": "Luyu Zhang",
    "normal_followers_count": 27422,
    "possibly_sensitive": false,
    "has_custom_timelines": true,
    "needs_phone_verification": false,
    "profile_banner_url": "https://pbs.twimg.com/profile_banners/14046502/example",
    "profile_image_url_https": "https://pbs.twimg.com/profile_images/example_normal.jpg",
    "protected": false,
    "user_screen_name": "goocarlos",
    "statuses_count": 2928,
    "verified": false,
    "utc_offset": 0,
    "url": ""
  }
}
```

Values in this example are illustrative. Fields may be empty when X does not provide them for an account.

If a requested username does not exist or the account is unavailable, the Actor records the condition and continues with the remaining usernames:

```json
{
  "screen_name": "unknown_user",
  "status": "not_found",
  "error": "X user @unknown_user was not found or is unavailable."
}
```

Unavailable-account records are not charged as `profile-result` events.

If X cannot be reached after the initial request and two retries, the Actor writes an uncharged failure record for that username and continues with the remaining inputs:

```json
{
  "screen_name": "example_user",
  "status": "request_failed",
  "error": "Network request for @example_user failed after 3 attempts."
}
```

Retryable network failures and HTTP `401`, `403`, `404`, `429`, and `5xx` responses switch both the credential and Apify Proxy session. A `429` response uses a short retry delay. Genuine unavailable-user responses remain `not_found` and are not retried.

### Output fields

#### Account origin and history

| Field | Description |
| --- | --- |
| `account_based_in` | Country or region associated with the account. |
| `source` | Signup or application source reported by X. |
| `created_country_accurate` | Whether X marks the creation-country signal as accurate. |
| `username_changes` | Object containing the recorded change count and latest change timestamp in Unix milliseconds. |
| `rest_id` | Numeric X user ID used as a stable account identifier. |

#### Identity

| Field | Description |
| --- | --- |
| `user_name`, `user_screen_name`, `user_created_at` | Identity fields returned by the detailed profile response. |
| `profile_image_url_https` | HTTPS profile image URL from the detailed profile. |
| `profile_banner_url` | Profile banner URL, when available. |
| `description` | Public profile biography. |
| `entities` | Structured links and entities associated with public profile text. |
| `location` | Self-declared profile location. |
| `url` | Public profile URL field. |

#### Audience and activity

| Field | Description |
| --- | --- |
| `followers_count` | Public follower count. |
| `normal_followers_count` | Normal follower count reported by X. |
| `friends_count` | Number of accounts followed. |
| `favourites_count` | Number of liked posts. |
| `statuses_count` | Number of posts and reposts reported by X. |
| `media_count` | Number of media posts. |
| `listed_count` | Number of public lists containing the account. |
| `creator_subscriptions_count` | Creator subscription count reported by X. |

#### Account state

| Field | Description |
| --- | --- |
| `is_blue_verified` | Whether the account currently has X Blue verification. |
| `verified` | Legacy verification flag. |
| `protected` | Whether the account is protected. |
| `possibly_sensitive` | Sensitive-content account flag. |
| `business_account` | Business-account metadata returned by X. |
| `has_graduated_access` | Graduated-access state returned by X. |
| `has_custom_timelines` | Whether custom timelines are enabled for the account. |
| `needs_phone_verification` | Phone-verification requirement reported by X. |
| `utc_offset` | Legacy UTC offset value. |

### Run with the API

Replace `YOUR_APIFY_TOKEN` with your Apify API token.

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/arjun_code~x-twitter-account-origin-scraper/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"screenNames":["elonmusk","axiaisacat"]}'
```

The request starts an Actor run. Use the run's default dataset ID from the API response to retrieve results after the run succeeds.

### Run with Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("arjun_code/x-twitter-account-origin-scraper").call(
    run_input={"screenNames": ["elonmusk", "axiaisacat"]}
)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

### Run with JavaScript

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('arjun_code/x-twitter-account-origin-scraper').call({
    screenNames: ['elonmusk', 'axiaisacat'],
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Pricing

This Actor uses pay-per-event pricing:

- Event: `profile-result`
- Price: **$0.0005 per profile result**
- Equivalent price: **$0.50 per 1,000 profile results**

One `profile-result` event is charged for each successfully retrieved profile. `not_found` and `request_failed` records are written to the dataset without a `profile-result` charge. Your final run price depends on the number of profiles produced. Platform usage may be billed separately when that option is enabled in the Actor's Store pricing configuration; check the pricing section shown by Apify before starting a run.

### Use cases

- Verify account-origin signals during OSINT research
- Review username-change history and stable numeric user IDs
- Enrich creator, influencer, lead, or customer records
- Support social media monitoring and account risk analysis
- Compare public audience, activity, and verification metadata

Try the ready-made [X Twitter Account Origin Data Extractor](https://apify.com/arjun_code/x-twitter-account-origin-scraper/examples/x-twitter-account-origin-scraper) example, or enter your own screen names in the Actor input.

### Continue your X research workflow

| Goal | Actor |
| --- | --- |
| Discover public accounts by keyword, profession, niche, or location | [X (Twitter) People Search Scraper](https://apify.com/arjun_code/x-twitter-people-search-scraper) |
| Export followers or accounts followed by one or more profiles | [X Followers & Following Scraper — No Login](https://apify.com/arjun_code/x-twitter-followers-followings-scraper) |
| Inspect account origin, signup source, and username-change history | [X Twitter Account Origin Intelligence](https://apify.com/arjun_code/x-twitter-account-origin-scraper) |

A typical workflow is: discover relevant accounts, export their public audiences, then inspect origin signals for selected profiles.

### Limitations

- Results depend on data currently returned by X/Twitter and individual fields may be empty or unavailable.
- Account-origin signals are reported by X and should not be treated as independent proof of a person's identity, nationality, or physical location.
- Suspended, deleted, renamed, nonexistent, or otherwise unavailable accounts are returned with `status: "not_found"`, and the Actor continues processing the remaining usernames.
- Authentication, rate-limit, server, and network failures are retried up to two times. Each retry switches the credential and Apify Proxy session. If all attempts fail, an uncharged `request_failed` item is written and the Actor continues with the next username.
- X may change its response structure or access controls, which can temporarily affect availability.
- A single run processes screen names sequentially and writes each result immediately, so larger lists take longer to complete but completed items are preserved if a later request fails.

### Privacy and responsible use

This Actor processes publicly accessible X/Twitter account and profile metadata. Use the results only for lawful purposes and in accordance with applicable privacy laws, X's terms, and Apify's terms. Do not use account-origin signals alone to make high-impact decisions about individuals.

### Support

If a run fails or a field is unexpectedly missing, open an issue from the Actor's **Issues** tab and include the run ID. Do not post API tokens, cookies, or other credentials in public issues.

# Actor input Schema

## `screenNames` (type: `array`):

Enter one account per line as a username (fxtrader), @handle (@fxtrader), or full X profile URL (https://x.com/fxtrader). Equivalent inputs are normalized and queried only once.

## Actor input object example

```json
{
  "screenNames": [
    "fxtrader"
  ]
}
```

# Actor output Schema

## `results` (type: `string`):

Structured account origin and profile metadata stored 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 = {
    "screenNames": [
        "fxtrader"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("arjun_code/x-twitter-account-origin-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 = { "screenNames": ["fxtrader"] }

# Run the Actor and wait for it to finish
run = client.actor("arjun_code/x-twitter-account-origin-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 '{
  "screenNames": [
    "fxtrader"
  ]
}' |
apify call arjun_code/x-twitter-account-origin-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,arjun_code/x-twitter-account-origin-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/NSpWIO5XhAaphQnz5/builds/mKnv5TzQgjWxtC8nW/openapi.json
