TikTok Profile Scraper With Bio Link & Contact Leads
Pricing
Pay per usage
TikTok Profile Scraper With Bio Link & Contact Leads
The TikTok Profile Scraper extracts public TikTok profile data, including usernames, bios, followers, following counts, likes, and profile URLs. Ideal for marketers, analysts, and researchers to track influencer metrics, study engagement, and build accurate audience insights efficiently.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
API Empire
Maintained by CommunityActor stats
0
Bookmarked
19
Total users
0
Monthly active users
3 days ago
Last modified
Categories
Share
TikTok Profile Scraper โ Extract Profiles, Bio Links and Videos
TikTok Profile Scraper With Bio Link & Contact Leads turns a list of TikTok handles into structured creator contact records: the bio link, everything found behind a Linktree/hoo.be-style aggregator, best-effort email and phone parsed from the bio and captions, plus exact follower, heart and account-age signals. Each record ships as typed, normalized JSON โ no HTML, no selectors, no manual cleanup. The Actor runs logged out and prints its own measured bio-link and email find-rates into the run log for every run, so coverage is observable rather than promised. Feed it a handle list and get back an outreach-ready dataset in one run.
What is TikTok Profile Scraper With Bio Link & Contact Leads?
TikTok Profile Scraper With Bio Link & Contact Leads is an Apify Actor that turns a list of TikTok creator handles into contact records built around the bio link โ the one field TikTok most reliably exposes for outreach โ plus everything the Actor can extract or infer around it. It targets TikTok's public profile page and the public item_list video endpoint; no TikTok account, login or cookie is required at any point.
- ๐ชช Build one contact record per creator: bio link, expanded aggregator destinations, best-effort email/phone, follower and account-age signals
- ๐ Follow Linktree / hoo.be / Beacons / bio.link style bio links to their real destination URLs
- ๐ฌ Pull each creator's recent videos as backward-compatible child rows, and scan captions for contacts the bio doesn't carry
- ๐ Filter the output down to only creators that expose a contact, with an auditable uncharged reason for everyone dropped
- ๐ค Export as JSON, CSV or Excel, or read the dataset straight through the Apify API
What data does TikTok Profile Scraper With Bio Link & Contact Leads collect?
Every run produces up to three row types, distinguished by the type field: a charged creator contact record per handle, uncharged video rows behind it, and uncharged accounting rows that explain any skip or failure.
| Data Type | Key Fields | JSON Field Names |
|---|---|---|
| Creator contact record | Bio link, expanded destinations, email, phone, follower/heart counts, account age | bioLink, aggregatorDestinations, primaryEmail, phones, fans, accountAgeDays |
| Video (creator's own recent uploads) | Caption text, engagement counts, hashtags, mentions, subtitle links | text, diggCount, playCount, hashtags, mentions, videoMeta |
| Accounting / audit row | Why a handle produced no contact record, uncharged | type, errorReason, note |
๐ Need more TikTok data?
If the lead is in the comment section rather than the bio, TikTok Comments Scraper With Commenter Profile & Contacts collects comments and enriches every unique commenter with the same bio-contact extraction used here. For raw video metrics without the contact layer, TikTok Video Scraper pulls engagement and author metadata straight from post URLs. To find which creators to target in the first place, TikTok Trending Hashtags Scraper โ Find New & Rising Tags flags hashtags entering the charts before they peak.
How does TikTok Profile Scraper With Bio Link & Contact Leads differ from the official TikTok API?
TikTok's own developer platform does not offer arbitrary bulk creator lookup โ it authorizes one TikTok account to share its own data with one app, which is a different problem than building a lead list from other creators' public profiles.
| Feature | TikTok Developer APIs | TikTok Profile Scraper With Bio Link & Contact Leads |
|---|---|---|
| Whose data you can read | Only the authenticated user's own profile and videos, via the Display API (developers.tiktok.com/doc/display-api-get-started, checked 2026-07-25) | Any public creator handle you supply |
| Access model | OAuth login and explicit consent from the account owner, via Login Kit | No account, no login โ reads the public profile page directly |
| Approval process | App must be reviewed and granted user.info.basic / video.list scopes before any call succeeds | None โ start a run from the Apify Console |
| Bulk creator lookup | Not supported; each authorized session is scoped to one user | A single run accepts a list of handles |
| Public-video research access | Separate Research API, research.data.basic scope, restricted to an approved research application; queries are capped at a 30-day date range per request (developers.tiktok.com/doc/research-api-specs-query-videos, checked 2026-07-25) | No application, no date-range cap on which creators you can query |
| Bio-link and contact extraction | Not a field either API returns | Bio link, aggregator expansion, best-effort email/phone are the Actor's core output |
If you already operate the target account and just need its own posts inside an authorized app, the Display API is the correct, TikTok-sanctioned path. If you need public contact data across creators you don't operate โ the actual lead-generation use case โ neither TikTok API reaches it, which is the gap this Actor fills.
Why do developers and teams scrape TikTok creator profiles?
๐ For marketers and brand teams
Influencer and partnerships teams turn a shortlist of handles into a contactable pipeline in one run: bioLink, primaryEmail and aggregatorDestinations replace the manual click-through-every-profile step, and contactScore gives an instant rank so outreach starts with the creators most likely to have a real contact channel rather than the ones alphabetically first on the list.
๐ค For AI engineers and agent builders
A lead-qualification agent can call this Actor with a batch of handles, receive typed JSON with hasContact, contactScore, commerceCategory and accountAgeDays already computed, and route each record to an outreach queue or a CRM write without a parsing step in between. The stable field names mean the same prompt template works whether the run returned 5 creators or 5,000.
๐ฌ For researchers and analysts
verified, commerceUser, ttSeller and accountAgeDays let a researcher segment a creator sample by account legitimacy and business status without opening a single profile manually. Because every field is read from what TikTok's own profile page already renders publicly, the dataset stays within public-data scope for academic or market-structure studies.
๐ ๏ธ For developers building data products
statsAreExact flags whether a row's follower/heart/video counts came from TikTok's exact statsV2 string counters or a rounded fallback โ a distinction a lead-scoring or CRM-enrichment product needs before treating a count as precise. Feeding the dataset on a schedule keeps a downstream lookup table current without hand-rolling TikTok's hydration parsing.
How to scrape TikTok creator profiles (step by step)
- Open TikTok Profile Scraper With Bio Link & Contact Leads on the Apify Console and click Try for free
- Paste creator handles into ๐ฏ TikTok Creator Handles โ a bare handle, an
@handle, or a full profile URL all work, one per line - Set ๐ฌ Videos to pull per creator to
0for the fastest profile-only run, or leave the default of 10 to also pull recent videos and scan their captions for contacts - Turn on ๐ Keep only creators that expose a contact if you only want creators with a bio link, email or phone in the final dataset
- Click Start, then export the dataset as JSON, CSV or Excel, or pull it through the Apify API
What to do when TikTok changes its structure
The scraper is maintained, and the output schema is designed to stay stable across TikTok structural changes โ field names and types don't change on your end even when the underlying page payload does. No specific turnaround time is published; check the Actor's build history for the latest update.
โ ๏ธ What changed in TikTok scraping recently?
Two engineering findings from this Actor's own 2026-07 measurement pass changed how a logged-out TikTok scraper has to be built. First, TikTok's older SIGI_STATE / sigi-persisted-data hydration blobs are gone from the profile page โ the only hydration script left is __UNIVERSAL_DATA_FOR_REHYDRATION__, so any scraper still parsing the old blob name silently returns nothing. Second, TikTok now WAF-challenges desktop browser TLS fingerprints on the profile page: a challenge comes back as an ordinary HTTP 200 with a roughly 1.4 KB body containing _wafchallengeid, so checking the status code alone reports success on a page that is actually a block. This Actor fetches with a mobile TLS impersonation target (chrome99_android first) specifically because desktop fingerprints get challenged. A third, related finding: TikTok no longer server-renders a creator's post grid into the profile page at all โ 100% of video data now comes from the separate /api/creator/item_list/ endpoint, which hard-caps the count parameter at 10 per request regardless of what is requested. The scraper is maintained against all three; no numeric SLA is published for future changes.
โฌ๏ธ Input
None of the fields below are required โ an empty run simply logs an error and produces no rows, so at minimum fill in the creator handles field.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
creatorHandles | No | array | One creator per line: a bare handle (mrbeast), an @handle (@thekoreanvegan) or a full profile URL. Each creator produces exactly one charged contact-record row. No default (empty list). | ["thekoreanvegan", "mrbeast"] |
contactsOnly | No | boolean | When true, a creator with no bio link, email or phone is dropped from the results but still writes an uncharged accounting row naming the reason. Default false. | false |
expandLinkAggregators | No | boolean | Follows a Linktree/hoo.be/Beacons/bio.link-style bio link and returns the real destination URLs behind it. Default true. | true |
scanVideoCaptions | No | boolean | Runs the email/phone/URL extractor over fetched video captions as well as the bio. Default true. | true |
customDomains | No | array | Optional email-domain allowlist. Leave empty to keep every extracted address. Default []. | ["gmail.com", "mycompany.com"] |
maxVideosPerCreator | No | integer | Recent videos to fetch per creator. Minimum 0, maximum 200, default 10. Set 0 for a profile-only, contacts-only run. | 10 |
includeVideoRows | No | boolean | Off keeps the dataset to contact records only; captions are still scanned either way. Video rows are never charged regardless of this setting. Default true. | true |
profileSorting | No | string | Client-side ordering of the fetched video window only โ TikTok's API does not sort server-side. Enum: latest (Newest first), popular (Most viewed first), oldest (Oldest of the fetched window first). Default "latest". | "latest" |
oldestPostDateUnified | No | string | Absolute date (YYYY-MM-DD) or relative days-ago (e.g. 30). Filters video rows and the caption contact scan; the contact record itself is always produced regardless. No default. | "2026-01-01" |
newestPostDate | No | string | Absolute date (YYYY-MM-DD) or relative days-ago (e.g. 0 for today). No default. | "0" |
leastDiggs | No | integer | Minimum heart (like) count on a video row. Minimum 1. No default. | 1000 |
mostDiggs | No | integer | Maximum heart (like) count on a video row. Minimum 1. No default. | 500000 |
profiles | No | array | Backward-compatible alias for creatorHandles, under the original TikTok Profile Scraper's key. When both profiles and creatorHandles are filled, profiles wins. No default. | ["nike"] |
resultsPerPage | No | integer | Backward-compatible alias for maxVideosPerCreator. Minimum 0, maximum 200. Wins over maxVideosPerCreator when both are filled. No default. | 10 |
profileScrapeSections | No | array | Accepted for backward compatibility only. Enum items: videos, reposts. This Actor reads a creator's own videos only โ the value is never read by the run logic, so setting it has no effect. | ["videos"] |
maxFollowersPerProfile | No | integer | Author-level ceiling applied to video rows: a video row is dropped when its author's follower count is at or above this value. Minimum 1. No default. | 5000000 |
maxFollowingPerProfile | No | integer | Author-level ceiling applied to video rows: a video row is dropped when its author's following count is at or above this value. Minimum 1. No default. | 10000 |
proxyConfiguration | No | object | Apify Proxy settings. Prefilled to {"useApifyProxy": false} โ the run starts with no proxy at all. On a soft block the Actor escalates itself to datacenter, then residential, only while a creator has produced zero rows, regardless of what this field was set to. | {"useApifyProxy": false} |
Example input
{"creatorHandles": ["thekoreanvegan", "mrbeast", "https://www.tiktok.com/@nike"],"contactsOnly": false,"expandLinkAggregators": true,"scanVideoCaptions": true,"customDomains": [],"maxVideosPerCreator": 10,"includeVideoRows": true,"profileSorting": "latest","oldestPostDateUnified": "","newestPostDate": "","leastDiggs": null,"mostDiggs": null,"maxFollowersPerProfile": null,"maxFollowingPerProfile": null,"proxyConfiguration": { "useApifyProxy": false }}
Common pitfall: filling in both a legacy key and its replacement โ profiles alongside creatorHandles, or resultsPerPage alongside maxVideosPerCreator โ is not additive. The legacy key silently wins in both cases, so a value typed into the new field appears to be ignored. Fill one of each pair, not both.
โฌ๏ธ Output
Every row lands in the same Apify dataset with a type field marking which of the three shapes it is: profile (the charged contact record), video (an uncharged child row), or accounting (an uncharged audit row). Export as JSON, CSV or Excel, or read the dataset through the Apify API. The dataset's default table view surfaces 26 of the profile row's fields; the full row carries more, documented below from the Actor's row-building code.
Scraped creator contact record (type: "profile")
This is the only row type that is charged โ one row_result event per creator, whether or not a contact was found (unless contactsOnly dropped it as an uncharged skip instead).
| Field | Description |
|---|---|
type, isChild | Always "profile" and false for this row shape |
id, input, username, nickName | TikTok's internal user ID, the handle you supplied, the resolved uniqueId, and the display name |
profileUrl, secUid, avatar, originalAvatarUrl | Canonical profile URL, TikTok's internal secUid, and both avatar image sizes |
bioLink, bioLinkHost | The raw bio-link URL exactly as TikTok stores it, and its hostname |
bio, shareDescription | The profile's bio text (signature), and TikTok's share-card description |
isLinkAggregator, aggregatorDestinations, aggregatorExpansionStatus | Whether bioLink is a recognized aggregator, the real destination URLs found behind it, and how that expansion went |
emails, primaryEmail, emailSource | Every extracted email address, the first one (or null), and whether it came from "bio" or "caption" |
phones | Every extracted phone number, in its original matched format |
websites, socialProfiles | Every non-asset URL found across the bio link, aggregator destinations and extracted text; and the subset matched to a known social platform |
contactScore, hasContact | A 0โ100 composite score (see formula below), and whether any contact channel was found at all |
verified, commerceUser, commerceCategory, ttSeller, isOrganization, privateAccount | TikTok's own account-type and business flags |
accountCreatedAt, accountCreatedTimestamp, accountAgeDays | Account creation time as ISO-8601 and as a raw Unix timestamp, and the age in days computed at scrape time |
roomId, nickNameModifiedAt, uniqueIdModifiedAt | Live-room ID if any, and when the display name / handle were last changed |
fans, following, heart, video, digg, friends | Follower count, following count, total hearts received, video count, likes given, and friend count |
statsAreExact | true when the counts above came from TikTok's exact statsV2 string counters rather than a rounded fallback |
videosAnalyzed | How many video rows were fetched and scanned behind this contact record |
errorReason, scrapedAt | Always null on a successful row, and the UTC scrape timestamp |
contactScore is computed as 40 (has an email) + 30 (has a bio link) + 15 (aggregator expansion found destinations) + 10 (a known social platform was matched) + 5 (has a phone number). hasContact is true when any of email, bio link, phone or aggregator destinations is present โ a social handle alone does not set it.
{"type": "profile","isChild": false,"id": "6829105512345678901","input": "fitcoachjordan","username": "fitcoachjordan","nickName": "Coach Jordan Fit","profileUrl": "https://www.tiktok.com/@fitcoachjordan","secUid": "MS4wLjABAAAA_examplesecuid","avatar": "https://p16-sign-va.tiktokcdn.com/avatar-medium.jpeg","originalAvatarUrl": "https://p16-sign-va.tiktokcdn.com/avatar-large.jpeg","bioLink": "https://linktr.ee/fitcoachjordan","bioLinkHost": "linktr.ee","bio": "Certified trainer | Programs & bookings below | jordan@fitcoachjordan.com","shareDescription": "Coach Jordan Fit on TikTok","isLinkAggregator": true,"aggregatorDestinations": ["https://fitcoachjordan.com","https://instagram.com/fitcoachjordan","https://calendly.com/fitcoachjordan"],"aggregatorExpansionStatus": "expanded","emails": ["jordan@fitcoachjordan.com"],"primaryEmail": "jordan@fitcoachjordan.com","emailSource": "bio","phones": [],"websites": ["https://linktr.ee/fitcoachjordan","https://fitcoachjordan.com","https://instagram.com/fitcoachjordan","https://calendly.com/fitcoachjordan"],"socialProfiles": [{ "platform": "instagram", "url": "https://instagram.com/fitcoachjordan" }],"contactScore": 95,"hasContact": true,"verified": false,"commerceUser": true,"commerceCategory": "Health & Fitness","ttSeller": false,"isOrganization": false,"privateAccount": false,"roomId": null,"nickNameModifiedAt": "2024-03-11T09:22:41Z","uniqueIdModifiedAt": "2022-08-02T14:05:19Z","accountCreatedAt": "2020-01-26T02:13:20Z","accountCreatedTimestamp": 1580004800,"accountAgeDays": 2372,"fans": 128400,"following": 512,"heart": 3120000,"video": 340,"digg": 8021,"friends": 12,"statsAreExact": true,"videosAnalyzed": 10,"errorReason": null,"scrapedAt": "2026-07-25T14:02:11Z"}
Scraped video row (type: "video")
Uncharged child rows, pushed when includeVideoRows is on. Structurally the same shape as the base TikTok Profile Scraper's video row for drop-in compatibility.
| Field | Description |
|---|---|
type, isChild, id | Always "video", true, and TikTok's video ID |
text, textLanguage | Caption text and TikTok's detected language (null if not returned) |
createTime, createTimeISO | Post time as Unix timestamp and real UTC ISO-8601 |
isAd, isSponsored, isPinned, isSlideshow | TikTok's own ad, sponsorship, pinned and slideshow flags |
authorMeta | Nested object: id, name, profileUrl, nickName, verified, signature, bioLink, avatars, commerceUserInfo, privateAccount, roomId, ttSeller, following, friends, fans, heart, video, digg. followDatasetUrl is a legacy field, always null |
musicMeta | Nested object: musicName, musicAuthor, musicOriginal, playUrl, coverMediumUrl, originalCoverMediumUrl, musicId |
locationMeta | Nested object with address, city, cityCode, countryCode, locationName, locationId โ empty object {} when TikTok attaches no location |
webVideoUrl, mediaUrls | Canonical video URL, and playable/downloadable media URLs |
videoMeta | Nested object: height, width, duration, coverUrl, originalCoverUrl, definition, format, subtitleLinks (array of caption-track objects) |
diggCount, shareCount, playCount, collectCount, commentCount, repostCount | Engagement counters, exact statsV2 when available |
hashtags, mentions, detailedMentions | Hashtag names, @-mentions, and a byte-identical duplicate of mentions kept for base compatibility |
effectStickers | Effect/sticker metadata attached to the post |
commentsDatasetUrl | Legacy field, always null โ no linked comments dataset is produced by this Actor |
input, fromProfileSection, scrapedAt | The handle you supplied, always "videos", and the UTC scrape timestamp |
{"type": "video","isChild": true,"id": "7398201847561234567","text": "Booking now open for the fall program! Link in bio #fitness #onlinecoaching","textLanguage": "en","createTime": 1753372800,"createTimeISO": "2025-07-24T18:20:00Z","isAd": false,"authorMeta": {"id": "6829105512345678901","name": "fitcoachjordan","profileUrl": "https://www.tiktok.com/@fitcoachjordan","nickName": "Coach Jordan Fit","verified": false,"signature": "Certified trainer | Programs & bookings below | jordan@fitcoachjordan.com","bioLink": "https://linktr.ee/fitcoachjordan","originalAvatarUrl": "https://p16-sign-va.tiktokcdn.com/avatar-large.jpeg","avatar": "https://p16-sign-va.tiktokcdn.com/avatar-medium.jpeg","commerceUserInfo": { "commerceUser": true, "category": "Health & Fitness" },"privateAccount": false,"roomId": "","ttSeller": false,"followDatasetUrl": null,"following": 512,"friends": 12,"fans": 128400,"heart": 3120000,"video": 340,"digg": 8021},"musicMeta": {"musicName": "original sound","musicAuthor": "fitcoachjordan","musicOriginal": true,"playUrl": "https://sf16-ies-music.tiktokcdn.com/track.mp3","coverMediumUrl": "https://p16-sign-va.tiktokcdn.com/music-cover.jpeg","originalCoverMediumUrl": "https://p16-sign-va.tiktokcdn.com/music-cover.jpeg","musicId": "7398201800001234567"},"locationMeta": {},"webVideoUrl": "https://www.tiktok.com/@fitcoachjordan/video/7398201847561234567","mediaUrls": ["https://v16.tiktokcdn.com/video-play.mp4"],"videoMeta": {"height": 1024,"width": 576,"duration": 38,"coverUrl": "https://p16-sign-va.tiktokcdn.com/video-cover.jpeg","originalCoverUrl": "https://p16-sign-va.tiktokcdn.com/video-cover-orig.jpeg","definition": "720p","format": "mp4","subtitleLinks": []},"diggCount": 15234,"shareCount": 342,"playCount": 210500,"collectCount": 980,"commentCount": 512,"repostCount": 12,"mentions": [],"detailedMentions": [],"isPinned": false,"commentsDatasetUrl": null,"hashtags": [{ "name": "fitness" }, { "name": "onlinecoaching" }],"effectStickers": [],"isSlideshow": false,"isSponsored": false,"input": "fitcoachjordan","fromProfileSection": "videos","scrapedAt": "2026-07-25T14:02:14Z"}
Accounting / audit row (type: "accounting")
Uncharged. Written whenever a handle produces no contact record โ a WAF block, an unparseable page, a missing/private/removed profile, or a contactsOnly skip.
| Field | Description |
|---|---|
type, isChild, id | Always "accounting", false, and null |
input, username, profileUrl | The handle you supplied, and the profile URL it resolved to |
bioLink, bio, emails, primaryEmail, phones, websites, socialProfiles, aggregatorDestinations, hasContact | All reset to their empty defaults โ null, [] or false |
errorReason | One of waf_blocked, unparseable_page, profile_not_found, profile_private, profile_unavailable, profile_data_missing, filtered_no_contact, unexpected_error, or a dynamic tiktok_status_<code> for a status code not in that list |
note | Human-readable detail for the reason, or null |
scrapedAt | UTC timestamp |
A contactsOnly skip row additionally carries fans (the follower count TikTok returned before the row was dropped), so a filtered creator's reach is still visible in the audit trail.
{"type": "accounting","isChild": false,"id": null,"input": "randomcreator22","username": "randomcreator22","profileUrl": "https://www.tiktok.com/@randomcreator22","bioLink": null,"bio": null,"emails": [],"primaryEmail": null,"phones": [],"websites": [],"socialProfiles": [],"aggregatorDestinations": [],"hasContact": false,"errorReason": "filtered_no_contact","note": "contactsOnly=true and this profile exposed no bio link, email or phone","fans": 842,"scrapedAt": "2026-07-25T14:02:09Z"}
Charged rows only carry row_result on type: "profile". To read only the billed rows from an exported dataset, filter on type == "profile"; everything with type of "video" or "accounting" was pushed for free.
How does TikTok Profile Scraper With Bio Link & Contact Leads compare to other TikTok scrapers?
| Feature | TikTok Profile Scraper With Bio Link & Contact Leads | Generic alternative |
|---|---|---|
| Output format | Typed JSON, stable schema, exported as JSON/CSV/Excel | Varies; several competitors ship a similar shape but with fewer documented fields |
| Aggregator expansion | Follows Linktree/hoo.be/Beacons/bio.link and returns the real destination URLs, honestly reporting no_ssr_links when a JS-only aggregator exposes nothing | Not documented on the competing listings reviewed |
| Charging on failure | Only a successfully parsed contact record is charged; WAF blocks, unparseable pages and contactsOnly skips write an uncharged accounting row | peakydev/leads-scraper-ppe's listing states a 100-lead minimum charge per run regardless of results returned (checked on the Apify Store 2026-07-25 โ not verified against its source) |
| Entity coverage | Contact record, video rows and audit rows in one run | gocreative.ai/tiktok-profile-scraper's listing documents profile rows only, with no video-level data (checked on the Apify Store 2026-07-25) |
| Login requirement | None โ reads the public profile page over a mobile TLS fingerprint | gocreative.ai/tiktok-profile-scraper's listing also advertises no login required (checked on the Apify Store 2026-07-25) |
If you're building an AI agent or RAG pipeline, the output-format row is the decision-maker โ parsing HTML inside an agent loop is a reliability failure mode, not a feature.
How many results can you scrape with TikTok Profile Scraper With Bio Link & Contact Leads?
There is no hard cap on how many creator handles you can submit in creatorHandles โ the Actor processes the list one handle at a time. Per creator, maxVideosPerCreator caps video rows at 200, matching the ceiling the Actor enforces in code; reaching it takes roughly 20 sequential paginated requests per creator because TikTok's item_list endpoint hard-caps its own count parameter at 10 items per request regardless of what is asked for. Set maxVideosPerCreator to 0 for the fastest possible run when you only need the contact record. No benchmark run time is published โ actual duration scales with how many creators you submit and how many videos you request per creator.
Integrate TikTok Profile Scraper With Bio Link & Contact Leads and automate your workflow
TikTok Profile Scraper With Bio Link & Contact Leads works with any language or tool that can send an HTTP request, since it runs as a standard Apify Actor.
REST API integration
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("<YOUR_USERNAME>/tiktok-profile-scraper-with-bio-link-contact-leads").call(run_input={"creatorHandles": ["thekoreanvegan", "mrbeast"],"contactsOnly": False,"maxVideosPerCreator": 10,})for lead in client.dataset(run["defaultDatasetId"]).iterate_items():if lead.get("type") == "profile":print(lead["username"], lead["bioLink"], lead["primaryEmail"])
Works in Python, Node.js, Go, Ruby, cURL.
Automation platforms (n8n, Make, LangChain)
In n8n, use the Apify node โ select this Actor, pass the same JSON input shown above, and route dataset items straight into a CRM or Google Sheets node on a schedule. In Make, the Apify module runs the Actor and hands its dataset output to any downstream module, so a weekly creator-list refresh needs no code. In a LangChain or similar agent framework, wrap the apify_client call above as a tool โ the Actor returns typed JSON, so the agent can read hasContact and contactScore directly without a parsing step.
Is it legal to scrape TikTok creator profiles?
Yes โ TikTok Profile Scraper With Bio Link & Contact Leads reads only what TikTok already renders on a creator's public profile page to any anonymous, logged-out visitor. No login-gated or private content is accessed.
Because the output includes personal data โ a bio, a follower count, and any email or phone the Actor extracts โ data-protection regimes like GDPR and CCPA apply to how you store and use it, not to whether the initial collection is technically possible. You need a lawful basis for processing (typically legitimate interest for B2B outreach) and must honor deletion and access requests from the individuals concerned. Extracted contact details should also be checked against outreach and anti-spam rules (e.g. CAN-SPAM) in your jurisdiction before use.
Consult legal counsel for commercial use cases involving bulk personal data.
โ Frequently asked questions
Does TikTok Profile Scraper With Bio Link & Contact Leads work without a TikTok account?
Yes. The Actor sends anonymous requests to TikTok's public profile page and video endpoint over a mobile-impersonated TLS session โ no TikTok login, cookie or session token is ever used, and the input schema has no field for one. The only credential you need is your Apify token.
How often is the scraped data updated?
Every run performs a live fetch against TikTok at the moment it runs โ nothing is cached or served from a stored snapshot. Re-run the Actor to get current follower counts, bio text and video data.
What happens if a creator's profile is private, removed or doesn't exist?
The Actor pushes an uncharged accounting row instead of a contact record, with errorReason set to profile_private, profile_not_found, profile_unavailable, or profile_data_missing depending on what TikTok returned. No fabricated or partial contact record is produced for a handle that failed.
Can I scrape private TikTok accounts?
No. Only publicly accessible profile data is returned. A private account resolves to an uncharged profile_private accounting row rather than any profile data.
Is there a minimum charge or free trial?
Pricing and any free-usage allowance are set on the Actor's Apify Store listing under the Pricing tab, not in this README โ check the listing for the current terms before running at volume.
Does TikTok Profile Scraper With Bio Link & Contact Leads work for AI agent workflows and LLM pipelines?
Yes. It's callable as a standard HTTP endpoint through the Apify API, so any agent framework โ LangChain, CrewAI, a custom tool definition โ can invoke it and receive typed JSON directly, with no parsing step before passing a record into an LLM context window.
How does TikTok Profile Scraper With Bio Link & Contact Leads handle TikTok's anti-bot system?
It fetches with mobile TLS impersonation (chrome99_android first, falling back through three other mobile/desktop targets) because TikTok WAF-challenges desktop fingerprints. A challenge response โ HTTP 200 with a short body containing _wafchallengeid โ is detected by body content and size, not by status code, and triggers a retry with the next fingerprint. If fingerprint rotation alone doesn't clear it, the Actor escalates itself from no proxy to a datacenter proxy, then a residential proxy, but only while a given creator has produced zero rows โ so a retry can never duplicate or double-charge a row.
How does TikTok Profile Scraper With Bio Link & Contact Leads compare to other TikTok scrapers?
Checked on the Apify Store on 2026-07-25, gocreative.ai/tiktok-profile-scraper's listing advertises email, Instagram-handle and Linktree extraction from the bio with no login required, similar in scope to this Actor's contact layer but documented as profile-only, with no video rows. peakydev/leads-scraper-ppe and peakydev/leads-scraper target a broader, cross-platform lead database (their listings describe "700M verified leads... similar to Apollo") rather than TikTok specifically, and their listings state a 100-lead minimum charge per run. This Actor's difference is the aggregator-expansion layer โ following a Linktree-style bio link to its real destination URLs rather than stopping at the aggregator link itself โ combined with an uncharged, auditable accounting row for every creator that produces no contact record.
Does TikTok Profile Scraper With Bio Link & Contact Leads return data in a format LLMs can use directly?
Yes. Every response is typed, normalized JSON with stable field names across runs. No HTML, no selectors, no parsing. Pass a row directly into an LLM context window, index it into a vector store, or route it through an agent tool.
Can I use TikTok Profile Scraper With Bio Link & Contact Leads without managing proxies?
Yes, in the sense that no proxy is required to start โ the default input runs with no proxy at all. If TikTok soft-blocks a request, the Actor manages the proxy ladder itself (datacenter, then residential) without any action from you. If you want a specific behavior from the start, set proxyConfiguration to your preferred Apify Proxy group.
What happens when TikTok changes its structure or blocks the scraper?
The scraper is maintained, and the output schema is built to stay stable on your end โ field names and types don't change even when TikTok's underlying page structure does. No numeric turnaround time is promised for a fix after a breaking TikTok change.
๐ฌ Your feedback
Found a bug, or a field in TikTok's profile payload that isn't in the output yet? Open an issue on the Actor's Issues tab on Apify โ a report backed by the affected handle and a run log is the fastest to act on.