Get an API key
Every request is authenticated with an API key in the
x-api-keyheader. To try SocialTap right now, use this public test key:Public test keyGet your own key and 100 free credits →st_test_docs_mZkmkl5JiSWvVgL4v3DLolbtSsjxXm11It works right now, with no signup: every endpoint answers from recorded responses, free. It can't reach an account or spend credits. For live data, use your own key.
Keep keys out of source control, for example in an environment variable:
Shell export SOCIALTAP_API_KEY="st_test_docs_mZkmkl5JiSWvVgL4v3DLolbtSsjxXm11"Make a request
Endpoints are plain HTTPS
GETrequests with query parameters. This calls the TikTok Profile API with its documented example input:cURL curl -G 'https://staging-fly.socialtap.dev/v1/tiktok/profile' \ --data-urlencode 'handle=https://www.tiktok.com/@nasa' \ -H "x-api-key: $SOCIALTAP_API_KEY"Node.js const params = new URLSearchParams({ handle: "https://www.tiktok.com/@nasa", }); const res = await fetch(`https://staging-fly.socialtap.dev/v1/tiktok/profile?${params}`, { headers: { "x-api-key": process.env.SOCIALTAP_API_KEY ?? "" }, }); const body = await res.json(); if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`); const { data, meta } = body; console.log(data, meta.credits_charged);Python import os import requests res = requests.get( "https://staging-fly.socialtap.dev/v1/tiktok/profile", params={"handle": "https://www.tiktok.com/@nasa"}, headers={"x-api-key": os.environ["SOCIALTAP_API_KEY"]}, ) body = res.json() if not res.ok: raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}") data, meta = body["data"], body["meta"] print(data, meta["credits_charged"])Go package main import ( "encoding/json" "fmt" "log" "net/http" "net/url" "os" ) func main() { q := url.Values{} q.Set("handle", "https://www.tiktok.com/@nasa") req, err := http.NewRequest("GET", "https://staging-fly.socialtap.dev/v1/tiktok/profile?"+q.Encode(), nil) if err != nil { log.Fatal(err) } req.Header.Set("x-api-key", os.Getenv("SOCIALTAP_API_KEY")) res, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer res.Body.Close() var body struct { Data json.RawMessage `json:"data"` Meta map[string]any `json:"meta"` Error *struct { Code string `json:"code"` Message string `json:"message"` } `json:"error"` } if err := json.NewDecoder(res.Body).Decode(&body); err != nil { log.Fatal(err) } if body.Error != nil { log.Fatalf("%s: %s", body.Error.Code, body.Error.Message) } fmt.Println(string(body.Data), body.Meta["credits_charged"]) }PHP <?php $query = http_build_query([ 'handle' => 'https://www.tiktok.com/@nasa', ]); $ch = curl_init('https://staging-fly.socialtap.dev/v1/tiktok/profile?' . $query); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['x-api-key: ' . getenv('SOCIALTAP_API_KEY')], ]); $body = json_decode(curl_exec($ch), true); if (curl_getinfo($ch, CURLINFO_RESPONSE_CODE) >= 400) { throw new RuntimeException($body['error']['code'] . ': ' . $body['error']['message']); } print_r($body['data']); echo $body['meta']['credits_charged'], PHP_EOL;Ruby require "json" require "net/http" uri = URI("https://staging-fly.socialtap.dev/v1/tiktok/profile") uri.query = URI.encode_www_form('handle' => 'https://www.tiktok.com/@nasa') req = Net::HTTP::Get.new(uri) req["x-api-key"] = ENV.fetch("SOCIALTAP_API_KEY") res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(req) } body = JSON.parse(res.body) raise "#{body["error"]["code"]}: #{body["error"]["message"]}" unless res.is_a?(Net::HTTPSuccess) pp body["data"] puts body["meta"]["credits_charged"]Java import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; public class Main { public static void main(String[] args) throws Exception { String query = "handle=" + encode("https://www.tiktok.com/@nasa"); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://staging-fly.socialtap.dev/v1/tiktok/profile?" + query)) .header("x-api-key", System.getenv("SOCIALTAP_API_KEY")) .GET() .build(); HttpResponse<String> response = HttpClient.newHttpClient() .send(request, HttpResponse.BodyHandlers.ofString()); // An error is {"error": {"code", "message", ...}}; success is {data, meta}, meta.credits_charged its price. if (response.statusCode() >= 400) throw new RuntimeException(response.body()); System.out.println(response.body()); } static String encode(String value) { return URLEncoder.encode(value, StandardCharsets.UTF_8); } }.NET using System.Text.Json; using var http = new HttpClient(); http.DefaultRequestHeaders.Add("x-api-key", Environment.GetEnvironmentVariable("SOCIALTAP_API_KEY")); var query = string.Join("&", "handle=" + Uri.EscapeDataString("https://www.tiktok.com/@nasa")); var res = await http.GetAsync("https://staging-fly.socialtap.dev/v1/tiktok/profile?" + query); using var body = JsonDocument.Parse(await res.Content.ReadAsStringAsync()); if (!res.IsSuccessStatusCode) { var error = body.RootElement.GetProperty("error"); throw new Exception($"{error.GetProperty("code")}: {error.GetProperty("message")}"); } Console.WriteLine(body.RootElement.GetProperty("data")); Console.WriteLine(body.RootElement.GetProperty("meta").GetProperty("credits_charged"));Rust // Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }, serde_json = "1" use std::env; fn main() -> Result<(), Box<dyn std::error::Error>> { let res = reqwest::blocking::Client::new() .get("https://staging-fly.socialtap.dev/v1/tiktok/profile") .query(&[("handle", "https://www.tiktok.com/@nasa")]) .header("x-api-key", env::var("SOCIALTAP_API_KEY")?) .send()?; let ok = res.status().is_success(); let body: serde_json::Value = res.json()?; if !ok { return Err(format!("{}: {}", body["error"]["code"], body["error"]["message"]).into()); } println!("{} {}", body["data"], body["meta"]["credits_charged"]); Ok(()) }Read the response
A successful response is a JSON object with two keys:
data, the item in its resource's shared schema, andmeta, which describes how the request was served. List endpoints add a third key with what you need to fetch the next page.200 OK { "data": { "approximate_fields": [], "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/e5143212a59c09a008bf50f487d54d1f~tplv-tiktokx-cropcenter:1080:1080.jpeg?dr=9640&refresh_token=9341391e&x-expires=4070908800&x-signature=SCRUBBED&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=81f88b70&idc=useast5", "banner_url": null, "bio": "Making the seemingly impossible, possible.✨", "category": null, "country_code": null, "created_at": "2026-07-20T15:55:49Z", "display_name": "NASA", "external_links": [ { "title": null, "url": "https://science.nasa.gov/feature/artemis-ii-preliminary-lunar-science-report" } ], "id": "7664638705177150477", "is_private": false, "is_verified": true, "location": null, "metrics": { "follower_count": 2140425, "following_count": 23, "post_count": 60, "total_like_count": 11385816, "total_view_count": null }, "platform": "tiktok", "platform_specific": {}, "type": "organization", "unknown_fields": [], "url": "https://www.tiktok.com/@nasa", "username": "nasa" }, "meta": { "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f", "platform": "tiktok", "source": "page", "is_cached": false, "credits_charged": 1, "latency_ms": 0, "fetched_at": "2026-10-25T12:00:00Z", "input": { "kind": "profile", "id": "7664638705177150477", "url": "https://www.tiktok.com/@nasa" }, "credits_remaining": 9999, "client_request_id": null, "warnings": [], "mode": "live" } }(Omitted: another section of this file has it.)
Field Type Description meta.request_idstringUnique request ID; include it when contacting support. meta.platformstringPlatform ID of the endpoint (youtube, tiktok, …). meta.sourcestringWhich upstream strategy produced the data. meta.is_cachedbooleanTrue when served from the cache (free); see max_age. meta.credits_chargedintegerCredits charged for this request (0 for errors and cache hits). meta.latency_msintegerTime SocialTap spent on the request, in milliseconds. meta.fetched_atstring(date-time)When the data was fetched from the platform, RFC 3339 UTC (older than the request for cache hits). meta.inputobjectornullWhat the request's url or handle resolved to: kind, platform ID and canonical URL, so you can confirm what was fetched; null for searches. meta.input.kindstringWhat the input points to (profile, video, post, …). New values may be added; treat unknown values as other. meta.input.idstringornullPlatform-native ID of the item; null when it is only known after the fetch and the request failed. meta.input.urlstringornullCanonical URL of the item; null when unknown. meta.credits_remainingintegerornullAccount balance after this request (the x-credits-remaining header); for a busy account an estimate that may not yet subtract concurrent requests (about a second of usage), never below the real balance; null when SocialTap could not read it. meta.client_request_idstringornullYour x-client-request-id, echoed; null when you sent none. meta.warningsobject[]Things to act on that did not fail the request: a deprecated endpoint, partial data. [] when none. meta.warnings[].codestringMachine-readable warning code (see the warnings list). New codes may be added. meta.warnings[].messagestringWhat to do about it. meta.warnings[].doc_urlstringWhere to read more (the changelog entry, the endpoint's docs). meta.warnings[].fieldsstring[]partial_data: the output fields (catalog paths such as metrics.view_count) that are null or [] because part of the data could not be fetched; absent for other codes. meta.modestringornulllive, or test for a test key's answer: a recorded response (fixture), free and deterministic; null when SocialTap could not tell. New values may be added.
One oflive,test
Errors
A failed request returns a non-2xx status and an error object with a stable code:
{
"error": {
"code": "invalid_input",
"message": "unknown parameter \"username\"; did you mean \"handle\"? This endpoint accepts: handle, max_age, fields.",
"request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
"status": 400,
"retryable": false,
"param": "username",
"remediation": "Fix the parameter named in param (the message says how); for a link of the wrong kind, call the endpoint the message names.",
"doc_url": "https://staging-fly.socialtap.dev/docs/errors/#invalid_input",
"details": {
"accepted_params": [
"handle",
"max_age",
"fields"
],
"suggestion": "handle"
},
"charged": false
}
}(Omitted: another section of this file has it.)
Branch on code, never on message. The error reference lists every code and whether it is safe to
retry.
Next steps
All endpoints
- Facebook Post API
GET /v1/facebook/post - Facebook Ad Library Search API
GET /v1/facebook/search_ads - Facebook Video Transcript API
GET /v1/facebook/transcript
- Instagram Post API
GET /v1/instagram/post - Instagram Posts API
GET /v1/instagram/posts - Instagram Profile API
GET /v1/instagram/profile - Instagram Reels Transcript API
GET /v1/instagram/transcript
Rumble
- Rumble Comments API
GET /v1/rumble/comments - Rumble Video API
GET /v1/rumble/post - Rumble Channel Videos API
GET /v1/rumble/posts - Rumble Channel API
GET /v1/rumble/profile - Rumble Search API
GET /v1/rumble/search_posts - Rumble Transcript API
GET /v1/rumble/transcript
Threads
- Threads Profile API
GET /v1/threads/profile
TikTok
- TikTok Comments API
GET /v1/tiktok/comments - TikTok Post API
GET /v1/tiktok/post - TikTok Posts API
GET /v1/tiktok/posts - TikTok Profile API
GET /v1/tiktok/profile - TikTok Transcript API
GET /v1/tiktok/transcript
YouTube
- YouTube Comments API
GET /v1/youtube/comments - YouTube Video API
GET /v1/youtube/post - YouTube Channel Videos API
GET /v1/youtube/posts - YouTube Channel API
GET /v1/youtube/profile - YouTube Transcript API
GET /v1/youtube/transcript