Social listening here means a narrow job: search posts for a term, store the ids, and run the search again later. It is not a purchased stream of every mention on the internet.
Each platform has its own search route, its own page size and its own filter rules. The key is x-api-key. See authentication.
Keep a row per platform and post id. A later run inserts only ids you do not have. That is the whole dedupe. Do not merge five rankings into one "top post". Each platform ranked its own page.
TikTok videos
GET /v1/tiktok/search/keyword searches videos. query is required. The recorded request also sends date_posted=week.
TikTok ignores sort and date filters in the way the reference spells out. sort other than relevance is refused. date_posted (any, day, week, month, three_months, six_months) drops videos older than the window from each page.
Pages can be short or empty. Keep following has_more. region is TikTok's region hint, not a proxy country.
1curl -G "https://api.socialscrape.dev/v1/tiktok/search/keyword" \2 -H "x-api-key: $SOCIALSCRAPE_API_KEY" \3 --data-urlencode "query=nasa" \4 --data-urlencode "date_posted=week"1import os2import requests34params = {5 "query": "nasa",6 "date_posted": "week",7}8res = requests.get(9 "https://api.socialscrape.dev/v1/tiktok/search/keyword",10 headers={"x-api-key": os.environ["SOCIALSCRAPE_API_KEY"]},11 params=params,12)13body = res.json()1415if body["ok"]:16 print(body["data"])17else:18 print(body["error"]["code"], body["error"]["message"])1const url = new URL("https://api.socialscrape.dev/v1/tiktok/search/keyword");2url.search = new URLSearchParams({3 "query": "nasa",4 "date_posted": "week"5}).toString();6const res = await fetch(url, {7 headers: { "x-api-key": process.env.SOCIALSCRAPE_API_KEY! },8});9const body = await res.json();1011if (body.ok) {12 console.log(body.data);13} else {14 console.error(body.error.code, body.error.message);15}Items are posts: id, url, text, published_at, author, stats (views, likes, comments, shares), hashtags, song. extra can include author_followers, comments_disabled and is_private.
Store id and url. The url is what you pass to GET /v1/tiktok/video/comments if you want the comments on that video.
Each page is 1 credit. Pass cursor back until has_more is false. See pagination.
YouTube
GET /v1/youtube/search- takes
query.typeisvideo,channel,playlist,shortorlive. Shorts and live results are posts of typeshortandlive.upload_dateishour,today,week,monthoryear.duration(short,medium,long) applies to videos, not Shorts. sort- defaults to
relevance.latestandratingare refused withinvalid_params, because YouTube answers them in relevance order. Userelevanceorpopular(view count) and narrow withupload_date.include_extrasadds likes, comment count and description per video.
The recorded request asks for playlists, so the sample items are collections (kind, title, owner, item_count), not videos. For a listening job, set type to video. The same query string works. Playlist rows are the wrong object if you wanted captions and view counts.
1curl -G "https://api.socialscrape.dev/v1/youtube/search" \2 -H "x-api-key: $SOCIALSCRAPE_API_KEY" \3 --data-urlencode "query=lofi hip hop" \4 --data-urlencode "type=playlist"1import os2import requests34params = {5 "query": "lofi hip hop",6 "type": "playlist",7}8res = requests.get(9 "https://api.socialscrape.dev/v1/youtube/search",10 headers={"x-api-key": os.environ["SOCIALSCRAPE_API_KEY"]},11 params=params,12)13body = res.json()1415if body["ok"]:16 print(body["data"])17else:18 print(body["error"]["code"], body["error"]["message"])1const url = new URL("https://api.socialscrape.dev/v1/youtube/search");2url.search = new URLSearchParams({3 "query": "lofi hip hop",4 "type": "playlist"5}).toString();6const res = await fetch(url, {7 headers: { "x-api-key": process.env.SOCIALSCRAPE_API_KEY! },8});9const body = await res.json();1011if (body.ok) {12 console.log(body.data);13} else {14 console.error(body.error.code, body.error.message);15}Page with cursor. One page, one credit.
Instagram reels, Threads, X
GET /v1/instagram/search/reels searches reels for query, from Instagram's Popular search. The reference says that is the same source as search/popular, not Google's index, about 50 to 70 reels over 5 or 6 pages.
date_posted is accepted and not applied. There is no date filter upstream. The recorded query is sourdough.
1curl -G "https://api.socialscrape.dev/v1/instagram/search/reels" \2 -H "x-api-key: $SOCIALSCRAPE_API_KEY" \3 --data-urlencode "query=sourdough"1import os2import requests34params = {5 "query": "sourdough",6}7res = requests.get(8 "https://api.socialscrape.dev/v1/instagram/search/reels",9 headers={"x-api-key": os.environ["SOCIALSCRAPE_API_KEY"]},10 params=params,11)12body = res.json()1314if body["ok"]:15 print(body["data"])16else:17 print(body["error"]["code"], body["error"]["message"])1const url = new URL("https://api.socialscrape.dev/v1/instagram/search/reels");2url.search = new URLSearchParams({3 "query": "sourdough"4}).toString();5const res = await fetch(url, {6 headers: { "x-api-key": process.env.SOCIALSCRAPE_API_KEY! },7});8const body = await res.json();910if (body.ok) {11 console.log(body.data);12} else {13 console.error(body.error.code, body.error.message);14}GET /v1/threads/search- returns one page of about 15 to 20 posts. It does not page.
start_dateandend_datefilter that page only. Threads does not apply them itself. Details are in Threads profiles, posts and search. GET /v1/twitter/search/posts- finds posts through a web search engine, restricted to x.com, then reads them like a tweet. The reference is blunt: this is engine-indexed discovery, not X's own search. Coverage is incomplete, recent posts can be missing, and the order is the engine's. Views, retweet and bookmark counts are missing. Deleted, protected and unreachable posts are left out. Cursor pages 1 to 11. The recorded query is
ai agents. Errors includeupstream_blockedas well asinvalid_paramsandnot_found.
A hit is still a post: text, author, published_at, stats with the gaps above, url. Store the id. Do not describe the list as everything said on X that day.
After the search
Comments are a second call, per video, and another credit. Instagram comment pages stop at about 14 and do not page. That limit is Get Instagram post comments. TikTok and YouTube comment routes are separate and do page.
Check has_more on the route you called. Do not assume they share Instagram's rule.
A monitor watches a list endpoint and posts new items to a signed webhook, so you are not polling. Create one with the list path and that endpoint's params. Management calls are free. The contract is monitors and monitors and webhooks.
Cost and limits
Every successful search page is 1 credit. Five platforms, one page each, is five credits if nothing was cached. max_age_days makes a repeat of the same query free and is the wrong tool if you need posts from the last hour.
Use it when yesterday's page is acceptable. Cache TTL on these routes is 30 days. Failures cost 0.
Signup is 100 credits, once, no card. See pricing and credits.
The honest gaps: TikTok will not sort by latest. YouTube will not sort by latest either. Instagram will not filter reels by date. Threads will not give you page two. X will not give you the firehose.
Write those down next to the term you track, or the report will treat missing as silence.
Packs and plans have no rate limits; free accounts have a lower one. See rate limits.
Next
The product page for this job is the social listening use case. Endpoints: TikTok search, YouTube search, Instagram reel search, Threads search, X post search. Tutorials follow the same slugs under /tutorials/how-to-scrape-..., for example how to scrape TikTok search. References live under the API index.