Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Read-only Twitter/X data: search tweets, user profiles, followers, replies, and retweets via twitterapi.io.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
SKILL.md
1---2name: twitter3version: 2.0.24description: |5Twitter/X data: fetch tweets, search, user profiles, followers, replies, trends.67Use for any x.com or twitter.com URL or lookup (e.g. summarize this tweet, recent posts by @vitalikbuterin, search $SOL min_faves:50).8delivery: script9metadata:10starchild:11emoji: "๐ฆ"12skillKey: twitter13requires:14env:15- TWITTER_API_KEY1617user-invocable: false18disable-model-invocation: false1920---2122# Twitter / X (script-mode)2324Read-only access to twitterapi.io endpoints. 13 functions covering tweets,25users, followers, replies, threads, quotes, articles, and trends.2627All requests go through sc-proxy via `core.http_client.proxied_get`. The28`TWITTER_API_KEY` env var is auto-injected server-side, no local key needed29on the agent machine.3031## Script Usage3233Standard invocation pattern:3435```bash36python3 - <<'EOF'37import sys, json38sys.path.insert(0, "/data/workspace/skills/twitter")39from exports import twitter_user_info, twitter_user_tweets4041profile = twitter_user_info(username="vitalikbuterin")42print(json.dumps(profile, indent=2))4344recent = twitter_user_tweets(username="vitalikbuterin")45print(f"got {len(recent.get('tweets', []))} tweets")46EOF47```4849Tweet ID extraction from URL: the last path segment of any50`x.com/{user}/status/{id}` or `twitter.com/{user}/status/{id}` URL is the51tweet ID. Pass it as a string (Python int will lose precision on long IDs).5253## Function Reference (signatures)5455All 13 functions live in `exports.py`. Returns are dicts straight from56twitterapi.io โ keys vary per endpoint, inspect once before scripting.5758### Tweet endpoints5960| Function | Description |61|---|---|62| `twitter_search_tweets(query, cursor=None)` | Advanced search. Operators: `from:user`, `to:user`, `#tag`, `$cashtag`, `lang:en`, `has:media`, `has:links`, `is:reply`, `min_faves:N`, `since:YYYY-MM-DD`, `until:YYYY-MM-DD`. |63| `twitter_get_tweets(tweet_ids)` | Fetch one or more tweets by ID. `tweet_ids` = list of strings (also accepts comma-string). |64| `twitter_tweet_replies(tweet_id, cursor=None)` | Replies to a tweet. |65| `twitter_tweet_retweeters(tweet_id, cursor=None)` | Users who retweeted. |66| `twitter_tweet_thread_context(tweet_id)` | Full thread context (parents + direct replies). |67| `twitter_tweet_quote(tweet_id, cursor=None)` | Quote tweets. |68| `twitter_get_article(tweet_id)` | Long-form X article body. |69| `twitter_get_trends(woeid=None, country=None, category=None, limit=None)` | Trending topics; all filters optional. |7071### User endpoints7273| Function | Description |74|---|---|75| `twitter_user_info(username)` | Profile: bio, follower/following counts, tweet count, verified. |76| `twitter_user_tweets(username, cursor=None)` | User's recent tweets. |77| `twitter_user_followers(username, cursor=None)` | Follower list. |78| `twitter_user_followings(username, cursor=None)` | Accounts followed. |79| `twitter_search_users(query, cursor=None)` | Search users by name/keyword. |8081`username` is the handle WITHOUT `@` (e.g. `"elonmusk"`, not `"@elonmusk"`).82Pagination: when a response includes `next_cursor`, pass it back as `cursor`83on the next call.8485## When to use this skill8687- ANY `x.com/...` or `twitter.com/...` URL โ start here, NOT `web_fetch`88(Twitter blocks scrapers).89- Single tweet detail โ `twitter_get_tweets([tweet_id])`.90- "What's @user been posting?" โ `twitter_user_tweets`.91- KOL discovery / cashtag mentions โ `twitter_search_tweets("$SOL min_faves:50")`.92- Trending topics โ `twitter_get_trends`.9394## Billing & cost control (READ before bulk/scheduled use)9596twitterapi.io bills **per item actually returned**, not per request and NOT by97any "max_results" you ask for. sc-proxy charges = returned-item-count ร unit98(tweets 45 / profiles 54 / followers 45 credits; 100k credits = $1; 3ร upstream).99Min 1 item per request.100101**The `last_tweets` / `user_tweets` trap:** the upstream102`/twitter/user/last_tweets` endpoint has **no page-size parameter** โ it always103returns up to **20 tweets per page**. There is no `max_results` / `pageSize`104lever, and `twitter_user_tweets()` does not accept one. So "I only need 5" still105fetches and **bills for ~20**. Slicing the result client-side does NOT save106money โ the charge is already counted at the proxy from the upstream response.107108### โญ Polling for "new tweets from account X" โ use search, NOT last_tweets109110This is the biggest, most common waste. `twitter_user_tweets()` (upstream111`last_tweets`) has **no page-size param** and always bills a full ~20-tweet112page every call, even when nothing new was posted. The official twitterapi.io113guide recommends the **advanced_search** endpoint instead, which our skill114already exposes as `twitter_search_tweets()`:115116```python117# Cheap polling pattern โ bills only the tweets actually in the window.118# When NO new tweet exists, the call is billed as 1 item (not 20).119import time120since = int(last_check_unix)121until = int(time.time())122q = f"from:{handle} include:nativeretweets since_time:{since} until_time:{until}"123res = twitter_search_tweets(q) # queryType defaults to Latest124```125126Official pricing (upstream; our proxy bills 3ร):127- tweets found โ $0.00015 per returned tweet128- **no tweets found โ $0.00015 for the whole call** (vs last_tweets' ~20ร that)129130Per-call cost in our billing makes the difference obvious:131- `last_tweets` โ ~$0.009/call (20 tweets every time)132- `advanced_search` empty window โ ~$0.00045/call (1 item) โ **~20ร cheaper**133134Frequency vs monthly cost (single account, upstream): hourly $0.11 ยท 30min135$0.22 ยท 15min $0.43 ยท 5min $1.30 ยท 1min $6.48.136137### Other cost levers138- **Use `get_tweets([ids])`** when IDs are known โ pay only for those exact139tweets, not a 20-item page.140- **Followers/followings** bill per returned profile (default page 200 โ 200141billed). Only paginate as far as needed. For ID-only graph work use the142bulk followers-IDs endpoint (lightweight).143- **Tighten search queries** (min_faves, since_time/until_time, lang) so fewer144pages are needed.145146> Note: twitterapi.io also sells a managed stream/webhook product. **We do NOT147> subscribe to it** โ do not use the `/oapi/x_user_stream/*` or148> `/oapi/tweet_filter/*` endpoints. For any account-monitoring need, the149> advanced_search polling pattern above is the correct and only approach here.150151## Error handling152153- `402 Credits is not enough` โ upstream proxy credits exhausted; tell user154to top up. Don't retry.155- `429` โ rate limited; surface to user, don't auto-retry.156- `404 user not found` โ suggest verifying the handle spelling.157158## Version Policy (hard rule)159160This skill is **script-mode** (`delivery: script`). It does NOT register161runtime tools โ agent must `read_file` SKILL.md and call functions via162`bash` + `python3`. The legacy `tools.py` / `__init__.py` files are kept163for backward compatibility but are no longer the preferred entry point.164165Bump rules:166- Any signature change, env-var change, or sc-proxy contract change โ MAJOR167- New function added, response schema clarified โ MINOR168- Bug fix or doc-only change โ PATCH169