# TikTok Profile Scraper — Followers, Bio & Influencer Score (`khadinakbar/tiktok-profile-scraper`) Actor

Get TikTok profile data by username: followers, hearts, videos, bio link, verification and a 0–80 Influencer Score to rank creators. $0.003 per profile (less on Scale and Business plans). Not-found and blocked profiles are free. No login.

- **URL**: https://apify.com/khadinakbar/tiktok-profile-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Social media, Videos, Lead generation
- **Features:** Limited permissions
- **Stats:** 1,232 total users, 143 monthly users, 98.2% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 scraped tiktok profiles

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What is TikTok Profile Scraper?

TikTok Profile Scraper turns public TikTok usernames or profile URLs into one clean row per creator. Each row has followers, following, total hearts (likes), video count, bio, bio link, verification, avatar, and an Influencer Score from 0 to 80 that ranks creators on the same scale. Influencer marketers, talent scouts, agencies and AI agents use it to vet a creator shortlist in one run, with no TikTok login or cookies.

### Why teams choose this TikTok profile scraper

- **One row per creator.** You pay for creator profiles, and every row is a complete profile card you can sort, filter and export.
- **Influencer Score on every row.** `influencer_score` (0–80) combines follower tier, heart-to-follower ratio, verification and content volume, so a shortlist ranks itself.
- **Bio links decoded.** `bio_link` holds the creator's real outbound link, ready for outreach or lead enrichment.
- **Clear status per profile.** `profile_status` shows `found`, `not_found` or `blocked`, and only `found` rows are billed.
- **Automatic recovery.** Profiles that stall on the first route are retried on residential proxies automatically.
- **Built for AI agents.** Flat JSON with stable snake_case keys, available through Apify MCP and the Apify API.

### Best fit for this Actor

- Start here when you already have TikTok handles, `@handles` or profile URLs and want one vetting row per creator.
- For discovering creators by topic first, start with **TikTok Trending Videos Scraper** and pass the video authors into `profiles`.
- For a creator's individual videos, continue with **TikTok Profile Videos Scraper** after vetting.

### What people and AI agents ask this Actor to do

> Vet these 20 TikTok creators and rank them by Influencer Score.
> Which of these creators are verified and have more than a million hearts?
> Get the bio links for this list of TikTok handles so I can reach out.
> Refresh follower counts for our creator roster every week.

| Request | Input to send |
|---|---|
| Vet a creator shortlist | `{"profiles": ["nasa", "khaby.lame"], "maxResults": 20}` |
| Profiles from full URLs | `{"profiles": ["https://www.tiktok.com/@nasa"]}` |
| Mixed handles and URLs | `{"profiles": ["@nasa", "khaby.lame", "https://www.tiktok.com/@nba"]}` |
| A large roster refresh | `{"profiles": ["handle1", "handle2", "handle3"], "maxResults": 500}` |

Then sort by `influencer_score`, filter by `verified` or `follower_count`, and read `bio_link` for outreach.

### Example workflow: from a creator shortlist to a partnership decision

An influencer manager starts with ten public handles from a campaign brief. They send the handles in `profiles` and get one row per creator. They compare `follower_count`, `heart_count` and `influencer_score`, keep the creators whose audience fits the brief, then read `bio_link` to reach each one. Next they export the dataset to a spreadsheet and schedule the same input monthly, so `scraped_at` shows how each creator grows over time.

### How to scrape TikTok profiles

1. Add usernames, `@handles` or profile URLs in **Profiles**.
2. Set **Max results** to the number of creators you want back.
3. Click **Start**. Export the dataset as JSON, CSV or Excel, or read it through the API.

### Quick start input

```json
{
  "profiles": [
    "nasa",
    "https://www.tiktok.com/@khaby.lame"
  ],
  "maxResults": 10
}
```

### Input reference

| Field | Type | What it controls |
|---|---|---|
| `profiles` | array of strings | Public TikTok usernames, `@handles` or profile URLs. Required unless you use `searchKeywords`. |
| `searchKeywords` | array of strings | Optional. Niches or topics, one per line (up to 10). The Actor finds public creators for each and returns the same profile row. |
| `maxProfilesPerKeyword` | integer | Creators taken per keyword, 1 to 100. Default 20. |
| `verifiedOnly` | boolean | Return only accounts with a verification badge. |
| `minFollowers`, `maxFollowers` | integer | Keep only profiles inside this follower range. |
| `shopSellersOnly` | boolean | Keep only accounts that sell through TikTok Shop. |
| `postedAfter`, `postedBefore` | string (YYYY-MM-DD) | Keep only creators whose newest video falls in this date range. Up to 100 profiles per run are checked. |
| `maxResults` | integer | Cap on profiles looked up, usernames first, then keyword results. Default 10, maximum 10000. |
| `proxyConfiguration` | object | Apify Proxy settings. The default uses Apify Proxy, with automatic residential retries. |
| `scrapeRecentVideos` | boolean | Kept so older saved inputs keep working; profile rows are the output. |
| `maxVideosPerProfile` | integer | Kept so older saved inputs keep working; profile rows are the output. |

### Output: TikTok profile data you receive

One dataset row is one TikTok creator from your `profiles` list.

| Field | What it contains |
|---|---|
| `username`, `display_name` | Handle and display name |
| `follower_count`, `following_count` | Audience size and accounts followed |
| `heart_count` | Total likes the creator has received |
| `video_count` | Number of public videos |
| `bio`, `bio_link` | Bio text and decoded outbound link |
| `verified`, `is_private` | Verification badge and privacy flag |
| `tiktok_shop_seller` | Whether the account sells through TikTok Shop (null if the page did not show it) |
| `last_post_at` | Time of the newest video, filled when a date filter is used |
| `matched_keyword` | The keyword that found this creator (null for usernames you entered) |
| `influencer_score` | Derived score from 0 to 80 (see below) |
| `avatar_url`, `region` | Avatar image and region when TikTok shows it |
| `profile_status` | `found`, `not_found` or `blocked` |
| `profile_url`, `source_url`, `scraped_at` | Provenance and collection time |

```json
{
  "profile_status": "found",
  "username": "nasa",
  "display_name": "NASA",
  "bio": "Making the seemingly impossible, possible.✨",
  "bio_link": null,
  "follower_count": 1900000,
  "following_count": 23,
  "heart_count": 9800000,
  "video_count": 49,
  "verified": true,
  "is_private": false,
  "region": null,
  "influencer_score": 59,
  "profile_url": "https://www.tiktok.com/@nasa",
  "source_url": "https://www.tiktok.com/@nasa",
  "scraped_at": "2026-09-29T09:57:50.018Z"
}
```

**How Influencer Score works.** It adds four parts from the public profile card: follower tier (0–30), heart-to-follower ratio (0–20), verified badge (0–10) and content volume (0–20). It is this Actor's own heuristic for ranking a shortlist, independent of TikTok's internal ranking.

### What each run outcome means

Every run writes an `OUTPUT` record and a `RUN_SUMMARY` record to the default key-value store. Read `OUTPUT.outcome` to branch in code or in an agent.

| Outcome | Meaning |
|---|---|
| `COMPLETE` | Every existing profile returned data. |
| `PARTIAL` | Some profiles returned data and some stayed unavailable after the residential retry; each of those has a row saying so. |
| `VALID_EMPTY` | The input was valid and none of the profiles exist; each has a `not_found` row. |
| `INVALID_INPUT` | The input was rejected; `OUTPUT.message` explains the working format. |
| `UPSTREAM_FAILED` | Every profile stayed unavailable, so no useful data was produced. |

The summary also counts profiles found, not found, unavailable, retried through residential, and charged.

### Pricing

This Actor uses **Pay per event** plus **Apify platform usage**. You pay one profile event for each row with real profile data, plus the start event and the platform usage of the run. Rows marked `not_found` or unavailable are free. The live **Pricing** tab on this page shows the current event prices.

Worked examples:

- 10 creators, all found = 10 profile events + start event + platform usage.
- 10 creators, 8 found and 2 not found = 8 profile events + start event + platform usage.
- `maxResults: 50` on a list of 200 handles = at most 50 profile events.

Formula: `profile event price × found profiles + start event + platform usage`. Set a maximum charge per run in the run options to cap spend; the Actor checks that limit before each charge.

### Use TikTok Profile Scraper with AI agents (MCP)

Connect this Actor to Claude, ChatGPT, Cursor or any MCP client through [Apify MCP](https://mcp.apify.com), then ask in plain language:

> Vet these 10 public TikTok creators. Return username, follower_count, heart_count, influencer_score, bio_link, source_url and scraped_at, sorted by influencer_score. Tell me which profiles were not found.

Agent checklist:

1. Pass handles or URLs in `profiles` and set `maxResults` to the list size.
2. Read rows with `get-dataset-items`, then read `OUTPUT.outcome`.
3. Keep rows where `profile_status` is `found` before ranking by `influencer_score`.
4. Keep `source_url` and `scraped_at` to cite where and when each number was collected.

### API example

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~tiktok-profile-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"profiles": ["nasa", "khaby.lame"], "maxResults": 10}'
```

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('khadinakbar/tiktok-profile-scraper').call({
    profiles: ['nasa', 'khaby.lame'],
    maxResults: 10,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((row) => row.profile_status === 'found'));
```

### Choosing the right TikTok tool

Other Actors from the same developer pick up where this one stops.

| Your starting point | Tool to use | Why it fits |
|---|---|---|
| When you start from handles or profile URLs | This Actor | One vetting row per creator with Influencer Score |
| When you want to discover creators from trending content | [TikTok Trending Videos Scraper](https://apify.com/khadinakbar/tiktok-trending-videos-scraper) | Trending videos whose author handles you can pass into `profiles` here |
| When you want to search TikTok by keyword first | [TikTok Search Scraper](https://apify.com/khadinakbar/tiktok-search-scraper) | Videos, hashtags and users for a keyword |
| When you then want a creator's videos | [TikTok Profile Videos Scraper](https://apify.com/khadinakbar/tiktok-profile-videos-scraper) | Pass the same `username` values for captions, views and engagement per video |
| When you want to analyze comments on a creator's video | [TikTok Video Comments Scraper](https://apify.com/khadinakbar/tiktok-video-comments-scraper) | Comments and replies that show audience sentiment before you commit |
| When you want the hashtags your niche uses | [TikTok Trending Hashtags Scraper](https://apify.com/khadinakbar/tiktok-trending-hashtags-scraper) | Ranked trending hashtags by country and industry |

### Best results

| Starting situation | Helpful action | Expected outcome |
|---|---|---|
| A clean shortlist of handles | Paste handles or profile URLs as they are | One row per creator |
| A long roster | Set `maxResults` to the roster size | A predictable bill |
| Tracking growth over time | Schedule the same `profiles` list | Comparable rows by `scraped_at` |
| Handles copied from captions | Keep the `@` or remove it; both work | Normalized usernames |

### Builder's note

I found that creator vetting mostly needs the profile card, so I built the row around followers, hearts, video count, verification and the bio link, and I bill only rows with real profile data. I learned that a single number helps shortlists more than raw counts, which is why `influencer_score` puts every creator on the same 0–80 scale.

### FAQ

#### How do I find creators in a niche?

Add one or more `searchKeywords`, for example `fitness`. Each creator found is returned as a normal profile row and charged as one scraped profile. Add `verifiedOnly`, a follower range or `shopSellersOnly` to keep only the creators you want.

#### Are filtered-out profiles charged?

No. A profile that does not match your filters is not returned and not charged. Not-found and blocked profiles are free too. Filters do not remove the page lookup itself, so use a sensible `maxResults`.

#### How much does it cost to scrape 100 TikTok profiles?

100 found profiles cost 100 profile events plus one start event and platform usage. Profiles marked not found or unavailable are free. Multiply by the profile event price on the Pricing tab.

#### Do I need a TikTok account or cookies?

No. The Actor reads public profile pages only and needs no login.

#### What is a good Influencer Score?

Scores rise with follower tier, strong heart-to-follower ratio, verification and steady posting. Use it to rank a shortlist against itself rather than as an absolute grade.

#### Can I get a creator's videos too?

Profile rows are this Actor's output. Pass the same usernames to TikTok Profile Videos Scraper for per-video data.

#### What happens with private or deleted accounts?

A deleted or mistyped handle returns a free row with `profile_status` set to `not_found`. A private account that still shows its public profile card comes back as a normal row with `is_private` set to `true`.

### Responsible use

This Actor collects public TikTok profile data only. Profiles include usernames, names and bio links, which are personal data protected by laws such as the GDPR and CCPA. Collect and use them only with a lawful basis, keep them no longer than you need, and respect TikTok's terms. Read Apify's guide on [whether web scraping is legal](https://blog.apify.com/is-web-scraping-legal/) for more context. TikTok is a trademark of ByteDance Ltd. This independent Actor is not affiliated with, associated with, or endorsed by TikTok or ByteDance. For questions or bugs, open a ticket in the Issues tab.

# Changelog

This Actor's version history is a separate document: https://apify.com/khadinakbar/tiktok-profile-scraper/changelog.md

# Actor input Schema

## `profiles` (type: `array`):

Enter public TikTok usernames or profile URLs, one per line. Accepts example.creator, @example.creator, or https://www.tiktok.com/@example.creator. This field selects which creator profile rows to return.

## `maxResults` (type: `integer`):

Cap how many profile rows this run processes, starting from the top of the profiles list. Use this as a cost control. Default 10, maximum 10000.

## `searchKeywords` (type: `array`):

Optional. One niche or topic per line, for example fitness or vegan recipes. The Actor finds public creators for each keyword, then returns the same profile row for each. Works alone or together with usernames. Up to 10 keywords.

## `maxProfilesPerKeyword` (type: `integer`):

How many creators to take from each keyword, 1 to 100. The overall Maximum number of profiles above still applies.

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

Return only accounts with a TikTok verification badge. Profiles that do not match are not returned and not charged.

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

Return only profiles with at least this many followers. Leave empty for no minimum.

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

Return only profiles with at most this many followers. Leave empty for no maximum.

## `shopSellersOnly` (type: `boolean`):

Return only accounts that sell through TikTok Shop. Profiles where this cannot be confirmed are skipped.

## `postedAfter` (type: `string`):

Keep only creators whose newest video was posted on or after this date, written YYYY-MM-DD. Leave empty for no limit. Creators whose latest post date cannot be read are skipped and not charged. Date filters check up to 100 profiles per run.

## `postedBefore` (type: `string`):

Keep only creators whose newest video was posted on or before this date, written YYYY-MM-DD. Use with the field above to find inactive or recently active creators.

## `scrapeRecentVideos` (type: `boolean`):

Kept so saved inputs keep working. Does not change the profile-only output.

## `maxVideosPerProfile` (type: `integer`):

Kept only for old saved inputs. Has no effect.

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

Proxy used for the first request to each profile. Leave the default for Apify's cheap datacenter pool. A blocked profile is retried on residential automatically, up to 2 times. A username that does not exist is not retried. Pick residential here only if you want every profile to start on residential.

## Actor input object example

```json
{
  "profiles": [
    "example.creator",
    "sample.studio"
  ],
  "maxResults": 10,
  "maxProfilesPerKeyword": 20,
  "verifiedOnly": false,
  "shopSellersOnly": false,
  "scrapeRecentVideos": true,
  "maxVideosPerProfile": 24,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Dataset of TikTok profile records. profile_status is found, not_found, or blocked. Only a found row is charged.

## `output` (type: `string`):

Terminal outcome (COMPLETE, PARTIAL, VALID_EMPTY, UPSTREAM_FAILED, or INVALID_INPUT) and the counts of profiles found, not found, blocked, retried through residential, and charged.

## `runSummary` (type: `string`):

Same terminal record as OUTPUT, including charged usernames and warnings.

# 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 = {
    "profiles": [
        "example.creator",
        "sample.studio"
    ],
    "maxResults": 10,
    "scrapeRecentVideos": true,
    "maxVideosPerProfile": 24,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/tiktok-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 = {
    "profiles": [
        "example.creator",
        "sample.studio",
    ],
    "maxResults": 10,
    "scrapeRecentVideos": True,
    "maxVideosPerProfile": 24,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/tiktok-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 '{
  "profiles": [
    "example.creator",
    "sample.studio"
  ],
  "maxResults": 10,
  "scrapeRecentVideos": true,
  "maxVideosPerProfile": 24,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call khadinakbar/tiktok-profile-scraper --silent --output-dataset

```

## MCP server setup

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