Two searches show up next to each other: Instagram's rate limit, and TikTok's slider captcha. Both are what happens when a script drives the website. The website expects a person. It slows the session down, or it asks the session to solve a puzzle.
This API is the other path. You do not launch a browser, you do not store the site's cookies, and you do not solve the puzzle. You send HTTPS to api.socialscrape.io and you get JSON for a public object the product already knows how to read. If the platform will not show that object to a logged-out viewer, the endpoint says so. It does not hand the problem back as a captcha.
The routes are in beta. The API is in early access. The key goes in x-api-key. See authentication.
A profile, as HTTP#
A TikTok profile is GET /v1/tiktok/profile with handle. The recorded call:
curl -G "https://api.socialscrape.io/v1/tiktok/profile" \
-H "x-api-key: $SOCIALSCRAPE_API_KEY" \
--data-urlencode "handle=khaby.lame"import os
import requests
params = {
"handle": "khaby.lame",
}
res = requests.get(
"https://api.socialscrape.io/v1/tiktok/profile",
headers={"x-api-key": os.environ["SOCIALSCRAPE_API_KEY"]},
params=params,
)
body = res.json()
if body["ok"]:
print(body["data"])
else:
print(body["error"]["code"], body["error"]["message"])const url = new URL("https://api.socialscrape.io/v1/tiktok/profile");
url.search = new URLSearchParams({
"handle": "khaby.lame"
}).toString();
const res = await fetch(url, {
headers: { "x-api-key": process.env.SOCIALSCRAPE_API_KEY! },
});
const body = await res.json();
if (body.ok) {
console.log(body.data);
} else {
console.error(body.error.code, body.error.message);
}An Instagram profile is GET /v1/instagram/profile with handle. The recorded call uses nasa.
curl -G "https://api.socialscrape.io/v1/instagram/profile" \
-H "x-api-key: $SOCIALSCRAPE_API_KEY" \
--data-urlencode "handle=nasa"import os
import requests
params = {
"handle": "nasa",
}
res = requests.get(
"https://api.socialscrape.io/v1/instagram/profile",
headers={"x-api-key": os.environ["SOCIALSCRAPE_API_KEY"]},
params=params,
)
body = res.json()
if body["ok"]:
print(body["data"])
else:
print(body["error"]["code"], body["error"]["message"])const url = new URL("https://api.socialscrape.io/v1/instagram/profile");
url.search = new URLSearchParams({
"handle": "nasa"
}).toString();
const res = await fetch(url, {
headers: { "x-api-key": process.env.SOCIALSCRAPE_API_KEY! },
});
const body = await res.json();
if (body.ok) {
console.log(body.data);
} else {
console.error(body.error.code, body.error.message);
}Both return a profile: handle, name, bio, avatar_url, verified, is_private, external_url, links and stats (followers, following, posts, likes, views). Nulls are values the platform did not send. Instagram's profile leaves stats.posts null on purpose. The reference says to use GET /v1/instagram/profile/post-count for that number. Do not treat the null as zero posts.
You did not set a user agent, a cookie jar or a puzzle token. The request is the header and the query. That is the whole client.
The limit you still have#
You stop hitting the website's browser checks. You start hitting this API's team limit. It is per team, not per key. Making more keys does not raise it. The rate limits page lists:
- Free credits only: 30 requests a minute.
- Any paid pack: 300.
- Starter monthly plan: 120. Builder: 300. Pro: 600. Scale: 1,200.
- Enterprise: 3,000.
Every response includes x-ratelimit-limit and x-ratelimit-remaining. When you pass the allowance the status is 429, the code is rate_limited, retryable is true, and credits_charged is 0. The retry-after header is the number of seconds to wait. Wait, then send the same request. Refused requests do not count against the allowance. Bursts are allowed. What counts is the average over a short window.
That is a different limit from Instagram's. Calling this API does not tell you Instagram's current threshold, and it does not raise it. Your code should branch on error.code, not on a captcha page you will not receive.
Cache, so you call less#
max_age_days from 0 to 30 asks for a cached copy. A hit costs 0 credits, sets cached true, and sets cached_at to when the data was first fetched. These profile endpoints keep results 30 days. Nothing is served from the cache unless you ask. The cache key is the endpoint plus its parameters. trim and raw do not split the key. A different handle does.
If you poll the same profile every minute, send max_age_days and you will not spend a credit or a rate-limit slot on a fresh fetch each time. A miss still fetches and still counts. See caching.
Failed requests cost 0 credits as well. not_found, invalid_params and unsupported_url are failures. Stop retrying them. upstream_blocked and rate_limited are in the errors list. Read retryable on the one you got.
What stays impossible on purpose#
Logged-out gaps are documented per endpoint, and they are not a puzzle to bypass.
Instagram comments return about 14 comments and has_more false. Replies are not available. include_replies is ignored. TikTok profile videos return about 10 videos and has_more false, with likes null, because the embed page does not have them. LinkedIn company posts stop at the signed-out block, up to 10, and the cursor stays null. A private account stays private.
region on some routes is a country code for results that vary by country. On TikTok search the reference calls it a region hint, not a proxy country. There is no parameter for a residential proxy, a TLS fingerprint or a solved captcha token. Do not add one. The request will reject unknown parameters as invalid_params.
Batching does not dodge the team limit. A batch of up to 100 requests runs on our side and saves round trips. Each item still counts toward the minute allowance.
Cost#
A successful profile is 1 credit. The signup grant is 100 credits, once, with no card, which is 100 successful reads if every one misses the cache and none fail. Packs start at $15 for 5,000 credits. Monthly Starter is $15 for 6,500 credits. Those figures are pricing. Spend order and refunds are in credits.
Next#
Build the client from the quickstart and the errors page. Profile examples: TikTok profile, Instagram profile API, how to scrape an Instagram profile. When the same handle is fetched often, caching matters more than concurrency. The feature note is free cached results.