Social media data for research

Collect public posts and comments for a study, with cursors you can resume.

The job

A study needs repeatable collection. Page through a feed with its cursor, keep the raw response, and record when each page was fetched.

Endpoints

EndpointReturnsCost
GET /v1/youtube/searchYouTube search1 credit
GET /v1/youtube/video/commentsYouTube video comments1 credit
GET /v1/tiktok/search/hashtagTikTok videos by hashtag1 credit
GET /v1/bluesky/profile/postsBluesky profile posts1 credit
GET /v1/telegram/channel/postsTelegram public channel posts1 credit

Failed requests and cached repeats cost 0 credits. Send max_age_days to accept a recent cached copy. See credits and caching.

Recipe

  1. Define the query and the date window.
  2. Page with the cursor until has_more is false.
  3. Store the raw response and the fetch time.
Preview
The API is in early access. Calls use api.socialscrape.io and return the shapes in the reference.
Python
import os
import requests

API = "https://api.socialscrape.io"
HEADERS = {"x-api-key": os.environ["SOCIALSCRAPE_API_KEY"]}


def get(path, **params):
    res = requests.get(API + path, headers=HEADERS, params=params, timeout=60)
    res.raise_for_status()
    return res.json()["data"]

# YouTube search
page = get("/v1/youtube/search", query="climate policy", type="video", upload_date="month")
# YouTube video comments
comments = get("/v1/youtube/video/comments", url=page["items"][0]["url"], sort="top")

print(page["has_more"], page["cursor"])
print(len(comments["items"]))
TypeScript
const API = "https://api.socialscrape.io";
const headers = { "x-api-key": process.env.SOCIALSCRAPE_API_KEY! };

async function get(path: string, params: Record<string, string | number | boolean>) {
  const query = new URLSearchParams(Object.entries(params).map(([k, v]) => [k, String(v)]));
  const res = await fetch(`${API}${path}?${query}`, { headers });
  if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
  return (await res.json()).data;
}

// YouTube search
const page = await get("/v1/youtube/search", { query: "climate policy", type: "video", upload_date: "month" });
// YouTube video comments
const comments = await get("/v1/youtube/video/comments", { url: page.items[0].url, sort: "top" });

console.log(page.has_more, page.cursor);
console.log(comments.items.length);

Good to know

A cached response carries cached_at, so you can tell fresh collection from a repeat. Check your ethics board and each platform's terms for your use.

Build on social data early.

Developers and agent builders get the first keys.

Get early access