# TikTok User Profile Scraper: Business Leads (`simpleapi/tiktok-user-profile-scraper`) Actor

TikTok User Profile Scraper: Business Leads extracts TikTok creator profiles, usernames, bios, profile URLs, follower counts, business details, contact links, emails, and social profiles. Ideal for B2B lead generation, influencer outreach, prospecting, and market research.

- **URL**: https://apify.com/simpleapi/tiktok-user-profile-scraper.md
- **Developed by:** [SimpleAPI](https://apify.com/simpleapi) (community)
- **Categories:** Social media, Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

### TikTok Lead Scraper — Business Profiles, Bio Emails and Links

This TikTok lead generation scraper turns a list of TikTok handles, numeric user IDs, or
profile links into a lead sheet: the full public profile payload plus a contact layer parsed
from each creator's bio — `bioEmail`, `bioWebsiteUrl`, the bio link resolved past link-in-bio
shorteners (`resolvedBioUrl`), other social handles mentioned in the bio (`bioSocialHandles`),
and business-account signals promoted to top-level columns (`companyName`, `category`,
`commerceUserLevel`, `isBusinessAccount`). It's built for sales, agency, and influencer-outreach
teams who need a TikTok B2B contact list without opening profiles by hand. Every field comes
straight off the public profile page at request time, ready for CRM import.

### 🧭 What is TikTok Lead Scraper?

TikTok Lead Scraper: Business Leads is an Apify Actor that looks up TikTok creator and brand
profiles you supply — by `@handle`, numeric user ID, or full profile URL — and returns one
structured JSON row per lead. No TikTok account or login is required; it reads only the public
profile page. Key capabilities, all read from the source code:

- **Three ways to identify a lead** — handle, numeric user ID, or profile URL, mixed freely in
  the same run (plus the original base-actor key names `usernames`/`userIds`/`urls`, still
  accepted for backward compatibility).
- **Bio-derived contact extraction** — email, a website mention, and other social handles
  parsed out of the bio text (`signature`), on by default.
- **Bio-link shortener resolution** — Linktree, Beacons, Lnk.Bio, Carrd, Stan Store, and 15
  other known link-in-bio domains get followed to their real destination URL.
- **Business-account promotion** — company name, category, and commerce tier pulled out of
  nested TikTok objects into clean top-level lead columns.
- **Optional business-only filter** — keep only leads TikTok flags as a business/commerce
  account.
- **Deduplication** — repeat lookups of the same creator across your input lists are collapsed
  to one row.

### 📦 What data can I extract with TikTok Lead Scraper?

Every dataset row carries the lead/business layer this actor adds on top of the complete public
profile payload — every key below is read directly from the row-building code, not just the
default dataset view.

#### Lead & business fields (this actor's own layer)

| Field | Type | Description |
| --- | --- | --- |
| `unique_id` | string | TikTok handle (no `@`) — the row's identifier and dedupe key. |
| `nickname` | string | Display name on the profile. |
| `profile_url` | string | null | Canonical `https://www.tiktok.com/@<unique_id>` link; `null` if the handle could not be read. |
| `isBusinessAccount` | boolean | `true` when TikTok flags the account as commerce/business (`with_commerce_entry` or `account_type == 3`). |
| `companyName` | string | null | Company name, promoted from the nested `biz_account_info.rba_user_info.company_name`. `null` if TikTok has none on file. |
| `category` | string | Business category TikTok assigns the account; empty string if none. |
| `commerceUserLevel` | integer | camelCase alias of `commerce_user_level` (same value, listed again below), added as a clean lead column. |
| `bioEmail` | string | null | Email parsed from the bio text, including `name (at) domain.com` obfuscation. `null` if none found. |
| `bioEmailIsCorporate` | boolean | null | `true` if `bioEmail`'s domain is not on the actor's personal-webmail list (gmail.com, googlemail.com, yahoo.com, yahoo.co.uk, outlook.com, hotmail.com, live.com, icloud.com, me.com, aol.com, protonmail.com, proton.me, mail.com, msn.com). `null` when no email was found. |
| `bioWebsiteUrl` | string | null | First non-TikTok, non-image URL mentioned in the bio text. Only the **first** match is captured, even if the bio mentions more than one. `null` if none. |
| `resolvedBioUrl` | string | null | The profile's bio-link field, followed past a known shortener to its real destination; unresolved (same URL) if it isn't a recognized shortener. `null` if the account has no bio link. |
| `bioUrlIsShortener` | boolean | `true` if `resolvedBioUrl` came from following a recognized shortener domain. |
| `bioSocialHandles` | string | Other platforms mentioned in the bio (Instagram, YouTube, X/Twitter, Snapchat, Telegram, Discord), formatted `platform:@handle`, comma-separated. Only the first mention per platform is captured. Empty string if none. |
| `hasContactInfo` | boolean | `true` if any email, website, social handle, or bio link was found — a one-glance lead-qualification flag. |
| `scrapedAt` | string | UTC timestamp the row was collected, `YYYY-MM-DDTHH:MM:SSZ`. |

> When `extractContactInfo` is `false`, all seven contact fields above come back `null`/empty
> and `hasContactInfo`/`bioUrlIsShortener` come back `false` — the underlying profile fields are
> unaffected either way.

#### Full public-profile fields (base payload, unchanged)

| Field | Type | Description |
| --- | --- | --- |
| `account_type` | integer | `3` if commerce/business, else `0`. |
| `ad_virtual` | boolean | TikTok's `isADVirtual` flag. |
| `aweme_count` / `visible_videos_count` | integer | Total video count (same value on both keys). |
| `avatar_thumb`, `avatar_medium`, `avatar_larger`, `avatar_168x168`, `avatar_300x300` | object | Each is `{uri, url_list, url_prefix}` for that avatar size. |
| `bio_secure_url` | string | TikTok's link-safety redirect wrapper for `bio_url`; empty string if no bio link. |
| `bio_url` | string | Raw, unresolved bio-link URL as set by the creator. |
| `biz_account_info` | object | `{added_contact_and_link_list, android_download_app_link, coupon_list, ios_download_app_link, leads_gen: {action_name, business_data, has_leads_gen, page_id, schema_url}, permission_list, rba_user_info: {company_name}}`. |
| `can_message_follow_status_list` | array | Constant `[0, 1, 2, 4]`. |
| `commerce_user_info` | object | `{ad_revenue_rits}`. |
| `commerce_user_level` | integer | Numeric commerce tier (same value promoted to `commerceUserLevel` above). |
| `custom_verify` | string | TikTok's custom verification label text, if any. |
| `enterprise_verify_reason` | string | `"Verified account"` when `verified` is `true`, else empty string. |
| `favoriting_count` | integer | Videos the account has liked (TikTok's `diggCount`). |
| `follow_status` / `follower_status` | integer | Numeric relation/follower-status codes from TikTok. |
| `follower_count` / `following_count` | integer | Follower / following counts. |
| `forward_count` | integer | Share/forward count. |
| `has_open_favorite` | boolean | Whether the Liked-videos tab is public. |
| `ins_id` | string | Linked Instagram ID, if set. |
| `is_acquaintance`, `is_block`, `is_blocked`, `is_effect_artist`, `is_star` | boolean | TikTok relationship/status flags, passed through as-is. |
| `live_commerce` | boolean | Whether live shopping is enabled. |
| `live_push_notification_status` / `post_push_notification_status` | integer | TikTok notification-preference codes (default `2`). |
| `message_chat_entry` | boolean | Whether direct messages are open. |
| `mplatform_followers_count` | integer | Cross-platform follower stat. |
| `music_tab_info` | object | `{show_artist_pick_videos}`. |
| `original_musician` | object | `{digg_count, music_count, music_used_count, new_release_clip_ids}` — populated for musician accounts. |
| `privacy_setting` | object | `{following_visibility}`. |
| `profile_tab_type` | integer | Numeric profile-tab layout code. |
| `recommend_reason_relation` | string | TikTok's recommend-reason text, if present. |
| `room_id` | integer | Live-room ID if currently live, else `0`. |
| `sec_uid` | string | TikTok's internal `sec_uid`. |
| `secret` | integer | TikTok's `secret` account flag as an int. |
| `share_info` | object | `{now_invitation_card_image_urls, share_desc, share_title, share_url}`. |
| `short_id` | string | Legacy short numeric ID, or `"0"` if unset. |
| `show_effect_list`, `show_favorite_list`, `show_messaging_entrance_on_profile` | boolean | Profile-tab visibility flags. |
| `signature` | string | The bio text itself — source of the contact fields above. |
| `signature_language` | string | Bio language code, or `"un"` if unknown. |
| `story_status` | integer | TikTok story-feature status code. |
| `supporting_ngo` | object | Nonprofit-affiliation block if present; `{}` otherwise. |
| `tab_settings` | object | `{private_tab: {private_tab_style, show_private_tab}, repost_tab: {repost_tab_all_visible, show_repost_tab_other}}`. |
| `total_favorited` | integer | Total likes received across the account's videos. |
| `twitter_id` / `twitter_name` | string | Linked X/Twitter account, if set. |
| `uid` | string | TikTok's internal numeric user ID. |
| `unique_id` | string | The handle (see lead table above). |
| `verification_type` | integer | Numeric verification-type code. |
| `watch_status` | boolean | TikTok's watch-status flag. |
| `with_commerce_enterprise_tab_entry` / `with_commerce_entry` | boolean | Commerce-tab entry flags — the source of `isBusinessAccount`. |
| `with_new_goods` | boolean | Whether the account has new product listings flagged. |
| `youtube_channel_id` / `youtube_channel_title` | string | Linked YouTube channel, if set. |
| `verified` | boolean | TikTok's blue-check verification flag. |
| `is_private` | boolean | `true` if the account is set to private. |
| `friend_count` | integer | Mutual-follow ("friend") count. |
| `tt_seller` | boolean | TikTok Shop seller flag. |

#### Contact & lead-qualification fields

`bioEmail`, `bioEmailIsCorporate`, `bioWebsiteUrl`, `resolvedBioUrl`, `bioUrlIsShortener`,
`bioSocialHandles`, and `hasContactInfo` are the fields that actually drive an outreach
decision. They exist only because the creator put them in their public bio or bio-link — there
is no email lookup, no guessing, and no phone-number extraction anywhere in this actor (TikTok
bios do not reliably carry phone numbers). A row with `hasContactInfo: false` simply means the
bio had no parsable contact signal at the time of the run.

#### Business & targeting fields

`isBusinessAccount`, `companyName`, `category`, and `commerceUserLevel` are the fields you filter
and segment leads on — e.g. keep only confirmed business accounts, or split creators by
`category` for niche outreach lists. `follower_count`, `verified`, and `is_private` are useful
secondary segmentation signals for prioritizing a large lead list.

### 🛠️ Why not build this yourself?

TikTok does not render profile data as plain HTML — it hydrates the page from a JSON blob
inside a `<script id="__UNIVERSAL_DATA_FOR_REHYDRATION__">` tag, and the shape of that JSON
drifts: this actor's parser tries three different key paths (`webapp.user-detail` and two
fallback shapes) before it gives up on a page. Numeric-ID lookups sometimes need a mobile-host
retry (`m.tiktok.com`) when the `www` share URL doesn't hydrate, and TikTok can return a
verification/CAPTCHA challenge page instead of profile data. To work around blocking, the actor
escalates through Apify's datacenter proxy, then falls back to a sticky residential-proxy
session (with its own internal retry loop) before it marks a lead as failed — none of this is
configurable per lead by hand-rolling `requests` calls; it's built into the fetch path here.
Building and maintaining this — hydration-shape drift, challenge detection, and proxy
escalation — is ongoing work; running it as a maintained Actor avoids re-solving it per project.

### 💡 How to use data extracted from TikTok profiles

#### Sales & B2B outreach teams

Feed a batch of `leadUsernames` or `leadUserIds` (from a CRM export, a hashtag-research list, or
a spreadsheet of prospects) with `onlyBusinessAccounts: true`. Every saved row carries
`bioEmail`, `companyName`, `category`, and `follower_count` — enough to prioritize outreach by
company and skip creators with no bio contact at all (`hasContactInfo: false`).

#### Agencies running outreach for clients

Run the same lead list on a schedule and diff `bioEmail`/`resolvedBioUrl` against the last run to
catch creators who've changed their bio-link destination or added a business email since the
last check — useful for keeping a client's influencer-outreach list current without re-checking
profiles by hand.

#### Market research and intelligence

Pull a set of brand or creator handles in a niche and look at the spread of `category`,
`commerceUserLevel`, and `isBusinessAccount` to see how many run TikTok Shop-enabled accounts
versus personal creator accounts, and which commerce tier they sit on.

#### AI agents and automated pipelines

Because the actor runs as a standard Apify Actor with a JSON input and a JSON dataset output, it
plugs into any agent framework that can call the Apify API — an agent can pass a batch of handles
in, poll for the run to finish, and read `bioEmail`/`isBusinessAccount` back out for automated
lead scoring or CRM enrichment, no bespoke scraping code required.

### 🔼 Input sample

At least one lead identifier — across `leadUsernames`, `leadUserIds`, `leadProfileUrls`, or the
legacy `usernames`/`userIds`/`urls` keys — is required for the run to do anything; the schema
itself does not mark any field `required`, but a run with none supplied logs an error and exits.

| Parameter | Required | Type | Description | Example Value |
| --- | --- | --- | --- | --- |
| `leadUsernames` | No | array | TikTok handles, with or without `@`. | `["nike", "@gymshark"]` |
| `leadUserIds` | No | array | Numeric TikTok user IDs, as digit strings. | `["208464585232822272"]` |
| `leadProfileUrls` | No | array | Full TikTok profile URLs. | `["https://www.tiktok.com/@nickiminaj"]` |
| `usernames` | No | array | Legacy alias of `leadUsernames` (base-actor key, still accepted). | `["nike"]` |
| `userIds` | No | array | Legacy alias of `leadUserIds`. | `["208464585232822272"]` |
| `urls` | No | array | Legacy alias of `leadProfileUrls`. | `["https://www.tiktok.com/@nike"]` |
| `extractContactInfo` | No | boolean, default `true` | Parse bio email/website/social handles into the lead fields. | `true` |
| `resolveBioLinkShorteners` | No | boolean, default `true` | Follow known link-in-bio shorteners to their real destination. Only applies when `extractContactInfo` is `true`. | `true` |
| `onlyBusinessAccounts` | No | boolean, default `false` | Only save leads with `isBusinessAccount: true` (still fetched, just not saved/charged otherwise). | `false` |
| `maxRetries` | No | integer, default `3`, min `0`, max `10` | Per-fetch retries on network errors before giving up on a lead. | `3` |
| `requestGapMs` | No | integer, default `750`, min `0`, max `60000` | Pause between one lead lookup and the next, in milliseconds. | `750` |
| `proxyConfiguration` | No | object | Standard Apify Proxy picker (`useApifyProxy`, groups). | `{"useApifyProxy": true}` |

```json
{
  "leadUsernames": ["nike", "gymshark"],
  "onlyBusinessAccounts": true,
  "extractContactInfo": true
}
```

⚠️ **`maxRetries: 0` and `requestGapMs: 0` don't actually take effect.** Both are read as
`input.get(key) or default` in the source — and in that expression `0` is falsy, so a `0` you
enter silently falls back to the default (`3` retries, `750` ms) instead of being honored as
zero. If you're trying to disable retries or remove the pacing gap entirely, that isn't
achievable through the input right now; plan around the defaults as the effective floor.

A second real pitfall: `leadUserIds` only gets the automatic `m.tiktok.com` mobile-host retry
when the value is all digits. Paste a `sec_uid` or any non-numeric ID into that field and the
actor still attempts the lookup, but loses that fallback path and is more likely to fail.

### 🔽 Output sample

One dataset row per unique lead (deduplicated by `unique_id`), pushed the moment it's collected.
Below is one representative row with the lead/business layer plus a slice of the base profile
payload — see the full field tables above for every key the actor writes.

```json
{
  "unique_id": "nike",
  "nickname": "Nike",
  "profile_url": "https://www.tiktok.com/@nike",
  "isBusinessAccount": true,
  "companyName": "Nike, Inc.",
  "category": "Sporting Goods",
  "commerceUserLevel": 1,
  "commerce_user_level": 1,
  "bioEmail": "partnerships@nike.com",
  "bioEmailIsCorporate": true,
  "bioWebsiteUrl": "https://nike.com",
  "resolvedBioUrl": "https://nike.com/promo",
  "bioUrlIsShortener": true,
  "bioSocialHandles": "instagram:@nike",
  "hasContactInfo": true,
  "follower_count": 9800000,
  "following_count": 12,
  "total_favorited": 210000,
  "aweme_count": 412,
  "verified": true,
  "is_private": false,
  "friend_count": 3,
  "tt_seller": false,
  "signature": "Just Do It. partnerships@nike.com",
  "sec_uid": "MS4wLjABAAAA...",
  "uid": "208464585232822272",
  "scrapedAt": "2026-07-30T10:15:00Z"
}
```

Dataset export works through the standard Apify Console/API options — JSON, CSV, Excel, and the
other formats the platform's dataset export supports.

### 🎯 How do you filter and target the right leads?

This actor's targeting comes from **which identifiers you feed it and which toggles you leave
on**, not a location/category search — it's a bulk lookup, not a directory crawl. Three axes
matter:

1. **Identifier type** — handles are the most forgiving; numeric IDs get an automatic mobile-host
   retry only when they're pure digits; profile URLs skip guesswork entirely. Mix all three
   freely in one run.
2. **Business-account filtering** — `onlyBusinessAccounts: true` keeps only leads TikTok flags
   as commerce/business accounts. Non-matching leads are still fetched and logged, just not
   saved or charged, so you can test the filter without wasting the run on unwanted rows.
3. **Contact-extraction depth** — `extractContactInfo` on/off decides whether the bio gets
   parsed at all; `resolveBioLinkShorteners` on/off (only meaningful when extraction is on)
   decides whether a shortened bio link gets followed to its real destination or left as-is.

```json
{ "leadUsernames": ["nike", "gymshark", "duolingo"], "onlyBusinessAccounts": true }
```

```json
{ "leadUserIds": ["208464585232822272"], "extractContactInfo": false }
```

```json
{ "leadProfileUrls": ["https://www.tiktok.com/@nickiminaj"], "resolveBioLinkShorteners": false, "requestGapMs": 1500 }
```

### ▶️ Want to try other SimpleAPI scrapers?

| Scraper | What it extracts |
| --- | --- |
| Linkedin Lead Scraper: Seniority & Department Filters | LinkedIn leads filtered by seniority level and department instead of raw keyword search. |
| LinkedIn Company Profile Scraper & Ad Library Creatives | LinkedIn company profile data plus live ad-library creative pulls. |
| LinkedIn Mass Company Profile Finder By Country & Name | Bulk LinkedIn company profile lookup by country and company name. |
| Instagram Profile Post Scraper With Engagement Analytics | Instagram profile data plus post-level engagement metrics. |
| Snapchat User Stories Scraper With Creator Profile Insights | Snapchat Stories and Highlights plus creator/profile analytics. |
| WhatsApp Group Links Scraper & Precision Search Filters | WhatsApp group link discovery with precision search filters. |

### 🔌 How to extract TikTok lead data programmatically

The actor runs like any Apify Actor — one API call starts the run, and the results land in a
standard dataset you read back over the Apify API.

#### Python example

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_API_TOKEN>")

run = client.actor("<your-username>/tiktok-user-profile-scraper-business-leads").call(
    run_input={
        "leadUsernames": ["nike", "gymshark"],
        "onlyBusinessAccounts": True,
    }
)

for lead in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(lead["unique_id"], lead["bioEmail"], lead["isBusinessAccount"])
```

#### Export to spreadsheets or CRM

Export the dataset as CSV from the Apify Console (or via the API) and map `unique_id` →
Handle, `nickname` → Name, `bioEmail` → Email, `companyName` → Company, and
`isBusinessAccount` → a business-account flag column in your CRM import template.

### ⚖️ Is it legal to scrape TikTok profiles for leads?

Scraping publicly visible TikTok profile pages is generally lawful — this actor reads only pages
anyone can already view in a browser without logging in, and never accesses private accounts.
Because the output includes personal data about identifiable individuals (bio text, and any
email address a creator put in their own bio), GDPR and CCPA still apply to how you store and use
it once collected, even though the data itself is public. You need a lawful basis for holding
and using that data — for outreach, that's typically legitimate interest, alongside honoring
opt-out/deletion requests. Consult legal counsel for commercial applications involving bulk
storage of personal data.

### ❓ FAQ

#### What happens if a lead's TikTok account is deleted, banned, or private?

The lead is not saved. A deleted or banned account returns a "not found" or "no profile data"
result and is logged as a failed lookup, not pushed to the dataset. A private account can still
be fetched (its public shell is visible) but comes back with `is_private: true` and typically no
usable bio content.

#### Can I get contact info (email, website) along with each lead's profile data?

Yes, by default. `extractContactInfo` is `true` unless you turn it off, and every saved row
includes `bioEmail`, `bioWebsiteUrl`, `resolvedBioUrl`, `bioSocialHandles`, and `hasContactInfo`
alongside the full profile fields — no separate run required.

#### How accurate is the contact and business data?

The actor returns the bio text, bio link, and business flags exactly as they appear on the
public profile at request time. Accuracy depends entirely on whether the creator keeps their
own bio current — there's no cross-checking against a third-party source. Treat `bioEmail` and
`companyName` as a starting point and validate before a large outreach send.

#### How many leads can I get per run?

There is no `maxItems`/limit parameter in the input schema. The number of leads processed equals
however many handles, IDs, and/or URLs you supply across `leadUsernames`, `leadUserIds`, and
`leadProfileUrls` (plus the legacy keys) combined — runtime scales with your list size and the
`requestGapMs` pacing between lookups.

#### How do I get only TikTok business accounts, not personal creators?

Set `onlyBusinessAccounts: true`. Every lead is still fetched and logged, but only rows with
`isBusinessAccount: true` are saved to the dataset and charged — personal-creator leads are
skipped, not billed.

#### Does TikTok Lead Scraper work with Claude, ChatGPT, and AI agent frameworks?

There's no dedicated MCP server for this actor. It's callable as a standard Apify Actor run
through the Apify API by any agent framework that can make an HTTP call and poll a run — pass a
lead list in, read `bioEmail`/`isBusinessAccount` back out of the dataset.

#### Can I use this without a TikTok account, login, or API key?

Yes. The actor only needs your Apify account/API token to run — it fetches public TikTok pages
with no TikTok login, session cookie, or TikTok API credential of any kind.

#### Will my existing TikTok User Profile Scraper input JSON still work here?

Yes. `usernames`, `userIds`, `urls`, `proxyConfiguration`, `maxRetries`, and `requestGapMs` are
all still accepted as the base actor's original key names — this variant reads its own
`leadUsernames`/`leadUserIds`/`leadProfileUrls` first and falls back to the legacy keys.

### 🏁 Conclusion

TikTok Lead Scraper: Business Leads turns a plain list of handles, IDs, or profile links into a
structured lead sheet — full public profile data plus bio-derived email, website, resolved
bio-link destination, and business-account signals promoted to top-level columns, with no phone
numbers invented or guessed. It's built for sales, agency, and market-research teams who need a
TikTok prospect list without opening profiles one by one. Start a run from the Apify Console with
a batch of handles and `onlyBusinessAccounts` on to see it filter down to real business leads.

# Actor input Schema

## `leadUsernames` (type: `array`):

🎪 One handle per line (examples: nike, @nike). 💡 Leave blank if you use lead IDs or lead links instead.

## `leadUserIds` (type: `array`):

📋 Long number IDs only (digits as text). ✏️ Skip this section if you're using handles or profile links.

## `leadProfileUrls` (type: `array`):

🎬 Paste TikTok profile links here. 💤 You can leave this empty when handles or IDs are enough.

## `usernames` (type: `array`):

Same as "Lead handle(s)" above — the base actor's original key name.

## `userIds` (type: `array`):

Same as "Lead user ID(s)" above — the base actor's original key name.

## `urls` (type: `array`):

Same as "Lead profile link(s)" above — the base actor's original key name.

## `extractContactInfo` (type: `boolean`):

✅ ON (default): adds bioEmail, bioWebsiteUrl, resolvedBioUrl and bioSocialHandles to every row. ❌ OFF: skips parsing and those fields come back null/empty (profile data is unaffected either way).

## `resolveBioLinkShorteners` (type: `boolean`):

✅ ON (default): if a lead's bio link points at a known link-in-bio shortener (Linktree, Beacons, Lnk.Bio, etc.), follow it to the real destination URL. ❌ OFF: keeps the shortener link as-is (faster, one less request per lead). Only applies when contact extraction is ON.

## `onlyBusinessAccounts` (type: `boolean`):

❌ OFF (default): every successfully-fetched lead is saved. ✅ ON: only leads with isBusinessAccount = true are saved to the dataset (still fetched and logged, just not charged/saved).

## `maxRetries` (type: `integer`):

Per-fetch retries on network errors before giving up on a lead. Example: maxRetries=3 (default) retries up to 3 times per URL attempted.

## `requestGapMs` (type: `integer`):

Pause between one lead lookup and the next, in milliseconds. Default is 750.

## `proxyConfiguration` (type: `object`):

⚙️ Standard Apify Proxy picker — choose groups or turn off if you don't need it. 💚 Your choice!

## Actor input object example

```json
{
  "leadUsernames": [
    "nike"
  ],
  "leadUserIds": [
    "208464585232822272"
  ],
  "leadProfileUrls": [
    "https://www.tiktok.com/@nickiminaj"
  ],
  "extractContactInfo": true,
  "resolveBioLinkShorteners": true,
  "onlyBusinessAccounts": false,
  "maxRetries": 3,
  "requestGapMs": 750,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All scraped items in the Actor's 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 = {
    "leadUsernames": [
        "nike"
    ],
    "leadUserIds": [
        "208464585232822272"
    ],
    "leadProfileUrls": [
        "https://www.tiktok.com/@nickiminaj"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("simpleapi/tiktok-user-profile-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 = {
    "leadUsernames": ["nike"],
    "leadUserIds": ["208464585232822272"],
    "leadProfileUrls": ["https://www.tiktok.com/@nickiminaj"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("simpleapi/tiktok-user-profile-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 '{
  "leadUsernames": [
    "nike"
  ],
  "leadUserIds": [
    "208464585232822272"
  ],
  "leadProfileUrls": [
    "https://www.tiktok.com/@nickiminaj"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call simpleapi/tiktok-user-profile-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,simpleapi/tiktok-user-profile-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/dYDdsBBuGYkn92dyQ/builds/cbDvM0iqWncHtFP7r/openapi.json
