# X Twitter Brand Presence Mapper - Domain to Handle (`mambalabs/x-brand-presence-mapper`) Actor

Resolves a company domain to its official X (Twitter) handle, profile URL, follower count, bio and account age. Runs keyless out of the box; add your own X API key for full reliability at scale. Flat, Clay ready, one row per company.

- **URL**: https://apify.com/mambalabs/x-brand-presence-mapper.md
- **Developed by:** [Mamba Labs](https://apify.com/mambalabs) (community)
- **Categories:** Lead generation, Automation, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.45 / 1,000 company checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

### 🔎 What can X Twitter Brand Presence Mapper do?

Give it a company domain and it returns that company's official X (Twitter) account: the handle, the profile URL, the exact follower, following and post counts, verification status, bio and account creation date. One flat row per company, no login, no setup.

**It runs in two modes, and the key is optional.** Keyless, it resolves the handle for every company and reads counts from X's public endpoint, which X rate limits: on a large batch some rows come back with the handle and URL populated and the counts marked `not_extractable`. Add **your own X API bearer token** and that limit goes away: every row returns full metrics, reliably, at any batch size. The key raises effectiveness rather than unlocking the actor.

| 📦 What you get | ⚙️ Features and integrations |
|---|---|
| 🐦 **Official X handle and profile URL**, resolved from a domain<br>🔢 **Exact follower, following and post counts**<br>🕰️ **Account creation date**, bio and display name<br>🧾 **18 flat fields**, `snake_case`, one row per company | 🔑 **Runs keyless out of the box**, bring your own X API key for scale<br>🌐 **Domain first discovery** from the homepage `sameAs` markup<br>🛣️ **Route reported per row** in `x_fetch_route`<br>⬇️ **Export** to JSON, CSV, Excel, HTML or XML |

Bought by competitive intelligence teams, agency new business, and anyone rebuilding a social column after X's API pricing made the official route uneconomic.

> 🚫 **This is not a tweet scraper or a listening tool.** It returns the account and its counts, once per company. It does not read tweets, replies, mentions or search.

### 💡 Why use X Twitter Brand Presence Mapper?

**It starts from a domain, and the official X API cannot.** api.twitter.com needs a username. If you are holding a list of company domains, the username is exactly the thing you do not have. This actor resolves it from the company's own website, where X is declared on a measured 14 of 14 B2B homepages, the highest rate of any platform we map. That resolution step is the part no X tool sells.

**The counts are exact.** X serves the real integer on both routes, so follower numbers from this actor can be summed across a target list. Instagram, TikTok, YouTube, Threads and Facebook all round, and their totals are the platform's rounding rather than a measurement.

**Both modes are honest about what they returned.** A rate limited row says `not_extractable`, which means the account exists and X would not serve its numbers on that request. It never returns a zero, never returns a blank you could mistake for a zero, and never charges you for a count it did not deliver.

#### 🧭 Where the handle comes from

X is the most reliably declared platform in this whole family: 14 of 14 measured B2B homepages link their X account. So discovery is nearly always a direct read of the company's own site, which costs nothing and is the company vouching for its own account.

When the homepage says nothing, one web search runs, and anything it finds is identity checked against the domain and the company name before it ships. A candidate that fails that check is reported as `identity_mismatch` rather than published as an answer.

### 📋 What data can X Twitter Brand Presence Mapper extract?

Every row carries **18 flat fields**. These are the ones a buyer
actually filters and sorts on.

| Field | Type | Meaning |
|---|---|---|
| `degraded` | boolean | True when this row could not be produced normally, for example the company site was unreachable and no discovery could run. A degraded row is never charged. |
| `degradation_reason` | string | null | Why the row is degraded, in plain words. Null on a normal row. |
| `company_domain` | string | null | The company domain this row is about, normalized. Null when only a handle or a name was supplied. This is the join key across the whole Mamba Labs fleet. |
| `company_name` | string | null | The company name as supplied or derived. Improves search accuracy and is what the identity gate matches against. |
| `x_url` | string | null | Canonical x.com profile URL. The most reliable field on the row: it is resolved from the company own website and does not depend on X serving us anything. |
| `x_handle` | string | null | The resolved handle, without the leading @. |
| `x_followers` | integer | null | Exact follower count. X serves the real integer, so this can be summed across a list. Null when X rate limited the request, which is what x\_status reports as not\_extractable; supplying your own API key removes that. |
| `x_followers_exact` | boolean | null | True whenever a count was returned. X serves the exact integer on both routes, so it never rounds. Null when no count was available. |
| `x_following` | integer | null | How many accounts this account follows. Same availability as the follower count. |
| `x_tweet_count` | integer | null | Total posts on the account. Same availability as the follower count. |
| `x_verified` | boolean | null | Verification flag as X reports it. Null when no profile data was reachable. |
| `x_display_name` | string | null | The account display name. |
| `x_bio` | string | null | The account bio text. |
| `x_created_at` | string | null | When the account was created. Distinguishes an established brand account from one opened last month. |
| `x_fetch_route` | string | null | Which route produced the counts: official\_api when you supplied a bearer token, syndication when the public endpoint answered. Null when neither did. |
| `x_discovery` | string | null | How the handle was found: input\_handle, homepage\_sameas, homepage\_link, search or pattern\_guess. X is declared on 14 of 14 measured B2B homepages, so this is usually homepage\_sameas or homepage\_link and the handle is reliable. |
| `x_status` | string | ok, not\_found, not\_extractable, blocked, identity\_mismatch, auth\_failed or skipped. not\_extractable means the account exists and X rate limited this request, which is common in keyless mode on a large batch and goes away with your own API key. auth\_failed means the token you supplied was rejected. |
| `run_date` | string | ISO 8601 timestamp of this run. Social counts move, so a row without a date is a number with no shelf life. |

> ⚠️ **How to read these values.** `x_status: "not_extractable"` with a populated `x_url` means the account exists, here it is, and X rate limited this particular request. In keyless mode you will see some of these on a large batch. With your own API key they go away.

### 🛠️ How to find a company's X account

1. Put a company domain in `company_domain`.
2. **For full reliability at scale**, paste your own X API v2 bearer token into `xApiBearerToken`. Free at developer.x.com. Without it the actor still works; X just rate limits it. Your token is used for your run only and is never stored.
3. If you already know the handle, put it in `handle` to skip discovery.
4. For a list, pass an array of objects.

#### 🧪 Using it in Clay

Add an **Enrichment > Apify** column, pick this actor, map `company_domain`.

For a large Clay table, put your X bearer token in the actor input for the column. Every row in that column then uses your key and your rate budget, and none of them hit X's public rate limit.

For a small table, leave it empty. Keyless mode needs no setup and usually returns everything.

### 💵 How much does it cost?

Pay per event. You are charged for output, never for input.

| Event | Fires when | Price |
|---|---|---|
| `company-checked` | Once per company for which the discovery cascade completed and a non degraded row was produced, whether or not an X account was found. Does not fire on a degraded row, because on a degraded row no discovery was performed. | $0.0035 |
| `profile-resolved` | Once per company whose candidate X URL passed the identity gate. Fires on the validation work, not on a populated count. This is the event that carries the actor in keyless mode, because handle resolution succeeds whether or not X served a count. | $0.0030 |
| `follower-count-extracted` | Once per company where a numeric follower count was actually read, from either route. A rate limited row does not fire it and is not charged for the count, which is deliberate: an event firing on a not\_extractable row would be charging for the string not\_extractable. | $0.0025 |

> 💳 **What you are billed for.** **You are not charged for a count you did not get.** `follower-count-extracted` fires only when a number was actually read, so a rate limited row bills `company-checked` plus `profile-resolved` and nothing more.
>
> If the token you supply is rejected, the row reports `auth_failed` and the extraction event still does not fire.

**What the same coverage costs bought a la carte:** apidojo/twitter-user-scraper charges $0.0004 per item plus $0.0040 per profile URL query, so $0.0044, and it takes a handle as input. This actor is priced below that and adds the domain to handle resolution step, which that actor does not perform and which is the step a buyer holding a domain list is missing.

### ⌨️ Input

| Field | Type | Required | Meaning |
|---|---|---|---|
| `company_domain` | string | no | Bare company domain, for example shopify.com. Supply this or a handle. With a domain the actor runs full discovery; with a handle it skips straight to the fetch. |
| `company_name` | string | no | Optional. Improves search accuracy and is what the identity gate checks a discovered profile against, so supplying it reduces wrong matches. |
| `handle` | string | no | Optional. The X handle with or without the leading @, for example Shopify. Supplying it skips discovery and goes straight to the fetch. |
| `includeFollowerCounts` | string | no | When "true" (default) the profile page is fetched and the counts are extracted. Set "false" to resolve the profile URL only, which is cheaper and needs no proxy. Sent as a string for Clay compatibility. |
| `skipCache` | string | no | When "false" (default) a successful lookup is cached for seven days and reused. Set "true" to force a fresh fetch. Sent as a string for Clay compatibility. |
| `xApiBearerToken` | string | no | YOUR OWN X API v2 bearer token, free to create at developer.x.com. OPTIONAL: leave it empty and the actor still resolves handles, profile URLs and follower counts, but X rate limits the public route so on a large batch some rows return not\_extractable instead of counts. Supplying a token removes that limit and every row returns full metrics. Your token is used for your run only, is never stored, and is never shared with another run. |

```json
{
  "company_domain": "shopify.com",
  "company_name": "Shopify"
}
```

### 📤 Output

Exports to **JSON, CSV, Excel, HTML or XML**. One flat, snake\_case row per
company. No nested objects, so it drops straight into Clay, a spreadsheet or a
warehouse table without a flattening step.

```json
{
  "degraded": false,
  "degradation_reason": null,
  "company_domain": "shopify.com",
  "company_name": "Shopify",
  "x_url": "https://x.com/Shopify",
  "x_handle": "Shopify",
  "x_followers": 452243,
  "x_followers_exact": true,
  "x_following": 3423,
  "x_tweet_count": 37167,
  "x_verified": false,
  "x_display_name": "Shopify",
  "x_bio": "The entrepreneurship company",
  "x_created_at": "2008-11-03T18:33:14.000Z",
  "x_fetch_route": "syndication",
  "x_discovery": "homepage_sameas",
  "x_status": "ok",
  "run_date": "2026-08-22T19:23:45.055Z"
}
```

#### false versus null, and why the difference matters

`false` means we looked and the answer is no. `null` means we could not look,
or the platform withheld it. They are never interchangeable in this output. If
you filter for companies with no presence on this platform, filter on `false`,
because `null` rows are unknown rather than absent and including them will
overstate your list.

### 💡 Tips

- **Run it without a key first.** On a small list keyless mode usually returns everything, and it needs no setup at all.
- **Add a free X developer key before a big batch.** It takes minutes, it removes the rate limiting, and this actor is built to use yours rather than share one.
- **`x_created_at` is underrated.** An account opened this year on a company claiming a decade of history is a real signal.
- **Filter on `x_discovery`** if a wrong handle would be costly. `homepage_sameas` and `homepage_link` are the company's own declaration.

### ⚠️ Known limits

- **Keyless mode is rate limited by X, and the limit is real.** Measured 2026-08-22: bursts of requests from one exit returned HTTP 429 on every route tried, while a paced run returned exact counts for every company (Shopify 452,239, Figma 572,410, Stripe 289,139, Notion 527,471). So keyless works and does not scale. On a large batch expect a share of rows to come back `not_extractable`. Adding your own X API bearer token removes this entirely.
- **X could close the public route at any time.** If it does, keyless mode degrades to handle and URL only, reporting `not_extractable` for every count rather than returning zeros. Keyed mode is unaffected.
- **No posts, no engagement, no follower lists.** Account level presence only.
- **Your API key is your rate budget.** X's free tier is tight. A large Clay run on a free developer key will hit X's limits, and the row will say `not_extractable` when it does rather than failing the run.
- **Follower counts are a public vanity metric,** a proxy for reach rather than a measurement of it.

### ❓ FAQ

**Do I need an API key?**
No. It runs keyless out of the box and returns handles, URLs and counts. The key removes X's rate limiting, so on large batches it is the difference between some rows and every row.

**Why did some rows come back without a follower count?**
X rate limited those requests. The row says `not_extractable`, the handle and URL are still there, and you were not charged for the missing count. Add your own key and this stops.

**What does this do that the official X API cannot?**
Start from a domain. api.twitter.com needs a username. Resolving a company domain to its X handle is the step you are missing if you hold a domain list, and it is what this actor does before it fetches anything.

**Will you add a shared API key so nobody needs their own?**
No. A shared key on a public actor means one buyer's rate limit is spent by another, and the first heavy user starves everybody else. Your key is yours.

**What does `auth_failed` mean?**
The bearer token you supplied was rejected by X. Check that it is an API v2 bearer token and that it has not expired.

**Am I charged when the count is unavailable?**
No. The extraction event fires only on a number actually read.

### 🧩 Want other GTM data?

Mamba Labs builds a fleet of GTM enrichment actors that share one flat,
Clay-ready output convention, so their rows join on `company_domain` with no
cleaning step:

| | |
|---|---|
| 🕵️ [Agent Accessibility Auditor](https://apify.com/mambalabs/agent-accessibility-auditor) | 🤖 [AI Tooling Detector](https://apify.com/mambalabs/ai-tooling-detector) |
| 📡 [B2B Buying Signals Aggregator](https://apify.com/mambalabs/b2b-buying-signals-hiring-tech-stack-intent-for-clay) | 🚀 [Prospect Engine](https://apify.com/mambalabs/b2b-prospect-engine) |
| 📝 [Publishing Frequency Tracker](https://apify.com/mambalabs/blog-publishing-frequency) | ⏩ [Sequencer Lead Push](https://apify.com/mambalabs/clay-to-instantly-smartlead-push) |
| 🔄 [Company Change-Event Feed](https://apify.com/mambalabs/company-change-event-feed) | 🧭 [Company Discovery List Builder](https://apify.com/mambalabs/company-discovery-list-builder) |
| 🏢 [Company Firmographic Enricher](https://apify.com/mambalabs/company-firmographic-enricher) | 🪪 [Company Identity Resolver](https://apify.com/mambalabs/company-identity-resolver) |
| 🌐 [Company Social Presence Mapper](https://apify.com/mambalabs/company-social-presence-mapper) | 🏷️ [Contact Classifier](https://apify.com/mambalabs/contact-classifier) |
| 📬 [Domain Deliverability Checker](https://apify.com/mambalabs/domain-deliverability-checker) | 🔗 [Domain to LinkedIn URL Resolver](https://apify.com/mambalabs/domain-to-linkedin-url-resolver) |
| ✉️ [Work Email Waterfall Finder](https://apify.com/mambalabs/email-waterfall-orchestrator) | 🎪 [Event Presence Index](https://apify.com/mambalabs/event-presence-index) |
| 💰 [Funding and Press Signal Scanner](https://apify.com/mambalabs/funding-press-signal-scanner) | 🧑‍💼 [GTM Hiring Signal Scraper](https://apify.com/mambalabs/gtm-hiring-signal-scraper) |
| 📋 [Job Posting Monitor](https://apify.com/mambalabs/gtm-job-discovery) | 🧱 [Tech Stack Detector](https://apify.com/mambalabs/gtm-tech-stack-signal-scraper) |
| 🎯 [ICP Fit Scorer](https://apify.com/mambalabs/icp-account-lead-scoring-fit-scorer-0-100-for-clay) | 🔑 [Job Board Keyword Scanner](https://apify.com/mambalabs/job-board-keyword-signal-scanner) |
| ⚖️ [Legal Entity Resolver](https://apify.com/mambalabs/legal-entity-resolver) | 💼 [LinkedIn Company Page Mapper](https://apify.com/mambalabs/linkedin-company-presence-mapper) |
| 💬 [LinkedIn Post Tracker and Comment Capture](https://apify.com/mambalabs/linkedin-post-engager-capture) | 📸 [Instagram and Facebook Brand Mapper](https://apify.com/mambalabs/meta-brand-presence-mapper) |
| 📮 [Outbound Stack Detector](https://apify.com/mambalabs/outbound-infrastructure-fingerprint) | 📄 [Page Finder and Extractor](https://apify.com/mambalabs/page-finder-extractor) |
| 👤 [People Finder and Email Verifier](https://apify.com/mambalabs/people-finder) | 📌 [Pinterest Brand Presence Mapper](https://apify.com/mambalabs/pinterest-brand-presence-mapper) |
| 🏛️ [Government Contract Award Monitor](https://apify.com/mambalabs/public-award-monitor) | 📅 [Public Company Reporting Window Finder](https://apify.com/mambalabs/public-company-reporting-window-finder) |
| 👥 [Team Page People Extractor](https://apify.com/mambalabs/team-page-people-extractor) | 🎵 [TikTok Brand Presence Mapper](https://apify.com/mambalabs/tiktok-brand-presence-mapper) |
| 🏅 [Workplace Program Detector](https://apify.com/mambalabs/workplace-program-detector) | ▶️ [YouTube Channel Stats Extractor](https://apify.com/mambalabs/youtube-channel-transcript-extractor) |

> Every actor in the suite takes a domain or a company and returns one flat row,
> so they stack in the same Clay table without reshaping anything.

> 🛠️ **Need something custom built for you or your team?** Tell us what you are
> trying to find and we will build it. [Talk to Mamba Labs](https://mambabuilt.com/contact).

### 🆘 Support

Issues, field requests and bug reports: open an issue on the actor's Issues tab.
Mamba Labs reads every one.

> ℹ️ **Sourcing and legal.** Fields come from X's public profile surfaces, read without a login where a key is not supplied. Follower counts are a public vanity metric. If you supply your own X API key, that call is governed by your agreement with X, not ours.

Built by [Mamba Labs](https://apify.com/mambalabs).

# Actor input Schema

## `company_domain` (type: `string`):

Bare company domain, for example shopify.com. Supply this or a handle. With a domain the actor runs full discovery; with a handle it skips straight to the fetch.

## `company_name` (type: `string`):

Optional. Improves search accuracy and is what the identity gate checks a discovered profile against, so supplying it reduces wrong matches.

## `handle` (type: `string`):

Optional. The X handle with or without the leading @, for example Shopify. Supplying it skips discovery and goes straight to the fetch.

## `includeFollowerCounts` (type: `string`):

When "true" (default) the profile page is fetched and the counts are extracted. Set "false" to resolve the profile URL only, which is cheaper and needs no proxy. Sent as a string for Clay compatibility.

## `skipCache` (type: `string`):

When "false" (default) a successful lookup is cached for seven days and reused. Set "true" to force a fresh fetch. Sent as a string for Clay compatibility.

## `xApiBearerToken` (type: `string`):

YOUR OWN X API v2 bearer token, free to create at developer.x.com. OPTIONAL: leave it empty and the actor still resolves handles, profile URLs and follower counts, but X rate limits the public route so on a large batch some rows return not\_extractable instead of counts. Supplying a token removes that limit and every row returns full metrics. Your token is used for your run only, is never stored, and is never shared with another run.

## `source_tag` (type: `string`):

Internal attribution tag set by Mamba Labs on published task examples. Not required, and nothing depends on it. Leave it empty.

## Actor input object example

```json
{
  "company_domain": "shopify.com",
  "company_name": "Shopify",
  "includeFollowerCounts": "true",
  "skipCache": "false"
}
```

# Actor output Schema

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

Dataset of one flat row per company, with per platform status so a blocked fetch never reads as a zero.

# 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 = {
    "company_domain": "shopify.com",
    "company_name": "Shopify",
    "handle": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("mambalabs/x-brand-presence-mapper").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 = {
    "company_domain": "shopify.com",
    "company_name": "Shopify",
    "handle": "",
}

# Run the Actor and wait for it to finish
run = client.actor("mambalabs/x-brand-presence-mapper").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 '{
  "company_domain": "shopify.com",
  "company_name": "Shopify",
  "handle": ""
}' |
apify call mambalabs/x-brand-presence-mapper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mambalabs/x-brand-presence-mapper"
        }
    }
}

```

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/oLOgadhHUkNAyDA3w/builds/gQ44iy9ZUekwWtnW0/openapi.json
