TikTok Follow Graph & Audience Export Scraper
Export who a TikTok account follows, or who follows it, as full public profile records with bio, verification status and exact engagement stats. No login or cookie is needed for public accounts.
Input schema
Input fields, types, required flags, descriptions, defaults, and prefills come from the published definition. Prefill examples are distinct from defaults.
| Field | Type | Required | Description |
|---|---|---|---|
profiles | array | optional | TikTok usernames, @handles, or profile URLs. Paste one per line. Examples: natgeo, @sephora, https://www.tiktok.com/@tiktok. |
listType | string | optional | Choose the side of the follow graph: people who follow the profile, accounts the profile follows, or both lists. |
maxUsersPerProfile | integer | optional | Maximum rows to return for each requested list. Each list gets this cap. The source may return fewer when accounts are private or deleted. |
Show all input fields
| Field | Type | Required | Description |
|---|---|---|---|
profiles | array | optional | TikTok usernames, @handles, or profile URLs. Paste one per line. Examples: natgeo, @sephora, https://www.tiktok.com/@tiktok. |
listType | string | optional | Choose the side of the follow graph: people who follow the profile, accounts the profile follows, or both lists. |
maxUsersPerProfile | integer | optional | Maximum rows to return for each requested list. Each list gets this cap. The source may return fewer when accounts are private or deleted. |
includeStats | boolean | optional | Add follower, following, likes received, video, likes given, and friend counts for each listed account. |
includeBioEmail | boolean | optional | Add a public email address from the bio when one is present. The field is omitted when the bio has no valid email. |
onlyVerified | boolean | optional | Only include accounts with a TikTok verified badge. |
sellerOnly | boolean | optional | Only include accounts marked as TikTok Shop sellers. |
excludePrivate | boolean | optional | Skip accounts whose profile is private. |
minFollowers | integer | optional | Only include accounts with at least this many followers. 0 = no minimum. |
maxFollowers | integer | optional | Only include accounts with at most this many followers. 0 = no maximum. |
bioKeywords | array | optional | Only include accounts whose bio or display name contains any of these keywords. Matching is case-insensitive. |
onlyWithEmail | boolean | optional | Only include accounts with a public email in the bio. This also fills the bioEmail field. |
scanLimit | integer | optional | Maximum list rows to scan before stopping. Use a higher value to search deeper for rare filters. 0 = automatic (10x the row cap, up to 10,000). |
Download the published input schema
View complete JSON
{
"description": "Export the followers or following list of public TikTok profiles. No login or cookie is needed. Private accounts and hidden following lists are reported honestly.",
"properties": {
"bioKeywords": {
"default": [],
"description": "Only include accounts whose bio or display name contains any of these keywords. Matching is case-insensitive.",
"editor": "stringList",
"items": {
"type": "string"
},
"prefill": [],
"title": "Bio or name keywords",
"type": "array"
},
"excludePrivate": {
"default": false,
"description": "Skip accounts whose profile is private.",
"prefill": false,
"title": "Exclude private accounts",
"type": "boolean"
},
"includeBioEmail": {
"default": false,
"description": "Add a public email address from the bio when one is present. The field is omitted when the bio has no valid email.",
"prefill": false,
"title": "Extract email from bio",
"type": "boolean"
},
"includeStats": {
"default": true,
"description": "Add follower, following, likes received, video, likes given, and friend counts for each listed account.",
"prefill": true,
"sectionCaption": "Output extras",
"sectionDescription": "Optional fields added to each row.",
"title": "Include audience stats",
"type": "boolean"
},
"listType": {
"default": "following",
"description": "Choose the side of the follow graph: people who follow the profile, accounts the profile follows, or both lists.",
"editor": "select",
"enum": [
"followers",
"following",
"both"
],
"enumTitles": [
"Followers",
"Following",
"Both lists"
],
"prefill": "following",
"title": "Which list to export",
"type": "string"
},
"maxFollowers": {
"default": 0,
"description": "Only include accounts with at most this many followers. 0 = no maximum.",
"maximum": 1000000000,
"minimum": 0,
"prefill": 0,
"title": "Maximum followers",
"type": "integer"
},
"maxUsersPerProfile": {
"default": 100,
"description": "Maximum rows to return for each requested list. Each list gets this cap. The source may return fewer when accounts are private or deleted.",
"maximum": 5000,
"minimum": 1,
"prefill": 3,
"title": "Max users per list",
"type": "integer"
},
"minFollowers": {
"default": 0,
"description": "Only include accounts with at least this many followers. 0 = no minimum.",
"maximum": 1000000000,
"minimum": 0,
"prefill": 0,
"title": "Minimum followers",
"type": "integer"
},
"onlyVerified": {
"default": false,
"description": "Only include accounts with a TikTok verified badge.",
"prefill": false,
"sectionCaption": "Audience filters",
"sectionDescription": "Optional filters applied after the list is fetched. Filtered-out rows are not pushed or charged.",
"title": "Verified accounts only",
"type": "boolean"
},
"onlyWithEmail": {
"default": false,
"description": "Only include accounts with a public email in the bio. This also fills the bioEmail field.",
"prefill": false,
"title": "Only accounts with a bio email",
"type": "boolean"
},
"profiles": {
"default": [],
"description": "TikTok usernames, @handles, or profile URLs. Paste one per line. Examples: natgeo, @sephora, https://www.tiktok.com/@tiktok.",
"editor": "stringList",
"items": {
"type": "string"
},
"prefill": [
"natgeo"
],
"title": "TikTok profiles",
"type": "array"
},
"scanLimit": {
"default": 0,
"description": "Maximum list rows to scan before stopping. Use a higher value to search deeper for rare filters. 0 = automatic (10x the row cap, up to 10,000).",
"maximum": 100000,
"minimum": 0,
"prefill": 0,
"title": "Scan limit",
"type": "integer"
},
"sellerOnly": {
"default": false,
"description": "Only include accounts marked as TikTok Shop sellers.",
"prefill": false,
"title": "TikTok Shop sellers only",
"type": "boolean"
}
},
"required": [],
"schemaVersion": 1,
"title": "TikTok Follow Graph & Audience Export Scraper Input",
"type": "object"
}
Output schema
Published result links and storage locations. This schema is not an exhaustive contract for every field in a dataset record.
| Field | Type | Required | Description |
|---|---|---|---|
data | string | optional | Dataset containing follower/following user records. Fields: sourceUsername, sourceUserId, sourceProfileUrl, sourceFollowerCount, sourceFollowingCount, sourceVerified, sourcePrivate, sourceIsOrganization, listType, position, listTotal, userId, secUid, username, displayName, verified, isOrganization, privateAccount, ttSeller, bio, avatarUrl, profileUrl, followerCount, followingCount, heartCount, videoCount, diggCount, friendCount, bioEmail, scrapedAt. |
Download the published output schema
View complete JSON
{
"actorOutputSchemaVersion": 1,
"description": "One record per TikTok follower or following account, with profile identity, exact audience stats, source context, and optional bio email.",
"properties": {
"data": {
"description": "Dataset containing follower/following user records. Fields: sourceUsername, sourceUserId, sourceProfileUrl, sourceFollowerCount, sourceFollowingCount, sourceVerified, sourcePrivate, sourceIsOrganization, listType, position, listTotal, userId, secUid, username, displayName, verified, isOrganization, privateAccount, ttSeller, bio, avatarUrl, profileUrl, followerCount, followingCount, heartCount, videoCount, diggCount, friendCount, bioEmail, scrapedAt.",
"template": "{{links.apiDefaultDatasetUrl}}/items",
"title": "Follow graph data",
"type": "string"
}
},
"title": "TikTok Follow Graph & Audience Export Scraper Output"
}
Dataset schema
Published dataset views and any declared field definitions. A view can select only a subset of the returned record fields.
Download the published dataset schema
View complete JSON
{
"actorSpecification": 1,
"fields": {
"avatarUrl": {
"description": "Signed TikTok CDN URL for the profile avatar. May expire; profileUrl is permanent.",
"title": "Avatar URL",
"type": "string"
},
"bio": {
"description": "Public profile biography/signature text",
"title": "Bio",
"type": "string"
},
"bioEmail": {
"description": "First public-looking email address found in the bio, when email extraction is enabled",
"title": "Bio Email",
"type": "string"
},
"diggCount": {
"description": "Number of likes this account has given from statsV2",
"title": "Digg Count",
"type": "integer"
},
"displayName": {
"description": "Display name (nickname) of this account",
"title": "Display Name",
"type": "string"
},
"followerCount": {
"description": "Exact follower count for this account from statsV2",
"title": "Follower Count",
"type": "integer"
},
"followingCount": {
"description": "Exact number of accounts this account follows from statsV2",
"title": "Following Count",
"type": "integer"
},
"friendCount": {
"description": "Mutual friend count reported by TikTok from statsV2",
"title": "Friend Count",
"type": "integer"
},
"heartCount": {
"description": "Total likes received across all videos from statsV2",
"title": "Heart Count",
"type": "integer"
},
"isOrganization": {
"description": "Whether TikTok classifies this account as an organization. Usually absent for list rows.",
"title": "Is Organization",
"type": "boolean"
},
"listTotal": {
"description": "Total relationship count reported by TikTok for this list",
"title": "List Total",
"type": "integer"
},
"listType": {
"description": "Either followers or following",
"title": "List Type",
"type": "string"
},
"position": {
"description": "1-based position in the emitted rows for this source and list",
"title": "Position",
"type": "integer"
},
"privateAccount": {
"description": "Whether this account is private",
"title": "Private Account",
"type": "boolean"
},
"profileUrl": {
"description": "Canonical https://www.tiktok.com/@username URL",
"title": "Profile URL",
"type": "string"
},
"scrapedAt": {
"description": "ISO 8601 UTC datetime when this row was generated",
"title": "Scraped At",
"type": "string"
},
"secUid": {
"description": "TikTok secure user identifier used for API calls",
"title": "Secure UID",
"type": "string"
},
"sourceFollowerCount": {
"description": "Exact follower count of the source profile from statsV2",
"title": "Source Follower Count",
"type": "integer"
},
"sourceFollowingCount": {
"description": "Exact following count of the source profile from statsV2",
"title": "Source Following Count",
"type": "integer"
},
"sourceIsOrganization": {
"description": "Whether TikTok classifies the source profile as an organization",
"title": "Source Is Organization",
"type": "boolean"
},
"sourcePrivate": {
"description": "Whether the source profile is private",
"title": "Source Private",
"type": "boolean"
},
"sourceProfileUrl": {
"description": "Canonical TikTok profile URL of the source account",
"title": "Source Profile URL",
"type": "string"
},
"sourceUserId": {
"description": "TikTok user ID of the profile whose list was scraped",
"title": "Source User ID",
"type": "string"
},
"sourceUsername": {
"description": "The @username of the profile whose list was scraped",
"title": "Source Username",
"type": "string"
},
"sourceVerified": {
"description": "Whether the source profile has a verified badge",
"title": "Source Verified",
"type": "boolean"
},
"ttSeller": {
"description": "Whether this account sells through TikTok Shop",
"title": "TikTok Shop Seller",
"type": "boolean"
},
"userId": {
"description": "TikTok user ID of this account",
"title": "User ID",
"type": "string"
},
"username": {
"description": "TikTok @handle (uniqueId) of this account",
"title": "Username",
"type": "string"
},
"verified": {
"description": "Whether this account has a TikTok verified badge",
"title": "Verified",
"type": "boolean"
},
"videoCount": {
"description": "Number of public videos posted by this account from statsV2",
"title": "Video Count",
"type": "integer"
}
},
"title": "TikTok Followers & Following",
"views": {
"overview": {
"description": "TikTok accounts from a profile's followers or following list, with exact audience stats and source context.",
"display": {
"component": "table",
"properties": {
"diggCount": {
"format": "number",
"label": "Likes Given"
},
"displayName": {
"format": "text",
"label": "Display Name"
},
"followerCount": {
"format": "number",
"label": "Followers"
},
"followingCount": {
"format": "number",
"label": "Following"
},
"heartCount": {
"format": "number",
"label": "Likes Received"
},
"listTotal": {
"format": "number",
"label": "List Total"
},
"listType": {
"format": "text",
"label": "List Type"
},
"position": {
"format": "number",
"label": "Position"
},
"privateAccount": {
"format": "boolean",
"label": "Private"
},
"profileUrl": {
"format": "text",
"label": "Profile URL"
},
"scrapedAt": {
"format": "text",
"label": "Scraped At"
},
"sourceUsername": {
"format": "text",
"label": "Source Profile"
},
"ttSeller": {
"format": "boolean",
"label": "TikTok Shop Seller"
},
"userId": {
"format": "text",
"label": "User ID"
},
"username": {
"format": "text",
"label": "Username"
},
"verified": {
"format": "boolean",
"label": "Verified"
},
"videoCount": {
"format": "number",
"label": "Videos"
}
}
},
"title": "Follow graph",
"transformation": {
"fields": [
"sourceUsername",
"listType",
"position",
"userId",
"username",
"displayName",
"verified",
"privateAccount",
"ttSeller",
"followerCount",
"followingCount",
"heartCount",
"videoCount",
"diggCount",
"listTotal",
"profileUrl",
"scrapedAt"
]
}
}
}
}
Key-value schema
Published key-value store definitions, when provided by this build.
This definition is not present in the default published build. See the published README for available documentation.
Published README
Read the full published documentation
TikTok Follow Graph & Audience Export Scraper
Export the two sides of a public TikTok account's follow graph: the accounts that follow it, the accounts it follows, or both. Every row is a real public profile with exact audience stats, source context, and optional contact signals from the bio. The actor needs no TikTok login, session cookie, or API key.
TikTok's web app signs its own list requests. This actor asks the page to make those requests, so public follower and following lists are reachable without a user session. Private accounts and hidden following lists are not bypassed; the run reports them instead of inventing rows.
What this actor does
- Exports followers (scene 67) and following (scene 21) for public profiles.
- Accepts usernames,
@handles, and profile URLs, includingm.tiktok.comlinks. - Works on one profile or a batch of profiles in the same run.
- Walks each list cursor by cursor, not just the first page.
- Adds exact follower, following, likes-received, video, likes-given, and friend counts from TikTok's
statsV2. - Can filter the audience by verification, TikTok Shop seller status, privacy, follower range, bio/name keywords, or the presence of a public bio email.
- Supports both lists in one run.
- Reports hidden/private lists and source shortfalls in the run status and
RUN_SUMMARY, never as fake rows.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
profiles |
string list | - | TikTok usernames, @handles, or profile URLs. Paste one per line. |
listType |
select | following |
followers, following, or both. |
maxUsersPerProfile |
integer | 100 |
Maximum rows per requested list (1-5000). Each list gets this cap. |
includeStats |
boolean | true |
Adds follower, following, likes-received, video, likes-given, and friend counts. |
includeBioEmail |
boolean | false |
Adds a public email from the bio when one is present. |
onlyVerified |
boolean | false |
Keeps only verified accounts. |
sellerOnly |
boolean | false |
Keeps only TikTok Shop sellers. |
excludePrivate |
boolean | false |
Skips private accounts. |
minFollowers |
integer | 0 |
Minimum follower count for a listed account; 0 = off. |
maxFollowers |
integer | 0 |
Maximum follower count for a listed account; 0 = no maximum. |
bioKeywords |
string list | [] |
Keeps rows whose bio or display name contains any keyword (case-insensitive). |
onlyWithEmail |
boolean | false |
Keeps only rows with a public bio email; also fills bioEmail. |
scanLimit |
integer | 0 |
Maximum list rows to scan before stopping; 0 = automatic (10x the row cap, up to 10,000). Raise it for rare filters. |
profiles is not marked required in the schema so saved tasks that still send the legacy usernames or profileUrls keys keep running. The actor reads those legacy keys, maps them onto profiles, and fails clearly only when no valid target remains. A legacy sessionCookie is accepted but ignored; it is no longer needed.
Example: followers
{
"profiles": ["natgeo"],
"listType": "followers",
"maxUsersPerProfile": 100,
"includeStats": true
}
Example: both lists with filters
{
"profiles": [
"https://www.tiktok.com/@sephora",
"@natgeo"
],
"listType": "both",
"maxUsersPerProfile": 500,
"includeStats": true,
"includeBioEmail": true,
"excludePrivate": true,
"minFollowers": 1000,
"bioKeywords": ["beauty", "skincare"]
}
Output
One dataset row is one account in one requested list. The same account can appear once in followers and once in following because those are different relationships.
Identity and relationship
sourceUsername,sourceUserId,sourceProfileUrl,listTypeposition- 1-based order in the emitted rows for this source/listlistTotal- total relationship count reported by TikTok for this listuserId,secUid,username,displayName,profileUrlbio,avatarUrl,scrapedAt
Account status
verified,privateAccount,ttSellerisOrganization- kept for compatibility, but TikTok's list endpoint usually does not expose it, so it is usually omitted.
Exact audience stats
followerCount,followingCount,heartCount(likes received)videoCount,diggCount(likes given),friendCount
Source context
sourceFollowerCount,sourceFollowingCountsourceVerified,sourcePrivate,sourceIsOrganization
Optional contact signal
bioEmail- first public-looking email in the bio, only when email extraction is enabled. Omitted when no valid email is present.
All fields are omitted when empty. Zero counts are real values and are kept. avatarUrl is a signed TikTok CDN URL and may expire; profileUrl is the permanent link.
How it works
- The actor opens the public profile page in a headless Chromium browser. No user session or cookie is supplied.
- It reads the profile's own SSR payload for the secure user ID, exact
statsV2, and the account's following visibility. - Inside that page, it asks TikTok's own client to call the relationship-list endpoint with scene 67 (followers) or scene 21 (following). TikTok's page runtime signs the request and attaches the anonymous session token.
- It follows the returned cursors until the requested cap, the end of the source list, a stagnant cursor, a source truncation, or the scan limit.
- Rows are deduplicated by user ID per source/list, filtered, assigned a position, and pushed to the dataset.
No sessionCookie is injected. No manual X-Bogus or X-Dynosaur value is replayed. The page signs each request.
What is available and what is not
Available for public profiles: follower and following lists, exact account stats, verification, privacy, TikTok Shop seller status, bio, avatar, profile URL, and optional bio email.
Not available from this source:
- Private accounts: both lists are blocked.
- A public account that hides its following list: the following list is unavailable, while its followers may still be exported.
bioLink,region,language,createTime, and per-followfollowedAt: TikTok's list endpoint does not return them.isOrganizationfor listed accounts: usually absent from the list payload.- Guaranteed row count parity: TikTok does not return every row for every account (deleted, private, or restricted accounts are omitted). The run reports the source total and the returned count.
FAQ
Do I need a TikTok account or cookies? No. Public follower and following lists are exported without a login, session cookie, or API key.
Why can a run return fewer rows than the profile's follower count?
TikTok's list endpoint omits accounts it cannot expose (for example deleted, private, or restricted accounts). The run records the source total in listTotal, the returned count in RUN_SUMMARY, and the source shortfall in the final status message. Filters can also reduce the pushed rows; use scanLimit to search deeper for rare filters.
Why is a following list empty? The account may not follow anyone, or it may hide its following list. A hidden list is reported in the run status; no rows are invented.
Can I export a private account's followers? No. Private accounts are not bypassed.
Why is isOrganization missing?
TikTok's relationship-list payload usually does not include it. The field remains in the output contract for compatibility and is filled only if the source provides it.
Are avatar URLs permanent?
No. They are signed CDN links that expire. Use profileUrl for a permanent link.
Can I filter by follower count or bio keyword?
Yes. Use minFollowers, maxFollowers, bioKeywords, onlyVerified, sellerOnly, excludePrivate, or onlyWithEmail.
How are filters applied? After the list is fetched, before rows are pushed. Filtered-out rows are not charged.
Does maxUsersPerProfile apply to each list or the whole run?
Each requested list gets the cap. For listType: "both", followers and following can each return up to the cap.
Data source and responsible use
The actor reads publicly visible TikTok profile and relationship data. It does not log in, bypass private accounts, or access non-public content. Use the output only for lawful research, analytics, and outreach, and comply with TikTok's terms and applicable privacy laws.
Python quickstart
Use a schema-derived input and the Python standard library to start a run. An Apify account and token are required for execution.
Source build 2GxiEUurrlbYIDHYi. Documentation is regenerated from the default published build; private drafts are not included.