# Tiktok Influencer Finder (`coregent/tiktok-influencer-finder`) Actor

TikTok Influencer Finder discovers TikTok creators by hashtag, keyword, niche, or seed profile, then returns outreach-ready leads with follower counts, bio details, public contact clues, and profile URLs. Use it for influencer research, lead generation, and creator sourcing.

- **URL**: https://apify.com/coregent/tiktok-influencer-finder.md
- **Developed by:** [Delowar Munna](https://apify.com/coregent) (community)
- **Categories:** Lead generation, Social media, Other
- **Stats:** 43 total users, 5 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 influencer results

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/platform/actors/running/actors-in-store#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 Influencer Finder

![TikTok Influencer Finder](https://raw.githubusercontent.com/coregentdevspace/tiktok-influencer-finder-assets/main/thumbnail-tiktok-influencer-finder.jpg)

Find TikTok creators by hashtag, keyword, niche, or seed profile — then filter and export outreach-ready influencer leads with follower counts, bio details, and public contact clues.

### What does this actor do?

**TikTok Influencer Finder** is an Apify Actor that discovers public TikTok creators for influencer outreach, market research, lead generation, and creator intelligence. It supports three discovery modes:

- **Hashtag discovery** — find creators active around hashtags like `#skincare`, `#gymtok`, or `#booktok`
- **Keyword/niche discovery** — find creators by search terms like "fitness coach", "AI productivity", or "travel creator Australia"
- **Seed profile discovery** — include known creators directly by username or profile URL

All three modes can be combined in a single run. Creators found across multiple sources are deduplicated with merged discovery lineage.

### Why use this actor?

- **Multiple discovery paths** in one actor — hashtags + keywords + seed profiles
- **Fast, reliable discovery** — browserless TikHub-backed endpoints for all three modes, with an automatic browser fallback if the fast path is unavailable
- **Creator-level output** — one row per creator, not per video
- **Discovery lineage** — every creator shows exactly why and how they were found
- **Contact clues** — public email, Instagram, YouTube, and external links extracted from bios
- **Filtering** — follower range and verification status
- **Scoring** — qualification (outreach-readiness) and relevance (niche match) scores with human-readable reasons
- **Deduplication** — same creator found via multiple hashtags = one row with merged lineage
- **Country and language** — best-effort country annotation and language inference from bio text
- **CSV-friendly** — flat, stable schema ready for Sheets, Airtable, CRM, and AI workflows

### Input

#### Discovery inputs

At least one of these is required:

| Parameter | Type | Description |
|-----------|------|-------------|
| `hashtags` | string\[] | Hashtag names or URLs to discover creators from |
| `keywords` | string\[] | Keywords or niche phrases for user search |
| `seedProfiles` | string\[] | TikTok usernames or profile URLs to include directly |

#### Filters & options

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxCreators` | integer | `500` | Maximum creators to return (overall) |
| `maxCreatorsPerSource` | integer | `0` | Cap creators contributed by each hashtag/keyword/seed (0 = no per-source cap) |
| `minFollowers` | integer | `0` | Minimum follower count (0 = disabled) |
| `maxFollowers` | integer | `0` | Maximum follower count (0 = disabled) |
| `verifiedOnly` | boolean | `false` | Only return verified creators |
| `minVideos` | integer | `0` | Minimum videos posted (0 = disabled) |
| `minTotalLikes` | integer | `0` | Minimum total likes/hearts received (0 = disabled) |
| `excludePrivateAccounts` | boolean | `false` | Drop private accounts |
| `countryCodes` | string\[] | `[]` | **Country Filter** — keep only creators from these countries (multi-select; best-effort, see match mode). Filters results, unlike `region` |
| `languages` | string\[] | `[]` | Only these inferred content languages — multi-select dropdown (best-effort) |
| `countryMatchMode` | string | `"best_effort"` | `best_effort` keeps unknowns; `strict` drops anything not confidently matched |
| `sortBy` | string | `"qualificationScore"` | Sort by: qualificationScore, relevanceScore, followers |
| `region` | string | `"US"` | **Discovery Region (hashtags only)** — biases which creators TikTok returns for a hashtag (US, GB, FR, JP, VN, SG). Does not filter; for country filtering use `countryCodes` |

Scoring, country/language annotation, and cross-source deduplication are always applied — they add no extra cost, so they run by default and are not configurable inputs.

#### Bio Enrichment

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `enrichBio` | boolean | `true` | Fetch each creator's full profile to fill bio-derived fields (email, Instagram, YouTube, link-in-bio, language) and any missing follower stats |

Hashtag- and keyword-discovered creators come back "lite" from TikTok's search endpoints — with follower stats but **no bio** — so email/Instagram/YouTube/link/language are empty without this step. When `enrichBio` is on, the actor makes **one extra API call per enriched creator**, so runs are slower and each enriched creator is billed via the separate `bio-enrichment` event (see Pricing). Turn it **off** for faster, cheaper runs that return identity + follower stats only.

#### Performance Analysis

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `includePerformance` | boolean | `false` | Analyze each creator's recent videos for engagement and activity signals |

When on, the actor samples each creator's recent videos and adds median views/likes/comments, an **estimated engagement rate**, and **activity/recency** (latest video, active/dormant). This is the strongest way to tell a genuinely active, engaging creator from a large-but-dormant one. It makes **one extra API call per creator** (slower) and bills each analyzed creator via the separate `performance-sample` event. **Off by default** — turn it on when you want real performance signals, not just follower counts.

#### Bio-Link Following

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `followBioLinks` | boolean | `false` | For creators with an external link but no email in their TikTok bio, fetch that page (Linktree/Beacons/personal site) and try to resolve an email |

Many creators put their email only behind a link-in-bio page, not in the TikTok bio itself. When on, the actor fetches those pages for creators who have a link but no bio email, and records the result in `emailInBio` with `emailSource: "followed_link"`. Billed via the `bio-link-follow` event **only when an email is actually resolved** (you don't pay for links that yield nothing). **Off by default.**

#### Brand Fit

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `campaignBrief` | string | `""` | Free-text description of your campaign / brand / ideal creator |

Describe your campaign in plain text (e.g. *"affordable vegan skincare for Gen-Z, US-based, authentic reviewers"*) and each creator gets a **`brandFitScore` (0–100)** with reasons — based on how well their bio, niche, audience size, and engagement match your brief. Deterministic, **no extra cost**, and you can set `sortBy: "brandFitScore"` to rank by it. Leave empty to skip. Also produced automatically: **`audienceQualityFlag`** (healthy / moderate / suspicious / unknown) from engagement-vs-followers — strongest when Performance Analysis is on.

#### Sample input: Influencer discovery by hashtag and keyword

```json
{
  "hashtags": ["skincare", "beautytok"],
  "keywords": ["ugc creator", "affordable skincare"],
  "seedProfiles": ["@skincarebylaura"],
  "maxCreators": 200,
  "minFollowers": 5000,
  "maxFollowers": 500000,
  "sortBy": "qualificationScore"
}
```

#### Sample input: Lead generation by keyword

```json
{
  "keywords": ["fitness coach", "personal trainer"],
  "minFollowers": 1000,
  "maxFollowers": 1000000,
  "sortBy": "qualificationScore"
}
```

#### Sample input: Seed profile enrichment

```json
{
  "seedProfiles": [
    "https://www.tiktok.com/@charlidamelio",
    "@addisonre",
    "khaby.lame"
  ]
}
```

### Output

The actor outputs a dataset where each row is one discovered creator. Results are available in five dataset views (including a **Shortlist** view that ranks the top candidates by score):

#### Overview table view

![TikTok Influencer Finder — Overview table view](https://raw.githubusercontent.com/coregentdevspace/tiktok-influencer-finder-assets/main/tiktok-influencer-finder-output-overview-table-view.png)

All samples below are real rows from a `"fitness coach"` keyword run with a `campaignBrief` set and all enrichment tiers on.

#### Shortlist view — sample output

Top candidates ranked by score — the fastest way to pick who to reach out to.

```json
{
  "shortlistRank": 1,
  "username": "jennlashley_",
  "displayName": "Jenn | Posture & Fitness Coach",
  "profileUrl": "https://www.tiktok.com/@jennlashley_",
  "followersCount": 239403,
  "qualificationScore": 100,
  "relevanceScore": 40,
  "brandFitScore": 57,
  "estimatedEngagementRate": 0.0247,
  "outreachReady": true,
  "emailInBio": "jenn@posturealignmentacademy.com",
  "country": null
}
```

#### Overview view — sample output

Key fields: identity, stats, likes-per-follower, scoring, and discovery summary.

```json
{
  "username": "jennlashley_",
  "displayName": "Jenn | Posture & Fitness Coach",
  "profileUrl": "https://www.tiktok.com/@jennlashley_",
  "isVerified": true,
  "followersCount": 239403,
  "followingCount": 265,
  "likesCount": 3185069,
  "videosCount": 1967,
  "followerRangeBucket": "100k-500k",
  "likesPerFollower": 13.3,
  "hasContactClue": true,
  "outreachReady": true,
  "qualificationScore": 100,
  "relevanceScore": 40,
  "discoverySourcesSummary": "Found via 1 keyword(s)",
  "scrapedAt": "2026-07-19T07:05:33.422Z"
}
```

#### Outreach view — sample output

Key fields: bio, email (+ source), external links, Instagram/YouTube, and contact clues. Here the email came from the bio-link page (`emailSource: "followed_link"`).

```json
{
  "username": "jennlashley_",
  "displayName": "Jenn | Posture & Fitness Coach",
  "profileUrl": "https://www.tiktok.com/@jennlashley_",
  "bio": "Helping you fix painful posture & move with confidence✨\n1:1 Coaching + Posture Academy App\n📩 DM \"TRIAL\" to start today or tap below👇🏼",
  "emailInBio": "jenn@posturealignmentacademy.com",
  "emailSource": "followed_link",
  "externalUrl": "https://stan.store/Jennlashley_",
  "instagramHandle": null,
  "instagramUrl": null,
  "youtubeHandle": null,
  "youtubeUrl": null,
  "linkInBioUrl": "https://stan.store/Jennlashley_",
  "contactClueType": "email_and_external_link",
  "hasContactClue": true,
  "outreachReady": true,
  "followersCount": 239403,
  "isVerified": true
}
```

#### Discovery view — sample output

Key fields: lineage showing which hashtags/keywords/seed profiles led to each creator, and their rank within the source's results.

```json
{
  "username": "jennlashley_",
  "displayName": "Jenn | Posture & Fitness Coach",
  "followersCount": 239403,
  "discoveredVia": ["keyword"],
  "sourceHashtags": [],
  "sourceKeywords": ["fitness coach"],
  "sourceSeedProfiles": [],
  "matchedBioKeywords": [],
  "discoveryCount": 1,
  "bestSearchRank": 3,
  "discoverySourcesSummary": "Found via 1 keyword(s)"
}
```

#### Quality view — sample output

Key fields: scoring, brand-fit, audience-quality, engagement/activity, country/language (with confidence).

```json
{
  "username": "jennlashley_",
  "displayName": "Jenn | Posture & Fitness Coach",
  "followersCount": 239403,
  "followerRangeBucket": "100k-500k",
  "country": null,
  "countryConfidence": 0,
  "language": "en",
  "languageConfidence": 0.5,
  "profileStatus": "public",
  "isVerified": true,
  "outreachReady": true,
  "qualificationScore": 100,
  "relevanceScore": 40,
  "brandFitScore": 57,
  "brandFitReason": "brief terms matched: fitness, coach, audience in target range, moderate engagement, contactable",
  "audienceQualityFlag": "healthy",
  "audienceQualityScore": 85,
  "estimatedEngagementRate": 0.0247,
  "activityBucket": "active",
  "daysSinceLatestVideo": 0,
  "isPartial": false
}
```

#### Full output example (all fields)

A real row from a keyword run (`"fitness coach"`) with a `campaignBrief` set and all enrichment tiers on. Long URLs are trimmed for readability.

```json
{
  "username": "jennlashley_",
  "profileUrl": "https://www.tiktok.com/@jennlashley_",
  "userId": "6765683454283547653",
  "secUid": "MS4wLjABAAAA13dcvIWqqbZDwxM6Z52AZgtvlRt5K0DI1Ysv0Lb7pPQ...",
  "displayName": "Jenn | Posture & Fitness Coach",
  "bio": "Helping you fix painful posture & move with confidence✨\n1:1 Coaching + Posture Academy App\n📩 DM \"TRIAL\" to start today or tap below👇🏼",
  "profilePictureUrl": "https://p16-common-sign.tiktokcdn-eu.com/...heic?...",
  "isVerified": true,
  "accountPrivate": false,
  "followersCount": 239403,
  "followingCount": 265,
  "likesCount": 3185069,
  "videosCount": 1967,
  "emailInBio": "jenn@posturealignmentacademy.com",
  "externalUrl": "https://stan.store/Jennlashley_",
  "instagramHandle": null,
  "youtubeHandle": null,
  "linkInBioUrl": "https://stan.store/Jennlashley_",
  "contactClueType": "email_and_external_link",
  "hasContactClue": true,
  "emailSource": "followed_link",
  "bioLinkFollowed": true,
  "instagramUrl": null,
  "youtubeUrl": null,
  "discoveredVia": ["keyword"],
  "sourceHashtags": [],
  "sourceKeywords": ["fitness coach"],
  "sourceSeedProfiles": [],
  "matchedBioKeywords": [],
  "searchRankBySource": [{ "sourceType": "keyword", "source": "fitness coach", "rank": 3 }],
  "bestSearchRank": 3,
  "shortlistRank": 1,
  "discoveryCount": 1,
  "discoverySourcesSummary": "Found via 1 keyword(s)",
  "country": null,
  "countryConfidence": 0,
  "language": "en",
  "languageConfidence": 0.5,
  "followerRangeBucket": "100k-500k",
  "likesPerFollower": 13.3,
  "outreachReady": true,
  "qualificationScore": 100,
  "qualificationReason": "has contact clue, email in bio, external link, target follower range, detailed bio, public account, verified, active creator",
  "qualificationComponents": { "contactability": 50, "audienceFit": 20, "profileCompleteness": 25, "activity": 5 },
  "relevanceScore": 40,
  "relevanceReason": "top-10 search rank, single source match, discovered via keyword, high engagement signal",
  "relevanceComponents": { "sourceMatch": 10, "bioMatch": 0, "multiSourceEvidence": 10, "engagement": 10, "discoveryRank": 10 },
  "scoringVersion": "1.1.0",
  "brandFitScore": 57,
  "brandFitReason": "brief terms matched: fitness, coach, audience in target range, moderate engagement, contactable",
  "brandFitComponents": { "briefMatch": 17, "audienceFit": 20, "engagement": 10, "contactable": 10 },
  "audienceQualityScore": 85,
  "audienceQualityFlag": "healthy",
  "audienceQualityReason": "engagement rate healthy for audience size",
  "recentVideosAnalyzed": 10,
  "medianViews": 1217,
  "medianLikes": 29,
  "medianComments": 1,
  "estimatedEngagementRate": 0.0247,
  "latestVideoAt": "2026-07-18T17:03:00.000Z",
  "daysSinceLatestVideo": 0,
  "activityBucket": "active",
  "performanceConfidence": 0.9,
  "performanceSampled": true,
  "scrapedAt": "2026-07-19T07:05:33.422Z",
  "isPartial": false,
  "bioEnriched": true,
  "profileStatus": "public",
  "errorType": null,
  "errorCode": null,
  "errorMessage": null
}
```

### Output fields

#### Identity fields

| Field | Description |
|-------|-------------|
| `username` | TikTok username |
| `profileUrl` | Full profile URL |
| `userId` | TikTok user ID (if available) |
| `secUid` | TikTok `secUid` — stable identifier for downstream API workflows (if available) |
| `displayName` | Display name |
| `bio` | Bio/signature text |
| `profilePictureUrl` | Avatar URL |
| `isVerified` | Verified badge |
| `accountPrivate` | Whether account is private |

#### Stats fields

| Field | Description |
|-------|-------------|
| `followersCount` | Follower count |
| `followingCount` | Following count |
| `likesCount` | Total likes received |
| `videosCount` | Total videos posted |
| `likesPerFollower` | Total likes ÷ followers (lifetime popularity proxy; null if followers unknown) |

#### Outreach/lead fields

| Field | Description |
|-------|-------------|
| `emailInBio` | Email extracted from bio, or resolved from a followed bio link (best-effort) |
| `emailSource` | Where the email came from: `bio` or `followed_link` (null if none) |
| `externalUrl` | External URL from profile |
| `instagramHandle` | Instagram handle from bio (best-effort) |
| `instagramUrl` | Instagram profile URL built from `instagramHandle` |
| `youtubeUrl` | YouTube profile URL built from `youtubeHandle` |
| `youtubeHandle` | YouTube handle from bio (best-effort) |
| `linkInBioUrl` | Link-in-bio URL |
| `contactClueType` | Type of contact clues found (e.g., `email_and_instagram_and_external_link`) |
| `hasContactClue` | Whether any contact clue was found |

#### Discovery lineage fields

| Field | Description |
|-------|-------------|
| `discoveredVia` | Array of discovery modes used (hashtag, keyword, profile) |
| `sourceHashtags` | Hashtags that led to this creator |
| `sourceKeywords` | Keywords that led to this creator |
| `sourceSeedProfiles` | Seed profiles that led to this creator |
| `matchedBioKeywords` | Search terms found in this creator's bio |
| `discoveryCount` | How many times this creator was discovered across sources |
| `searchRankBySource` | Position within each source's results: `[{ sourceType, source, rank }]` |
| `bestSearchRank` | Best (lowest) rank across all sources — a high rank is strong relevance evidence |
| `shortlistRank` | Overall rank in the final sorted/limited results (drives the Shortlist view) |
| `discoverySourcesSummary` | Human-readable discovery summary |

#### Quality/scoring fields

| Field | Description |
|-------|-------------|
| `country` | Country annotation (best-effort from bio/region/flag emojis) |
| `countryConfidence` | 0–1 confidence for `country` (region 0.9 > flag 0.85 > keyword 0.6; 0 = unknown) |
| `language` | Content language (inferred from bio text) |
| `languageConfidence` | 0–1 confidence for `language` (non-Latin script 0.9 > word-match 0.75 > English default 0.5) |
| `followerRangeBucket` | Follower range bucket (under-1k, 1k-5k, 5k-10k, 10k-50k, 50k-100k, 100k-500k, 500k-1M, 1M+) |
| `outreachReady` | Has contact clue AND 1000+ followers |
| `qualificationScore` | 0-100 score for outreach readiness |
| `qualificationReason` | Factors contributing to qualification score |
| `qualificationComponents` | Sub-score breakdown: `contactability`, `audienceFit`, `profileCompleteness`, `activity` |
| `relevanceScore` | 0-100 score for niche relevance |
| `relevanceReason` | Factors contributing to relevance score |
| `relevanceComponents` | Sub-score breakdown: `sourceMatch`, `bioMatch`, `multiSourceEvidence`, `engagement`, `discoveryRank` |
| `scoringVersion` | Scoring model version (bumped when weights change, so scores are comparable across runs) |
| `brandFitScore` | 0–100 fit vs. your `campaignBrief` (null if no brief). Set `sortBy: "brandFitScore"` to rank by it |
| `brandFitReason` | Why the creator scored that brand-fit |
| `brandFitComponents` | Sub-scores: `briefMatch`, `audienceFit`, `engagement`, `contactable` |
| `audienceQualityFlag` | `healthy` / `moderate` / `suspicious` / `unknown` from engagement-vs-followers |
| `audienceQualityScore` | 0–100 audience-quality estimate (best-effort; null when insufficient data) |
| `audienceQualityReason` | Basis for the audience-quality flag |

#### Metadata fields

| Field | Description |
|-------|-------------|
| `scrapedAt` | ISO 8601 extraction timestamp |
| `isPartial` | Whether this record has incomplete data |
| `bioEnriched` | Whether a follow-up profile lookup filled this creator (billed via `bio-enrichment`) |
| `profileStatus` | Standardized status: `public`, `private`, `partial`, or `error` |
| `errorType` | Error type if applicable |
| `errorCode` | Machine-readable error code (for automation); null on success |
| `errorMessage` | Error message if applicable |

#### Performance fields (only when `includePerformance` is on)

| Field | Description |
|-------|-------------|
| `recentVideosAnalyzed` | Number of recent videos sampled |
| `medianViews` | Median views across the sample |
| `medianLikes` | Median likes across the sample |
| `medianComments` | Median comments across the sample |
| `estimatedEngagementRate` | (median likes + median comments) ÷ median views |
| `latestVideoAt` | ISO timestamp of the most recent video |
| `daysSinceLatestVideo` | Days since the latest video |
| `activityBucket` | `active` (≤14d), `recent` (≤45d), `dormant` (≤180d), or `inactive` |
| `performanceConfidence` | 0–1 confidence based on how many videos were sampled |
| `performanceSampled` | Whether this creator was performance-analyzed (billed via `performance-sample`) |

### Scoring methodology

Scores are transparent, heuristic sums of named components (current `scoringVersion`: **1.1.0**). Each creator row includes the component breakdown so you can see exactly why it scored the way it did.

**Qualification score** (0–100 — how outreach-ready):

| Component | Signals (points) | Max |
|-----------|------------------|-----|
| `contactability` | contact clue (25) + email in bio (15) + external link (10) | 50 |
| `audienceFit` | 1k–1M followers (20) or >1M (10) | 20 |
| `profileCompleteness` | detailed bio (10) + public account (10) + verified (5) | 25 |
| `activity` | 10+ videos (5) | 5 |

**Relevance score** (0–100 — how well it matches your search):

| Component | Signals (points) | Max |
|-----------|------------------|-----|
| `sourceMatch` | found via 3+ sources (30), 2 (20), or 1 (10) | 30 |
| `bioMatch` | search terms present in bio (10 each) | 30 |
| `multiSourceEvidence` | multiple discovery modes (20) or one (10) | 20 |
| `engagement` | likes-per-follower ratio > 5 (10) | 10 |
| `discoveryRank` | top-10 rank in a source (10) or top-30 (5) | 10 |

Scores are indicative signals, not authoritative ratings. When the model changes, `scoringVersion` is bumped so you can tell old and new scores apart.

### Use cases

- **Influencer discovery** — find creators in your niche across multiple hashtags and keywords
- **Lead generation** — build outreach lists with emails and contact clues
- **Campaign sourcing** — discover creators matching audience size, niche, and outreach readiness
- **Competitor analysis** — find creators active in competitor hashtags
- **Market research** — understand which creators dominate specific niches
- **AI workflows** — feed creator data into scoring, categorization, and outreach pipelines

### Chaining with other TikTok actors

Creator results flow naturally into other TikTok actors:

- Use `profileUrl` as input for **TikTok Profile Scraper** for deeper profile enrichment
- Use `username` to feed **TikTok Followers/Following Scraper** for audience analysis
- Use discovered hashtags to feed **TikTok Hashtag Scraper** for content-level analysis

### Pricing

This actor uses **pay-per-event** pricing with three events:

- **`influencer-result`** — charged per creator returned in the dataset output.
- **`bio-enrichment`** — charged per creator enriched with a follow-up profile lookup (email, Instagram, YouTube, link-in-bio, language, and any missing follower stats). Only charged when **Enrich Bio & Contact Fields** (`enrichBio`) is on, and only for creators actually enriched. Turn `enrichBio` off to avoid this event.
- **`performance-sample`** — charged per creator analyzed with a recent-video sample (engagement + activity signals). Only charged when **Analyze Recent Performance** (`includePerformance`) is on, and only for creators actually sampled. Off by default.
- **`bio-link-follow`** — charged per creator whose external bio link was followed and **yielded an email**. Only charged when **Follow Bio Links** (`followBioLinks`) is on, and only when an email is actually resolved. Off by default.

The actor respects user-configured spending limits — if your maximum cost per run is reached, it stops pushing results and exits gracefully.

#### What you're charged for

| Scenario | `influencer-result` | `bio-enrichment` | `performance-sample` | `bio-link-follow` |
|----------|:---:|:---:|:---:|:---:|
| 200 creators, all toggles off | 200 | 0 | 0 | 0 |
| 200 creators, `enrichBio` on | 200 | 200 | 0 | 0 |
| 200 creators, all toggles on | 200 | 200 | 200 | only those where a link yielded an email |
| Invalid input / source with no creators | 0 | 0 | 0 | 0 |
| Failed / not-found / private-no-data / error row | 0 | 0 | 0 | 0 |

**Billing rules:**

- You are charged **per creator returned**, plus per creator **enriched** (`enrichBio`), **performance-sampled** (`includePerformance`), and **bio-link-resolved** (`followBioLinks`, only when an email is found) — each only when that toggle is on.
- **Failed and error rows are pushed for visibility but never charged** — you don't pay for our failures.
- A partial row is charged only if it carries a real creator (username/id).
- To control cost: lower `maxCreators`, set `maxCreatorsPerSource`, or turn off `enrichBio` / `includePerformance` / `followBioLinks`.

#### Free plan limitations

**The two profile-lookup enrichments require a paid Apify plan.** On the Free plan they are skipped and you are **not charged** for them.

| | Free plan | Any paid plan |
|---|---|---|
| Creators discovered, filters, qualification scoring, brand fit | ✅ Unrestricted | ✅ Unrestricted |
| Identity, profile URL, follower stats from discovery | ✅ Included | ✅ Included |
| **Follow Bio Links** (`followBioLinks`) | ✅ **Included** | ✅ Included |
| **Enrich Bio & Contact Fields** (`enrichBio`) | ❌ Skipped, not charged | ✅ Included |
| **Analyze Recent Performance** (`includePerformance`) | ❌ Skipped, not charged | ✅ Included |

Note that **`enrichBio` is on by default**, so a Free-plan run returns identity and follower stats rather than emails and social handles — the same output you'd get with `enrichBio` turned off.

Why these two: each costs an extra API call **per creator**, while discovery spreads a single call across a page of them. `followBioLinks` is unaffected because it fetches the creator's own link page directly rather than a metered API.

Runs are never failed because of this. You'll see it in the log and in the run's status message.

### Important notes and limitations

- **Public data only** — this actor uses publicly available TikTok data
- **Contact clues are best-effort** — emails, Instagram handles, and YouTube handles are extracted from public bios using pattern matching. They are not verified or guaranteed to be accurate
- **Country annotation is best-effort** — country is inferred from SSR region data, flag emojis, and bio keywords. It may be null for many profiles
- **Language inference is best-effort** — language is detected from Unicode scripts and common word patterns in bio text
- **Scoring is indicative** — qualification and relevance scores are heuristic-based signals, not authoritative ratings
- **Results depend on TikTok's response** — the actual number of creators found depends on what TikTok returns for each hashtag/keyword page
- **Large discovery runs** may return partial results depending on platform constraints

### Integrations

Results are a standard Apify dataset, so they plug into the usual tooling:

- **Export** — JSON, CSV, Excel, XML, or HTML from the run's Dataset tab (the flat schema drops straight into Google Sheets / Airtable / a CRM).
- **API** — run the actor and pull results via the Apify API / JS / Python / CLI (copy-paste snippets in **API & MCP** below).
- **Automation** — trigger runs and route results with Make, Zapier, n8n, or Apify **webhooks** (fire on run success into your own endpoint).
- **AI / MCP** — expose the actor as a tool to Claude/other agents via the Apify MCP server (config in **API & MCP** below).
- **Chaining** — feed `profileUrl` / `username` into other TikTok actors (see *Chaining with other TikTok actors* above).

#### Outreach & CRM recipes

Because every row is a flat, outreach-ready lead, you can wire runs straight into your outreach stack. Common patterns:

- **New leads → CRM/Sheet:** add an Apify **webhook** on `ACTOR.RUN.SUCCEEDED` that POSTs the dataset to a Make/Zapier/n8n scenario, which appends each creator to HubSpot / Pipedrive / Airtable / Google Sheets. Map `emailInBio`, `username`, `profileUrl`, `followersCount`, `qualificationScore`.
- **Only contactable leads:** in the Zap/scenario, filter to `outreachReady = true` (or `hasContactClue = true`) so only creators you can actually reach hit the CRM.
- **Auto-draft outreach:** pass `displayName`, `bio`, `matchedBioKeywords`, and `discoverySourcesSummary` into an AI step (or the Apify MCP server) to draft a personalized first message per creator.
- **Scheduled sourcing:** put the actor on an Apify **Schedule** (e.g., weekly per niche); each run's webhook feeds new creators into the same CRM pipeline.
- **Dedupe on your side:** use `username` (or `userId` / `secUid`) as the unique key when upserting into your CRM to avoid duplicates across runs.

### API & MCP

Run the actor and read results programmatically. Replace `YOUR_APIFY_TOKEN` with a token from **Apify Console → Settings → Integrations**. (Apify also auto-generates ready-to-copy snippets on the actor's **API** and **MCP** tabs.)

#### REST API

Run and get the results in one call (`run-sync-get-dataset-items`):

```bash
curl -X POST "https://api.apify.com/v2/acts/coregent~tiktok-influencer-finder/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "keywords": ["fitness coach"], "maxCreators": 100, "enrichBio": true }'
```

Or start a run asynchronously, then fetch the dataset later:

```bash
## Start a run
curl -X POST "https://api.apify.com/v2/acts/coregent~tiktok-influencer-finder/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "hashtags": ["skincare"], "maxCreators": 200 }'

## Then read items from the run's dataset
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?token=YOUR_APIFY_TOKEN&format=json"
```

#### JavaScript (`apify-client`)

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('coregent/tiktok-influencer-finder').call({
  keywords: ['fitness coach'],
  maxCreators: 100,
  enrichBio: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python (`apify-client`)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("coregent/tiktok-influencer-finder").call(run_input={
    "keywords": ["fitness coach"],
    "maxCreators": 100,
    "enrichBio": True,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

#### CLI

```bash
apify call coregent/tiktok-influencer-finder --input='{"keywords":["fitness coach"],"maxCreators":100}'
```

#### MCP (AI agents)

Expose the actor as a tool to Claude Desktop / any MCP client via the Apify MCP server:

```json
{
  "mcpServers": {
    "apify": {
      "command": "npx",
      "args": ["-y", "@apify/actors-mcp-server", "--actors", "coregent/tiktok-influencer-finder"],
      "env": { "APIFY_TOKEN": "YOUR_APIFY_TOKEN" }
    }
  }
}
```

The agent can then call the actor and read the returned creator leads directly in a conversation.

### FAQ

**Is this legal?** The actor collects only publicly available TikTok data. You are responsible for using the results in line with TikTok's Terms and applicable laws (e.g. GDPR when handling personal data).

**What data do you collect?** Public profile fields only — identity, follower stats, bio, and public contact clues creators put in their own bios. No private or login-gated data.

**How accurate are the emails / contact clues?** Best-effort — they're pattern-matched from public bios and not verified. Expect email coverage in the ~10–30% range depending on niche (only creators who publish an email).

**Why is `country` often empty?** Country is inferred from bio cues (flag emojis, city/country names) only — TikTok's search/profile responses don't expose a reliable region field. Use `countryConfidence` to gauge certainty.

**Why did a keyword/hashtag run take a while?** Contact fields require a follow-up profile call per creator (`enrichBio`). Turn `enrichBio` off for fast, cheap runs that return identity + follower stats only.

**Can I combine hashtags, keywords, and seed profiles?** Yes — provide any mix in one run. Creators found across sources are de-duplicated with merged discovery lineage.

**How is this different from a profile scraper?** This *finds* creators (discovery + qualification + scoring across many sources); a profile scraper *enriches* creators you already know. They chain well together.

### Troubleshooting

| Symptom | Likely cause & fix |
|---------|--------------------|
| Few or no creators returned | Broaden inputs (more/less-niche hashtags or keywords); very specific terms return little. Check the run log for per-source counts. |
| Contact/email/country/language fields empty | `enrichBio` is off, or those creators simply don't publish that info. Turn `enrichBio` on for bio-derived fields. |
| `country` is null but other fields are set | Expected — country is bio-inferred only (see FAQ). |
| Run stopped early | Your per-run spending limit was reached; the actor exits gracefully after the last charged batch. |
| Slow runs | Enrichment makes one call per creator; lower `maxCreators`/`maxCreatorsPerSource` or turn `enrichBio` off. |
| One broad hashtag dominates results | Set `maxCreatorsPerSource` to balance coverage across sources. |

# Actor input Schema

## `hashtags` (type: `array`):

Hashtag names or hashtag URLs to discover creators from. Accepts plain text (skincare), with # (#skincare), or full URLs (https://www.tiktok.com/tag/skincare).

## `keywords` (type: `array`):

Keywords or niche phrases to search for creators. Examples: 'fitness coach', 'AI productivity', 'travel creator Australia'.

## `seedProfiles` (type: `array`):

TikTok profile URLs or usernames to include directly. Accepts @username or full profile URLs.

## `maxCreators` (type: `integer`):

Maximum number of creators to return in the final output.

## `maxCreatorsPerSource` (type: `integer`):

Cap how many creators each individual hashtag/keyword/seed contributes, so one broad source can't dominate the run. 0 = no per-source cap (only the overall Max Creators applies).

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

Minimum follower count. Set to 0 to disable.

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

Maximum follower count. Set to 0 to disable.

## `verifiedOnly` (type: `boolean`):

Only return verified creators.

## `minVideos` (type: `integer`):

Minimum number of videos posted. Filters out low-activity creators. Set to 0 to disable.

## `minTotalLikes` (type: `integer`):

Minimum total likes (hearts) received across all videos. Set to 0 to disable.

## `excludePrivateAccounts` (type: `boolean`):

Drop creators whose accounts are private.

## `countryCodes` (type: `array`):

FILTERS results to creators from these countries (drops the rest). Different from Discovery Region: Region biases what TikTok returns for a hashtag, while this filters the creators actually found — across all discovery modes. Country is best-effort (inferred from bio) — see Country Match Mode. Leave empty to disable.

## `languages` (type: `array`):

Only return creators whose inferred content language is one of these. Best-effort (inferred from bio). Leave empty to disable.

## `countryMatchMode` (type: `string`):

How to treat creators with unknown country/language when a Country Codes or Languages filter is set. 'Best effort' keeps unknowns (drops only confirmed mismatches); 'Strict' drops anything not confidently matched.

## `sortBy` (type: `string`):

Sort results by this field.

## `region` (type: `string`):

Biases WHICH creators TikTok returns for a hashtag search — it does not filter results. Applies to hashtag discovery only (not keyword or seed profiles). To keep only creators from specific countries, use the Country Filter instead. Defaults to US.

## `enrichBio` (type: `boolean`):

Fetch each creator's full profile to fill bio-derived fields — email, Instagram, YouTube, link-in-bio, language (and any missing follower stats). Recommended for outreach. Adds one extra API call per enriched creator, so runs are slower and each enriched creator is billed via the 'bio-enrichment' event. Turn OFF for faster, cheaper runs that return identity + follower stats only. NOTE: this option requires a paid Apify plan. On the Free plan it is skipped and you are not charged for it — creator discovery, filtering and scoring are unrestricted.

## `includePerformance` (type: `boolean`):

Fetch each creator's recent videos to compute median views/likes/comments, an estimated engagement rate, and activity/recency (latest video, active/dormant). Adds one extra API call per creator (slower) and bills each analyzed creator via the 'performance-sample' event. Off by default. NOTE: this option requires a paid Apify plan. On the Free plan it is skipped and you are not charged for it.

## `followBioLinks` (type: `boolean`):

For creators with an external link (Linktree/Beacons/personal site) but no email in their TikTok bio, fetch that page and try to extract an email. Adds one external page fetch per such creator; billed via the 'bio-link-follow' event only when an email is actually resolved. Off by default.

## `campaignBrief` (type: `string`):

Describe your campaign / brand / ideal creator in plain text (e.g. 'affordable vegan skincare for Gen-Z, US-based, authentic reviewers'). Each creator gets a brand-fit score (0-100) with reasons, based on how well their bio, niche, audience size, and engagement match your brief. Leave empty to skip. No extra cost.

## Actor input object example

```json
{
  "hashtags": [],
  "keywords": [
    "fitness coach"
  ],
  "seedProfiles": [],
  "maxCreators": 500,
  "maxCreatorsPerSource": 0,
  "minFollowers": 0,
  "maxFollowers": 0,
  "verifiedOnly": false,
  "minVideos": 0,
  "minTotalLikes": 0,
  "excludePrivateAccounts": false,
  "countryCodes": [],
  "languages": [],
  "countryMatchMode": "best_effort",
  "sortBy": "qualificationScore",
  "region": "US",
  "enrichBio": true,
  "includePerformance": false,
  "followBioLinks": false,
  "campaignBrief": ""
}
```

# Actor output Schema

## `shortlist` (type: `string`):

No description

## `overview` (type: `string`):

No description

## `outreach` (type: `string`):

No description

## `discovery` (type: `string`):

No description

## `quality` (type: `string`):

No description

# 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 = {
    "keywords": [
        "fitness coach"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("coregent/tiktok-influencer-finder").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 = { "keywords": ["fitness coach"] }

# Run the Actor and wait for it to finish
run = client.actor("coregent/tiktok-influencer-finder").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "keywords": [
    "fitness coach"
  ]
}' |
apify call coregent/tiktok-influencer-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=coregent/tiktok-influencer-finder",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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