Threads
Threads User Posts API
Pull a Threads creator's own posts as JSON - text, like / reply / repost counts, publish time, media type, cover image and playable video URL - about 30 to a page, cursor-paginated. Costs 2 credits per page addressed by user_id and 4 addressed by username, and that surcharge repeats on EVERY page, so resolve the handle to an id once and page on the id.
Authorizations
AuthorizationstringheaderrequiredBearer authentication header of the form Bearer <token>, where <token> is your Scavio API key (e.g. Bearer sk_live_your_key).
Body
application/jsonuser_idstringNumeric Threads user id. The cheap path: 2 credits per page. Get one from Threads User Search, from Threads Profile, or from the user block on any post you already hold.
Example: 63269174602
usernamestringThreads handle without the leading @, 1 to 60 characters. Costs 4 credits per page instead of 2, because the upstream handle lookup is dead and the id has to be resolved through people search on every single call. Provide user_id or username; sending neither is rejected. Sending both bills the cheap rate and ignores the handle.
Example: natgeo
cursorstringOpaque pagination cursor. Omit it for the first page, then pass back the next_cursor value from the previous response. Stop when next_cursor is null - do not loop on has_more.
Request
from scavio import ScavioClient
client = ScavioClient(api_key="sk_live_your_key")
# Resolve the handle ONCE (2 credits), then page on the id at 2 credits a page
matches = client.threads.search_users("natgeo")
user_id = next(
u["user_id"] for u in matches["data"]["users"] if u["username"] == "natgeo"
)
cursor = None
while True:
page = client.threads.user_posts(user_id=user_id, cursor=cursor)
for post in page["data"]["posts"]:
print(post["taken_at"], post["like_count"], post["text"])
cursor = page["data"]["next_cursor"]
if not cursor: # null means no further page exists
breakResponse