twitterapi-io logo

twitterapi-io

twitterapi io

kaitoinfra/twitterapi-io452installs259stars

SKILL.md

Full skill instructions

twitterapi.io

Official skill maintained by the twitterapi.io team. Paths, parameters, and body fields in this skill are verified against the live backend.

When to use this skill

Trigger when the user wants any of:

  • Fetch tweets, user profiles, followers/following, trends, replies, quote-tweets, retweeters, articles
  • Advanced tweet search (X operators, date ranges, engagement filters)
  • Monitor users or filter rules in near real time
  • Post / delete / like / retweet / bookmark / quote-tweet / reply / follow / DM / schedule tweets
  • Update profile / avatar / banner, upload media
  • Create/join/leave communities, manage lists, report content
  • Anything involving twitterapi.io, api.twitterapi.io, x-api-key, login_cookies, or the X API without OAuth

Core facts

Base URLhttps://api.twitterapi.io
Prefix/twitter/... most endpoints; /oapi/x_user_stream/... and /oapi/tweet_filter/... for real-time monitoring/webhooks; /oapi/my/info for balance
Auth headerx-api-key: YOUR_KEY
Dashboardhttps://twitterapi.io/dashboard
Docshttps://docs.twitterapi.io
Rate limit~200 req/s per client
Pricing~$0.15/1k tweets, ~$0.18/1k profiles, $0.00015 minimum

⚠️ Two rules that catch people

Rule 1 — Parameter naming is per-endpoint

No universal snake_case or camelCase rule. Examples (all correct):

  • /twitter/user/followers?userName= (camel)
  • /twitter/user/verifiedFollowers?user_id= (snake)
  • /twitter/user/articles?username= (all-lowercase)
  • /twitter/tweets?tweet_ids= (snake) but /twitter/tweet/replies?tweetId= (camel)
  • /twitter/list/tweets_timeline?listId= (camel) but /twitter/list/members?list_id= (snake)

Copy the exact parameter name from references/endpoints.md. Don't normalize.

Rule 2 — Writes need three things in body, not two

Every write endpoint requires:

  1. login_cookies (plural, not login_cookie) — base64-encoded JSON from /twitter/user_login_v2
  2. proxy (HTTP/SOCKS proxy URL — configure in dashboard)
  3. Action-specific fields, almost always snake_case (tweet_id, user_id)

Plus key field-name traps:

  • create_tweet_v2 text field is tweet_text (not text); reply field is reply_to_tweet_id (not in_reply_to_tweet_id)
  • update_profile_v2 uses description (not bio)
  • bookmarks_v2 uses count (not pageSize)
  • send_dm_to_user: user_id + text; optional media_id (singular)
  • Monitoring add uses x_user_name; remove uses id_for_user (different fields per endpoint!)

See references/write-operations.md for full body shapes.

Rule 3 — Response shape varies per endpoint

  • data-wrapped: user/info, user_about, last_tweets, tweet_timeline, trends, check_follow_relationshipr["data"]["..."]
  • Flat with envelope: followers, followings, replies, mentions, community/tweetsr["followers"], r["tweets"], etc.
  • Flat without envelope: advanced_search, thread_context, user/search, get_tweets_from_all_community → just {tweets[], has_next_page, next_cursor}
  • Named top-level field: community/infor["community_info"]; batch_info_by_idsr["users"]
  • oapi/my/info{recharge_credits, total_bonus_credits} (no status wrapper)

Prefer defensive access: r.get("tweets", r.get("data", {}).get("tweets", [])).

Security

Never hardcode the API key. Read from env TWITTERAPI_IO_KEY. If missing, ask the user.

Minimal working example

curl -s "https://api.twitterapi.io/twitter/user/info?userName=elonmusk" \
  -H "x-api-key: $TWITTERAPI_IO_KEY"
import os, requests

BASE = "https://api.twitterapi.io"
HEADERS = {"x-api-key": os.environ["TWITTERAPI_IO_KEY"]}

r = requests.get(f"{BASE}/twitter/user/info",
                 headers=HEADERS,
                 params={"userName": "elonmusk"},
                 timeout=30)
r.raise_for_status()
d = r.json()["data"]
print(f"{d['userName']} — {d['followers']:,} followers")

Endpoint quick reference

Reads (API key only). Exact param names — copy as shown.

CapabilityMethodPath & key param
User by screen nameGET/twitter/user/info?userName=
Extended bioGET/twitter/user_about?userName=
Batch users by IDsGET/twitter/user/batch_info_by_ids?userIds=
Search usersGET/twitter/user/search?query= (not keyword)
Recent tweetsGET/twitter/user/last_tweets?userName= (or userId=)
Timeline by IDGET/twitter/user/tweet_timeline?userId=
User's articlesGET/twitter/user/articles?username= (all-lowercase)
Mentions of userGET/twitter/user/mentions?userName=
FollowersGET/twitter/user/followers?userName=&pageSize=200
Verified followersGET/twitter/user/verifiedFollowers?user_id= (snake)
FollowingsGET/twitter/user/followings?userName=
Check followGET/twitter/user/check_follow_relationship?source_user_name=&target_user_name=
Tweets by IDsGET/twitter/tweets?tweet_ids= (snake)
Tweet repliesGET/twitter/tweet/replies?tweetId=
Replies (sortable)GET/twitter/tweet/replies/v2?tweetId=&queryType=Latest
Quote tweetsGET/twitter/tweet/quotes?tweetId=
RetweetersGET/twitter/tweet/retweeters?tweetId=
Thread contextGET/twitter/tweet/thread_context?tweetId=
Article contentGET/twitter/article?tweet_id= (snake)
Advanced searchGET/twitter/tweet/advanced_search?query=
Bulk advanced searchPOST/twitter/tweet/bulk_advanced_search body {queries:[{query,queryType?,cursor?}]}
TrendsGET/twitter/trends?woeid=1&count=30
Space detailGET/twitter/spaces/detail?space_id= (snake)
List tweets (with filters)GET/twitter/list/tweets?listId=
List tweets_timelineGET/twitter/list/tweets_timeline?listId=
List members / followersGET/twitter/list/{members,followers}?list_id= (snake)
Community infoGET/twitter/community/info?community_id=
Community tweets/members/modsGET/twitter/community/{tweets,members,moderators}?community_id=
All-community firehoseGET/twitter/community/get_tweets_from_all_community?query= (required!)
Account balanceGET/oapi/my/info

Real-time monitoring (/oapi/x_user_stream/*). Field names differ per endpoint!

CapabilityMethodPath & body
Add monitorPOST/oapi/x_user_stream/add_user_to_monitor_tweet body {x_user_name}not user_id
List monitorsGET/oapi/x_user_stream/get_user_to_monitor_tweet (+ query_type 0/1/2)
Remove monitorPOST/oapi/x_user_stream/remove_user_to_monitor_tweet body {id_for_user}different field from add

Webhook filter rules (/oapi/tweet_filter/*):

CapabilityMethodPath & body
Add rulePOST/oapi/tweet_filter/add_rule body {tag, value, interval_seconds?=60} (range 0.05–86400)
List rulesGET/oapi/tweet_filter/get_rules
Update rulePOST/oapi/tweet_filter/update_rule body {rule_id, tag, value, interval_seconds?, is_effect?}
Delete ruleDELETE/oapi/tweet_filter/delete_rule body {rule_id} (body JSON, not query)

Writes — require login_cookies + proxy in body. login_cookies is base64(json(cookie_dict)) from /twitter/user_login_v2.

CapabilityMethodPathKey body fields (beyond login_cookies+proxy)
Log in → cookiesPOST/twitter/user_login_v2{user_name, email, password, totp_secret?, proxy}
Create tweetPOST/twitter/create_tweet_v2tweet_text (req); optional reply_to_tweet_id, quote_tweet_id, community_id, media_ids[], schedule_for
DeletePOST/twitter/delete_tweet_v2tweet_id
Like / UnlikePOST/twitter/{like,unlike}_tweet_v2tweet_id
RetweetPOST/twitter/retweet_tweet_v2tweet_id
Bookmark / UnbookmarkPOST/twitter/{bookmark,unbookmark}_tweet_v2tweet_id
List bookmarksPOST/twitter/bookmarks_v2optional count (def 20, not pageSize), cursor
Follow / UnfollowPOST/twitter/{follow,unfollow}_user_v2user_id
Send DMPOST/twitter/send_dm_to_useruser_id, text, optional media_id (singular), reply_to_message_id
ReportPOST/twitter/report_v2(tweet_id OR user_id), reason (enum, see endpoints.md)
Upload mediaPOST/twitter/upload_media_v2multipart: file, optional media_category, is_long_video
Update profilePATCH/twitter/update_profile_v2JSON: at least one of name, description (not bio!), location, url
Update avatar/bannerPATCH/twitter/update_{avatar,banner}_v2multipart: file
Create communityPOST/twitter/create_community_v2name, description (both required)
Join / Leave communityPOST/twitter/{join,leave}_community_v2community_id
Delete communityPOST/twitter/delete_community_v2community_id, community_name (both required)
Add list memberPOST/twitter/list/add_member_v2list_id, user_id

For exact param lists, response shapes, and edge cases see references/endpoints.md.

Recurring patterns

Cursor pagination — use has_next_page

def iter_followers(user_name):
    cursor = ""
    while True:
        r = requests.get(f"{BASE}/twitter/user/followers",
                         headers=HEADERS,
                         params={"userName": user_name, "cursor": cursor, "pageSize": 200},
                         timeout=30).json()
        yield from r.get("followers", [])
        if not r.get("has_next_page"):
            break
        cursor = r.get("next_cursor") or ""

Error handling

# FastAPI-style 4xx/5xx
{ "detail": "tweet_id is required" }
{ "detail": [{"type":"missing","loc":["body","file"]}] }  # 422 on multipart

# Semantic 200 errors
{ "status": "error", "msg": "No active monitoring subscription" }
  • 401 → bad x-api-key or expired login_cookies
  • 402 → top up balance at dashboard
  • 429 → rate-limited; exponential backoff
  • 400/422 → read detail — it names the missing/wrong field
  • 500 → transient; retry with jitter. If repeated, the param name is wrong

Cost awareness

Before a loop that could paginate for a long time (followers of a mega-account, years of advanced search), estimate cost up front and confirm with the user if it could exceed a few dollars. A 100M-follower crawl is $15k+ at $0.15/1k.

Anti-patterns

  • Do not assume a universal param-casing rule — check endpoints.md
  • Do not use login_cookie (singular) — it's login_cookies plural
  • Do not forget proxy in write bodies — every write requires it
  • Do not send text for create_tweet_v2 — use tweet_text
  • Do not use bio in update_profile_v2 — use description
  • Do not use in_reply_to_tweet_id for create_tweet_v2 — it's reply_to_tweet_id
  • Do not send JSON to upload_media_v2 / update_avatar_v2 / update_banner_v2 — they're multipart/form-data
  • Do not use pageSize for bookmarks_v2 — it's count
  • Do not send user_id to monitoring add — it's x_user_name; remove uses id_for_user
  • Do not log or commit API keys, login_cookies, proxies, or totp_secret
  • Do not use developer.twitter.com / official X OAuth — this API replaces them
  • Do not poll /user/last_tweets for "real-time" — use /oapi/tweet_filter/add_rule + webhook