DataSocial docs: TikTok tables, SQL tips and the MCP
Getting started
DataSocial is a free warehouse of public TikTok data: about 4 billion creators, 600 million sounds and 5.5 billion videos, with day-by-day history for the active ones. Ask a question and get a table and a chart; every answer is a SQL query you can read and change.
Open Search and type what you want to know, like “rising sounds” or “US creators”.
Pick a suggested question and it runs, or press Enter and Ask AI writes the SQL for you to run.
Read the table or switch to Chart. Change a number in the SQL and press Run again.
Free: up to 100 rows and 10 seconds per query, fair use (Terms). Sign in for a key to use it from Claude or Cursor: MCP.
Tables
Everything lives in one database, tiktok. Each table answers a different kind of question. Open one to see example questions you can run, and every column.
Latest state
One row per creator, video or sound, as it is now.
History
How numbers changed: one row per day, never rewritten.
Follow graph
Who follows whom. Looked up one creator at a time.
creators
Latest state
Who is big on TikTok, where they are, what they do, and whether they list a business email.
What it covers: Every TikTok creator we have seen: profile, counts, verification, links, business info for creators we have read in depth, and whether they list a contact email (the address itself is premium and not readable here). tracked = 1 means we read the creator every day. 4.1 billion creators worldwide, discovered through following lists. A creator is tracked while they have 5,000+ followers (1,000+ in the US, Canada, Australia or the UK) and are proven to have posted in the last 30 days (a recent video we know of, or a rising video count). 4.3 million were tracked on 2026-09-28 (after the imported archive proved many more recent posts), and the list grows every day as more creators are proven to post. Tracked creators get a creator_history row every day, and their videos a video_history row every day for 30 days, then weekly to day 90. Business and category fields only for creators we have read in depth (about 1 in 200).
Fastest filters: the table is sorted by country, followers, creator_id, so filters on the first of these are quickest (and cheapest).
1 = tracked: 5,000+ followers (1,000+ in the US, Canada, Australia or the UK) and posted in the last 30 days. A tracked creator gets a creator_history row every day, and their videos a video_history row every day for 30 days, then weekly to day 90. Rechecked daily.
tracked_since
DateTime
when the current tracking began; 1970 if not tracked
is_artist
UInt8
1 = has created sounds (sounds_created > 0) or TikTok labels them an artist
last_seen_at
DateTime
newest read of this creator (UTC)
refreshed_at
DateTime
when this row was built
creators read in depth only (else empty)
Column
Type
What it is
category
LowCardinality(String)
TikTok's business category, e.g. 'Entertainment'; set on few accounts, mostly business ones
account_type
LowCardinality(String)
'personal' | 'creator' | 'business'; '' = not read in depth
company_name
String
business accounts only
contact
Column
Type
What it is
email
String
'[email hidden]' when we have one, '' when not: addresses are never shown; message us to get email data
email_source
LowCardinality(String)
'bio' | 'archive' | '' (none)
has_email
UInt8
1 = we have an email for them (under 1%)
email_domain
LowCardinality(String)
the address's domain: 'gmail.com', 'agency.co', ...
sounds
Latest state
Which songs and original sounds exist, who made them, and how many videos use each one.
Rebuilt every 6 h; video_count as of video_count_date.
What it covers: Every sound seen on a video: title, artist, owner, originality, commercial rights, TikTok matching, Spotify/Apple ids, video count. 603 million sound ids seen on videos. About 1 in 5 has not been read yet: only sound_id is set, title is empty and video_count is 0. video_count is read daily for sounds with more than 3 videos, weekly for the rest.
Fastest filters: the table is sorted by sound_id, so filters on the first of these are quickest (and cheapest).
SELECT title, owner_username, video_count
FROM tiktok.sounds
WHERE is_original = 1
ORDER BY video_count DESC
LIMIT 10
Columns
Column
Type
What it is
sound_id
UInt64
title
String
artist
String
album
String
created_at
DateTime
when the sound was made; 1970 if not read yet
duration_s
UInt16
SECONDS (videos are ms); 0 if not read yet
language
LowCardinality(String)
'English', 'non_vocal', ...; '' on most sounds
owner_creator_id
UInt64
mostly original sounds; 0 = none
owner_username
String
owner_nickname
String
is_original
UInt8
made on TikTok by a creator
is_official
UInt8
is_pgc: a label/distributor upload
is_commercial
UInt8
cleared for business use
is_commercial_strict
UInt8
has_custom_title
UInt8
TikTok's own "the creator gave it a name" signal for originals. The strongest artist-discovery filter measured (median 86 videos vs 1 for other originals, 2026-09-28).
has_vocals
Nullable(UInt8)
NULL = TikTok did not say
has_strong_beat
UInt8
has_lyrics
UInt8
theme_tags
Array(LowCardinality(String))
matched_type
LowCardinality(String)
How TikTok matched the audio: 'not_found' | 'fingerprint' | 'pgc' | 'speed-pitch'; '' if not read yet. For finding UNDISCOVERED artists, a match is a NEGATIVE signal.
matched_song_title
String
matched_song_artist
String
spotify_id
String
dsp platform 3
apple_music_id
String
dsp platform 1
origin_video_id
UInt64
the video an original was lifted from
sim_group_id
UInt64
TikTok's "same audio" cluster; use it to avoid double counting re-uploads
loudness_lufs
Nullable(Float32)
NULL = not measured
cover_uri
String
play_url
String
unsigned mp3, does not expire
video_count
UInt32
videos using it (TikTok's user_count); 0 = not read yet
video_count_date
Date
when that was read; 1970 if never
is_retired
UInt8
never resolves in bulk (3 misses)
first_seen
DateTime
when it entered our store (2026-09-26 at the earliest); not when it was made (created_at)
refreshed_at
DateTime
videos
Latest state
What creators post: captions, hashtags, the sound used, views, likes and ad or shop flags.
Videos posted in the last ~100 days: hourly. Older months: every ~4 h. Stats are as of stats_updated_at: a tracked creator's video is re-read on the video_history schedule, other videos only when we come across them again.
What it covers: Videos with caption, hashtags, sound, ad / branded / shop / AI flags and engagement. 5.5 billion videos posted from 2014 to today. Not every TikTok video: the videos we have read ourselves, plus an archive of earlier reads imported on 2026-09-28 (most rows). Archive-only rows lack a few fields: width, height, downloads and sound_muted are 0, is_ai_generated is NULL, duration_ms is rounded to the second, and generic hashtags such as fyp and foryou are missing. tracked = 1 means the creator is tracked, so from 2026-09-28 the video's first 90 days go into video_history.
Fastest filters: the table is sorted by country, posted_at, video_id, so filters on the first of these are quickest (and cheapest).
WITH recent AS (
SELECT video_id, creator_id, posted_at, views
FROM tiktok.videos
WHERE country = 'US' AND posted_at >= now() - INTERVAL 2 DAY
ORDER BY views DESC
LIMIT 200
),
usual AS (
SELECT creator_id, median(views) AS typical_views
FROM tiktok.videos
WHERE country = 'US' AND posted_at BETWEEN now() - INTERVAL 90 DAY AND now() - INTERVAL 2 DAY
AND creator_id IN (SELECT creator_id FROM recent)
GROUP BY creator_id
HAVING count() >= 5
)
SELECT r.video_id, r.posted_at, r.views, round(u.typical_views) AS typical_views,
round(r.views / u.typical_views, 1) AS times_usual_views
FROM recent AS r
JOIN usual AS u USING (creator_id)
WHERE u.typical_views > 0 AND r.views >= 10 * u.typical_views
ORDER BY times_usual_views DESC
LIMIT 10
What were the most-viewed US videos posted in the last 7 days?
SELECT video_id, posted_at, views, likes, caption
FROM tiktok.videos
WHERE country = 'US' AND posted_at >= now() - INTERVAL 7 DAY
ORDER BY views DESC
LIMIT 10
Which hashtags are used most in this week's US videos?
SELECT arrayJoin(hashtags) AS hashtag, count() AS videos
FROM tiktok.videos
WHERE country = 'US' AND posted_at >= now() - INTERVAL 7 DAY
GROUP BY hashtag
ORDER BY videos DESC
LIMIT 15
Where in the world is a popular sound being used (in the videos we have)?
WITH (
SELECT sound_id FROM tiktok.videos
WHERE posted_at >= now() - INTERVAL 30 DAY AND sound_id != 0
GROUP BY sound_id ORDER BY count() DESC LIMIT 1
) AS top_sound
SELECT country, count() AS videos_30d, round(videos_30d / sum(videos_30d) OVER () * 100, 1) AS share_pct
FROM tiktok.videos
WHERE sound_id = top_sound AND posted_at >= now() - INTERVAL 30 DAY
GROUP BY country
ORDER BY videos_30d DESC
LIMIT 10
Which US creators with 100k+ followers post most often?
WITH posters AS (
SELECT creator_id, count() AS videos_30d
FROM tiktok.videos
WHERE country = 'US' AND posted_at >= now() - INTERVAL 30 DAY
GROUP BY creator_id
)
SELECT c.username, c.followers, round(p.videos_30d / 30 * 7, 1) AS posts_per_week, p.videos_30d
FROM posters AS p
JOIN (
SELECT creator_id, username, followers FROM tiktok.creators
WHERE country = 'US' AND followers >= 100000 AND creator_id IN (SELECT creator_id FROM posters)
) AS c USING (creator_id)
ORDER BY posts_per_week DESC
LIMIT 10
WITH ai AS (
SELECT creator_id, any(country) AS country, count() AS videos_30d, countIf(is_ai_generated = 1) AS ai_videos
FROM tiktok.videos
WHERE posted_at >= now() - INTERVAL 30 DAY
GROUP BY creator_id
HAVING videos_30d >= 5 AND ai_videos > 0
ORDER BY ai_videos / videos_30d DESC, ai_videos DESC
LIMIT 30
)
SELECT c.username, c.followers, ai.videos_30d, ai.ai_videos, round(ai.ai_videos / ai.videos_30d * 100) AS ai_pct
FROM ai
JOIN (
SELECT creator_id, username, followers FROM tiktok.creators
WHERE country IN (SELECT country FROM ai) AND creator_id IN (SELECT creator_id FROM ai)
) AS c USING (creator_id)
ORDER BY ai_pct DESC, ai.ai_videos DESC
LIMIT 10
Columns
Column
Type
What it is
video_id
UInt64
creator_id
UInt64
posted_at
DateTime
country
LowCardinality(String)
'US', 'ID', ...: the region TikTok gives the video
language
LowCardinality(String)
'en', 'es', ...; 'un' = undetermined (about half)
type
LowCardinality(String)
'video' | 'photo'
duration_ms
UInt32
0 on photos; archive-only rows rounded to the second
image_count
UInt8
images in a photo post; 0 on videos and when unknown (most archive-only rows)
width
UInt16
pixels; 0 on archive-only rows and photos
height
UInt16
pixels; 0 on archive-only rows and photos
caption
String
hashtags
Array(String)
lower-case; archive-only rows lack generic tags such as fyp and foryou
hashtag_ids
Array(UInt64)
parallel to hashtags
mentions
Array(UInt64)
creator_ids
on_screen_text
Array(String)
sound_id
UInt64
tiktok.sounds.sound_id; 0 = none
is_ad
UInt8
paid promotion (Spark Ads)
branded_content
LowCardinality(String)
'' | 'paid_partnership' | 'shop_affiliate'
product_id
UInt64
0 = none seen
is_shop_video
UInt8
seller_id
UInt64
is_ai_generated
Nullable(UInt8)
NULL = TikTok did not say (all archive-only rows)
not_recommended
Nullable(UInt8)
TikTok's own flag: 1 = kept out of recommendations; NULL = TikTok did not say
sound_muted
UInt8
audio removed for copyright; 0 on archive-only rows
What it covers: Daily followers, following, videos and likes: totals on that day (growth = the change between two days, divided by the earlier day). Every tracked creator, every day, from the day tracking starts (see creators.tracked; 96% of them had a row on 2026-09-27); also other large creators we count daily to find out whether they still post (4.2 million rows a day in all). Full days from 2026-09-27 (2026-09-26 holds 19 rows); no earlier backfill exists.
Fastest filters: the table is sorted by creator_id, date, so filters on the first of these are quickest (and cheapest).
Questions it answers
What were tracked creators' follower counts on the latest day?
SELECT creator_id, date, followers, videos, likes
FROM tiktok.creator_history
WHERE date = (SELECT max(date) FROM tiktok.creator_history)
ORDER BY followers DESC
LIMIT 10
Columns
Column
Type
What it is
creator_id
UInt64
date
Date
followers
UInt32
following
UInt32
videos
UInt32
likes
UInt64
observed_at
DateTime
When the numbers were read. Growth per day = change / (observed_at gap), not change / 1, reads within a "day" can be many hours apart.
video_history
History
How a tracked creator's video gains views and likes, day by day for its first 30 days, then week by week to day 90.
What it covers: Views, likes, comments, shares, saves over a video's first 90 days: totals at that day's read (gained = the change between two days). Videos of tracked creators: a row every day from day 1 to day 29 after posting, then weekly (days 35, 42, ... 84). Each read is at the hour of day the video was posted, so rows are 24 h apart; observed_at is the exact read time. Full days from 2026-09-27 (2026-09-26 holds 190 rows). 2026-09-27 covers only the 0.6 million videos our own crawl had found, and 2026-09-28 is partial (the imported archive arrived that day). From 2026-09-29 every due video gets its row unless it was deleted or made private (about 3.5% of them).
Fastest filters: the table is sorted by video_id, date, so filters on the first of these are quickest (and cheapest).
WITH (
SELECT video_id FROM tiktok.video_history
GROUP BY video_id HAVING count() >= 2
ORDER BY max(views) DESC LIMIT 1
) AS top_video
SELECT date, views, likes
FROM tiktok.video_history
WHERE video_id = top_video
ORDER BY date
Columns
Column
Type
What it is
video_id
UInt64
date
Date
views
UInt64
likes
UInt64
comments
UInt64
shares
UInt64
saves
UInt64
observed_at
DateTime
when it was read
sound_history
History
How many videos used a sound on each day, since February 2026 (with a gap from mid-May to September): which sounds are rising or fading.
What it covers: Each sound's total video count on each day (a running total: new videos = the change between two days, never a sum). Daily for sounds with > 3 videos, weekly for the rest, from our own reads since 2026-09-27: every sound we know (about 480 million) was read on 2026-09-27; from 2026-10-04 the weekly reads are spread over the week, so a day holds about 100 million sounds (about 40 million before that). Before that, history imported from an earlier system that followed 0.8 to 1.6 million sounds a day: one day on 2026-01-16, then 2026-02-07 to 2026-05-14 (a few days missing, only 4 in May), then 2026-09-02 to 2026-09-26. No data from 2026-05-15 to 2026-09-01.
Fastest filters: the table is sorted by date, sound_id, so filters on the first of these are quickest (and cheapest).
Questions it answers
Which sounds added the most videos this week, with their 30-day history?
WITH (SELECT max(date) FROM tiktok.sound_history) AS d0,
(
SELECT groupArray(sound_id) FROM (
SELECT sound_id, toInt64(n.video_count) - w.video_count AS added_7d
FROM (SELECT sound_id, video_count FROM tiktok.sound_history WHERE date = d0 - 7) AS w
JOIN (SELECT sound_id, video_count FROM tiktok.sound_history WHERE date = d0 AND video_count >= 100000) AS n
USING (sound_id)
ORDER BY added_7d DESC
LIMIT 30
)
) AS rising
SELECT s.title, s.artist, h.videos, h.added_7d, h.history
FROM (
SELECT sound_id,
anyIf(video_count, date = d0) AS videos,
toInt64(videos) - anyIf(video_count, date = d0 - 7) AS added_7d,
arraySort(groupArray((date, video_count))) AS history
FROM tiktok.sound_history
WHERE sound_id IN (SELECT arrayJoin(rising)) AND date >= d0 - 30
GROUP BY sound_id
) AS h
JOIN (SELECT sound_id, title, artist FROM tiktok.sounds WHERE sound_id IN (SELECT arrayJoin(rising)) AND title != '') AS s USING (sound_id)
ORDER BY h.added_7d DESC
LIMIT 10
WITH (SELECT max(date) FROM tiktok.sound_history) AS d0,
(
SELECT groupArray(sound_id) FROM (
SELECT sound_id, (toInt64(n.video_count) - w.video_count) / w.video_count AS growth
FROM (SELECT sound_id, video_count FROM tiktok.sound_history WHERE date = d0 AND video_count >= 10000) AS n
JOIN (SELECT sound_id, video_count FROM tiktok.sound_history WHERE date = d0 - 7 AND video_count >= 10000) AS w
USING (sound_id)
ORDER BY growth DESC
LIMIT 30
)
) AS rising
SELECT s.title, s.artist, h.videos_now, h.added_7d, round(h.added_7d / h.videos_week_ago * 100, 1) AS growth_pct_7d
FROM (
SELECT sound_id,
anyIf(video_count, date = d0) AS videos_now,
anyIf(video_count, date = d0 - 7) AS videos_week_ago,
toInt64(videos_now) - videos_week_ago AS added_7d
FROM tiktok.sound_history
WHERE sound_id IN (SELECT arrayJoin(rising)) AND date IN (d0, d0 - 7)
GROUP BY sound_id
) AS h
JOIN (SELECT sound_id, title, artist FROM tiktok.sounds WHERE sound_id IN (SELECT arrayJoin(rising)) AND title != '') AS s USING (sound_id)
ORDER BY growth_pct_7d DESC
LIMIT 10
How many videos did today's most-used sound have, day by day?
WITH (
SELECT sound_id FROM tiktok.sound_history
WHERE date = (SELECT max(date) FROM tiktok.sound_history)
ORDER BY video_count DESC LIMIT 1
) AS top_sound
SELECT date, video_count
FROM tiktok.sound_history
WHERE sound_id = top_sound
ORDER BY date
Which mid-size sounds (10k to 100k videos) are speeding up: more new videos this week than the week before?
WITH (SELECT max(date) FROM tiktok.sound_history) AS d0,
(
SELECT groupArray(sound_id) FROM (
SELECT sound_id,
toInt64(any(n.video_count)) - anyIf(o.video_count, o.date = d0 - 7) AS added_this_week,
toInt64(anyIf(o.video_count, o.date = d0 - 7)) - anyIf(o.video_count, o.date = d0 - 14) AS added_week_before
FROM (SELECT sound_id, date, video_count FROM tiktok.sound_history WHERE date IN (d0 - 7, d0 - 14)) AS o
JOIN (SELECT sound_id, video_count FROM tiktok.sound_history WHERE date = d0 AND video_count BETWEEN 10000 AND 100000) AS n
USING (sound_id)
GROUP BY sound_id
HAVING countIf(o.date = d0 - 7) > 0 AND countIf(o.date = d0 - 14) > 0 AND added_week_before > 0
ORDER BY added_this_week - added_week_before DESC
LIMIT 30
)
) AS picked
SELECT s.title, s.artist, h.videos_now, h.added_this_week, h.added_week_before
FROM (
SELECT sound_id,
anyIf(video_count, date = d0) AS videos_now,
toInt64(videos_now) - anyIf(video_count, date = d0 - 7) AS added_this_week,
toInt64(anyIf(video_count, date = d0 - 7)) - anyIf(video_count, date = d0 - 14) AS added_week_before
FROM tiktok.sound_history
WHERE sound_id IN (SELECT arrayJoin(picked)) AND date IN (d0, d0 - 7, d0 - 14)
GROUP BY sound_id
) AS h
JOIN (SELECT sound_id, title, artist FROM tiktok.sounds WHERE sound_id IN (SELECT arrayJoin(picked)) AND title != '') AS s USING (sound_id)
ORDER BY h.added_this_week - h.added_week_before DESC
LIMIT 10
Columns
Column
Type
What it is
sound_id
UInt64
date
Date
video_count
UInt32
observed_at
DateTime
follows
Follow graph
Who a creator follows: every account on their following list, with its handle and follower count. One creator per call.
Not refreshed since the crawl: following lists are not re-read yet. A lookup reads the source directly, so it is never staler than the crawl.
What it covers: Who one creator follows: every account on their following list, with its handle and follower count. Call it with a creator id: SELECT * FROM tiktok.follows(creator_id = 6596805238354558982). Find the id with SELECT creator_id FROM tiktok.creators WHERE username = 'kimberly.loaiza'. 113.7 billion follow edges from the following lists of 593 million creators, read 2026-09-06 to 2026-09-23. Many of the oldest, biggest accounts (short ids, such as charlidamelio) were not crawled and return no rows. Who follows a creator is not offered: it would read the whole graph.
How to call it:SELECT * FROM tiktok.follows(creator_id = …), with a creator id. It is a lookup, not a table: there is no way to read it without one. See the map of shared audiences.
Questions it answers
Who does Kimberly Loaiza follow, biggest accounts first?
SELECT follows_username, follows_nickname, follows_followers, position
FROM tiktok.follows(creator_id = 6596805238354558982)
ORDER BY follows_followers DESC
LIMIT 20
SELECT position, follows_username, follows_nickname, follows_followers
FROM tiktok.follows(creator_id = 6531081683746165760)
ORDER BY position
LIMIT 20
Columns
Column
Type
What it is
creator_id
UInt64
the creator whose following list this is (the parameter)
follows_id
UInt64
a creator they follow (tiktok.creators.creator_id)
follows_username
String
that creator's handle when their profile was last read, empty if never read
follows_nickname
String
that creator's display name, emails replaced (decision 109; pattern: build/creators.sql)
follows_followers
UInt32
that creator's follower count when their profile was last read
position
UInt16
place in the following list as TikTok returned it, 0 = the most recent follow
seen_at
DateTime
when this follow was last read (UTC)
SQL tips
The few things worth knowing to change a query: names, fast filters, dates, ids and the metrics.
Queries are ClickHouse SQL. If you have written any SQL, you already know most of it.
The basics
Every table is in the tiktok database: write tiktok.creators, tiktok.sounds and so on.
End with a LIMIT. Results stop at 100 rows per query, for everyone: aggregate or filter to get the rows you want.
Tables are already clean: one row per thing, no duplicates. You never need FINAL or DISTINCT to fix them.
SELECT username, followers
FROM tiktok.creators
WHERE country = 'GB'
ORDER BY followers DESC
LIMIT 20
Fast, cheap filters
Each table is stored sorted by a few columns. A filter on the first of them skips most of the table, so it is faster and cheaper. Each table's page lists them under “Fastest filters”. The big ones:
Table
Sorted by
So filter on
creators
country, followers
country, then followers
videos
country, posted_at
country, then a date range
sounds
sound_id
a list of sound ids
sound_history
date, sound_id
one day (or a few), then sound ids
For example, the biggest US creators read about 60 MB, while the same question with no country reads every creator's followers.
Dates, ids and units
Ids (creators, videos, sounds) are 64-bit numbers, too big for JavaScript. The API sends them as strings; keep them as text in spreadsheets.
Recent rows: WHERE posted_at >= now() - INTERVAL 7 DAY. A day: toDate(posted_at).
Video length is in milliseconds (videos.duration_ms); sound length is in seconds (sounds.duration_s).
Flags are 0 or 1, e.g. is_verified = 1.
Handy functions
You want
Write
How many
count()
How many that match
countIf(followers >= 1000000)
One row per hashtag of a video
arrayJoin(hashtags)
The value on the latest date
argMax(video_count, date)
The newest date in a table
(SELECT max(date) FROM tiktok.sound_history)
History in one cell: groupArray
groupArray turns many rows into one array, so each sound (or creator) gets one row with its whole history. The results table draws an array of numbers as a mini chart: green if the last value is above the first, red if below. Add the date as a pair, groupArray((date, video_count)), and hovering the chart shows the dates too.
SELECT sound_id, groupArray(video_count) AS history
FROM (
SELECT sound_id, date, video_count
FROM tiktok.sound_history
WHERE sound_id IN (7171140178143266818, 7673034501618567944)
AND date >= today() - 30
ORDER BY date
)
GROUP BY sound_id
Sort inside the subquery (ORDER BY date) so the array runs oldest to newest. For daily change instead of totals, wrap it: arrayDifference(groupArray(video_count)).
How metrics are defined
Growth % = change ÷ the previous value, never the current one. Put a floor on the previous value (e.g. 10,000 videos) so tiny sounds don't top the list.
Compare two days by reading both: WHERE date IN (d0, d0 - 7), then anyIf(video_count, date = d0 - 7) for the old value, and keep only rows that have both days (HAVING countIf(date = d0 - 7) > 0). The rising-sounds questions on the sound_history page show the whole query.
A missing day is NULL, never zero, and never filled in.
Country spread of a sound, counted from videos, is an estimate from the videos we hold, which lean towards the US.
What isn't allowed
Only reading: no INSERT, CREATE or anything that changes data.
Only the tiktok database, and no SET, SETTINGS or FORMAT: results always come back as a table (JSON over the API).
Email addresses are hidden: creators.email reads [email hidden] when we have one, and addresses in bios and captions are replaced the same way. has_email and email_domain say who has one. The 31M creator emails are sold privately: message me.
MCP
Query DataSocial from Claude, Cursor or your own code: an MCP server, or one HTTP call, with your key.
Everything Search does, from your own tools. 100 rows per request. Base URL: https://api.datasocial.ai
Get a key
Sign in and open MCP: your key is already there, inside commands ready to copy. It looks like ds_live_…; one per account, and Reset key there swaps it for a new one. Send it as a bearer token. Every query answers up to 100 rows; there is no daily cap.
Without a key the SQL endpoint still answers, with the same limits per address.
Use it from Claude or Cursor (MCP)
The MCP server lets an AI assistant query the warehouse itself. It has three tools: list_tables, describe_table and run_sql (100 rows per call). Claude Code:
Then ask, for example, “Which sounds grew fastest in the US this week?”. The MCP tab has this with your key filled in, and the config for Claude Desktop and Cursor too. The server speaks Streamable HTTP at POST /mcp, without sessions.
Run a query over HTTP
curl https://api.datasocial.ai/v1/data/sql \
-H "Authorization: Bearer $DATASOCIAL_KEY" \
-H 'content-type: application/json' \
-d '{"sql": "SELECT username, followers FROM tiktok.creators WHERE country = '\''US'\'' ORDER BY followers DESC LIMIT 3"}'