Datasets API endpoint
Use Crawlora's Search the TikTok creators dataset API to search or inspect stored structured datasets as JSON. This page includes request parameters, cURL examples, response schema, validation behavior, credit cost, and a Playground link for testing before integration. Dataset endpoints read indexed records and do not apply proxy routing.
/datasets/creators/searchSearches TikTok creators stored in a search index (one document per creator), with follower counts, verified status, niche, and engagement. Deleted and private accounts are excluded by default; set `include_inactive=true` to include them for historical lookups. Sort enum: `followers_desc`, `engagement_desc`, `engagement_qualified_desc`, `likes_desc`, `relevance`. Coverage note: `followers_desc`, `likes_desc`, and `relevance` are backed by profile fields present across the full dataset; the post-level engagement metrics (`engagement_rate`, `avg_views`, and the nested `post_stats` object) and the `engagement_desc`/`engagement_qualified_desc` sorts are currently populated for a growing subset of creators, prioritizing the highest-reach accounts. Creators without these metrics are still returned but sort last under `engagement_desc` and omit those fields; `engagement_qualified_desc` excludes them outright (they cannot clear its floors). `engagement_desc` ranks by raw `engagement_rate` with no eligibility floor — it surfaces a real stale-record + ratio-by-design trap: an account whose last real post was years ago can still carry an unrealistic rate computed from a handful of old posts. `engagement_qualified_desc` is the same metric restricted to creators with a recent post (`last_post_at` within 90 days), a minimum reach (`avg_views >= 10000`) and sample size (`post_stats.sampled_posts >= 10`), and a sanity ceiling (`engagement_rate <= 50%`) — use this, not the raw sort, for a "best engagement" leaderboard. Sound fields: `post_stats.top_sounds` holds only a creator's FIVE most-used sounds from the sampled posts, ranked by use count with ties broken by lowest `music_id`, so it is a top-5 view and not the creator's full sound list; `post_stats.distinct_sounds` gives the true number of different sounds the sample used. Use each sound's `original` boolean to tell TikTok-generated original audio from catalogue tracks - do NOT infer it from the title, because TikTok localizes the original-audio label (`sonido original`, `som original`, `оригинальный звук`, and at least fifteen more), so a title match silently reclassifies original audio as named tracks. Developers commonly use this endpoint for repeatable dataset search, filtering, facets, local business enrichment, analytics, exports, and internal tools that need structured records beyond the limited manual refinement available in the Google Maps app. Authentication uses the x-api-key header, usage is metered with the credit cost shown on this page, and the request does not trigger live scraping or proxy routing.
Request parameters are generated from the active endpoint catalog. Dataset parameters filter, page, facet, or locate stored structured records; they do not configure a live scraper or proxy path.
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| q | string | No | Full-text query over handle, nickname and bio, max 256 characters | ||
| handle | string | No | Exact handle lookup (case-insensitive), e.g. khaby.lame; returns the single creator with that exact @handle | ||
| niche | string | No | Exact content-niche filter, max 128 characters | ||
| country | string | No | Exact creator country/region filter, max 128 characters | ||
| verified | boolean | No | Filter by verified badge; true keeps only verified creators | ||
| min_followers | integer | No | Minimum follower count | ||
| has_email | boolean | No | Filter by contact-email presence; true keeps only creators with an email | ||
| include_email | boolean | No | Return the stored contact email instead of a blanked value. Off by default for everyone, and honoured only for entitled (non-Free) API keys | ||
| include_inactive | boolean | No | false (only live accounts returned | Include deleted/private accounts; defaults to false (only live accounts returned) | |
| sort | string | No | Sort enum: followers_desc, engagement_desc, engagement_qualified_desc, likes_desc, relevance. engagement_desc ranks by raw post-level engagement rate, currently populated for a subset of creators (highest-reach first); creators without it sort last. engagement_qualified_desc is the same metric restricted to creators with a recent post (<=90d), a minimum reach (avg_views>=10000) and sample size (>=10 posts), and a sanity ceiling (<=50%) -- use this, not the raw sort, for a 'best engagement' leaderboard Allowed values: followers_desc, engagement_desc, engagement_qualified_desc, likes_desc, relevance | ||
| page | integer | No | 1 | Page number, defaults to 1 | |
| page_size | integer | No | 20 and maxes at 100 | Page size, defaults to 20 and maxes at 100; page * page_size must be <= 10000 | |
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/datasets/creators/search?q=coffee&country=us&verified=true&has_email=true&include_email=true&include_inactive=true&sort=followers_desc&page=1" \ -H "x-api-key: $CRAWLORA_API_KEY"
Send your scraping API key in the x-api-key header. Use the console API Keys page to rotate or select the active key.
Endpoint usage is metered in credits. The plan prices, included credits, limits, and overage rates below match the active backend billing configuration.
| Plan | Price | Included credits | Daily cap | Rate limit | Overage |
|---|---|---|---|---|---|
| Free | $0/mo | 2,000 | 500 daily credits | 5/min | No overage |
| Starter | $9/mo | 20,000 | 5,000 daily credits | 15/min | $0.75/1,000 overage credits when enabled |
| Growth | $29/mo | 100,000 | 25,000 daily credits | 45/min | $0.45/1,000 overage credits when enabled |
| Pro | $79/mo | 400,000 | No daily cap | 120/min | $0.30/1,000 overage credits |
| Business | $199/mo | 1,200,000 | No daily cap | 300/min | $0.20/1,000 overage credits |
| Enterprise | $499/mo | 5,000,000 | No daily cap | 1,000/min | $0.12/1,000 overage credits |
This endpoint reads stored indexed dataset records. It does not execute a live upstream Google Maps request, browser session, or proxy-routed scraping job.
- The maximum result window is `10000`; `page * page_size` must not exceed `10000`. - Invalid enum values return the standard invalid params envelope. - A not-yet-populated index returns an empty `items` list rather than an error. - Does not trigger live scraping. Example response: ```json { "code": 200, "msg": "OK", "data": { "dataset": "creators", "items": [ { "creator_uid": "tiktok:@bubble", "platform": "tiktok", "sec_uid": "MS4wLjABAAAAxxxxxxxx", "unique_id": "bubble", "nickname": "Bubble Skincare", "bio": "Built with dermatologists since day 1.", "bio_link": "https://hellobubble.com", "niche": "skincare", "country": "us", "verified": true, "follower_count": 4100000, "following_count": 312, "total_likes": 25246297, "video_count": 1840, "first_seen": "2026-06-20T05:00:00Z", "last_crawled": "2026-06-20T05:00:00Z" } ], "page": 1, "page_size": 20, "total": 1, "sort": "followers_desc" } } ```
Crawlora does not silently return invalid dataset search results when filters, pagination, coordinates, or stored record lookups cannot be satisfied.
| Status | Common failure case |
|---|---|
| 400 | Invalid input, missing required parameter, invalid enum, bad coordinate pair, or result window beyond the dataset limit |
| 404 | Requested stored dataset item is not present |
| 429 | Plan or endpoint rate limit exceeded |
| 500 | Internal dataset query or storage error |
When possible, Crawlora returns structured error context so your integration can adjust filters, page size, location inputs, or lookup identifiers.
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 429 | Too Many Requests | #/definitions/app.Response |
| 500 | Internal Server Error | #/definitions/app.Response |
{
"code": 200,
"msg": "OK",
"data": {
"dataset": "creators",
"items": [
{
"creator_uid": "tiktok:@bubble",
"platform": "tiktok",
"sec_uid": "MS4wLjABAAAAxxxxxxxx",
"unique_id": "bubble",
"nickname": "Bubble Skincare",
"bio": "Built with dermatologists since day 1.",
"bio_link": "https://hellobubble.com",
"niche": "skincare",
"country": "us",
"verified": true,
"follower_count": 4100000,
"following_count": 312,
"total_likes": 25246297,
"video_count": 1840,
"first_seen": "2026-06-20T05:00:00Z",
"last_crawled": "2026-06-20T05:00:00Z"
}
],
"page": 1,
"page_size": 20,
"total": 1,
"sort": "followers_desc"
}
}Request schema
No body schema
Response schema
#/definitions/datasets.creatorsSearchResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | 200 | |||
| data | datasets.CreatorsSearchResponse | No | ||||
| data.dataset | string | No | ||||
| data.items | array | No | ||||
| data.items[].avatar_url | string | No | ||||
| data.items[].avg_views | integer | No | top-level mirror of PostStats.AvgViews for sort/filter | |||
| data.items[].bio | string | No | ||||
| data.items[].bio_link | string | No | ||||
| data.items[].brand_affiliations | array | No | ||||
| data.items[].country | string | No | ||||
| data.items[].creator_uid | string | No | ||||
| data.items[].email | string | No | ||||
| data.items[].email_status | string | No | ||||
| data.items[].engagement_rate | number | No | headline = by-view (TikTok standard); see PostStats for both | |||
| data.items[].first_seen | string | No | FirstSeen is the discovery timestamp: set once when the creator is first indexed, and never changed by a later re-crawl. Values recorded before 2026-08-29 are unreliable and should not be used for cohort or tenure analysis. | |||
| data.items[].follower_count | integer | No | ||||
| data.items[].following_count | integer | No | ||||
| data.items[].language | string | No | ||||
| data.items[].last_crawled | string | No | ||||
| data.items[].last_post_at | string | No | top-level mirror of PostStats.LastPostAt for recency filter | |||
| data.items[].niche | string | No | Niche is the DISCOVERY SEED TERM that surfaced this creator (the keyword/hashtag/ explore-category the crawler used), NOT a content classification. It is single-valued and first-write-wins, so a creator found via the "korean skincare" keyword sweep is tagged "skincare" whatever they actually post about. Do not present it as a category; use NicheClassified for that. | |||
| data.items[].niche_classified | string | No | NicheClassified is the content niche DERIVED FROM THE BIO by classifyNiche() in the creatorsdb-enrich worker. Independent of Niche by construction: it is computed for every creator with a bio, including those that already carry a seed term, so the two fields never contaminate each other and "which is this?" is answered by the field name rather than an unbackfillable provenance flag. | |||
| data.items[].nickname | string | No | ||||
| data.items[].platform | string | No | ||||
| data.items[].post_stats | es.PostStatsAgg | No | ||||
| data.items[].post_stats.analyzed_at | string | No | ||||
| data.items[].post_stats.avg_comments | integer | No | ||||
| data.items[].post_stats.avg_likes | integer | No | ||||
| data.items[].post_stats.avg_saves | integer | No | ||||
| data.items[].post_stats.avg_shares | integer | No | ||||
| data.items[].post_stats.avg_video_duration_sec | number | No | ||||
| data.items[].post_stats.avg_views | integer | No | ||||
| data.items[].post_stats.best_post_id | string | No | ||||
| data.items[].post_stats.best_post_views | integer | No | ||||
| data.items[].post_stats.distinct_sounds | integer | No | DistinctSounds is how many different sounds the sampled posts used. TopSounds keeps only the five most-used, so without this a consumer cannot tell a creator who reuses one sound across the sample from one who used a different sound every time — both surface five rows. | |||
| data.items[].post_stats.engagement_rate_by_follower | number | No | ||||
| data.items[].post_stats.engagement_rate_by_view | number | No | ||||
| data.items[].post_stats.first_post_at | string | No | ||||
| data.items[].post_stats.last_post_at | string | No | ||||
| data.items[].post_stats.median_likes | integer | No | ||||
| data.items[].post_stats.median_views | integer | No | ||||
| data.items[].post_stats.original_sound_ratio | number | No | ||||
| data.items[].post_stats.posts_per_week | number | No | ||||
| data.items[].post_stats.sampled_posts | integer | No | ||||
| data.items[].post_stats.top_hashtags | array | No | ||||
| data.items[].post_stats.top_sounds | array | No | ||||
| data.items[].post_stats.top_sounds[].author | string | No | ||||
| data.items[].post_stats.top_sounds[].music_id | string | No | ||||
| data.items[].post_stats.top_sounds[].original | boolean | No | Original marks TikTok-generated original audio. Titles cannot be used for this: TikTok localizes the label (`sonido original`, `оригинальный звук`, …), so a title match silently reclassifies original audio as a named track. | |||
| data.items[].post_stats.top_sounds[].title | string | No | ||||
| data.items[].post_stats.top_sounds[].uses | integer | No | ||||
| data.items[].post_stats.views_to_follower_ratio | number | No | ||||
| data.items[].sec_uid | string | No | ||||
| data.items[].source | string | No | ||||
| data.items[].status | string | No | "" active | "deleted" | "private" — refresh marks these to skip future crawls | |||
| data.items[].total_likes | integer | No | ||||
| data.items[].unique_id | string | No | ||||
| data.items[].verified | boolean | No | ||||
| data.items[].video_count | integer | No | ||||
| data.page | integer | No | ||||
| data.page_size | integer | No | ||||
| data.sort | string | No | ||||
| data.total | integer | No | ||||
| msg | string | No | OK |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/datasets/creators/search?q=coffee&country=us&verified=true&has_email=true&include_email=true&include_inactive=true&sort=followers_desc&page=1" \
-H "x-api-key: $CRAWLORA_API_KEY"Crawlora is designed for responsible structured public web data workflows. Customers are responsible for using Crawlora in compliance with applicable laws, third-party rights, target-platform rules, and Crawlora terms.
Read Crawlora terms