Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Guide for using twscrape to collect public Twitter/X data through its GraphQL interface, asynchronous queries, and account session management.
.claude/skills/aiskillstore-twscrape/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 274% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 150% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 65% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 71% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 109% | 0% |
Python library for scraping Twitter/X data using GraphQL API with account rotation and session management.
Use this skill when:
bashpip install twscrape
pythonimport asyncio from twscrape import API, gather async def main(): api = API() # Uses accounts.db by default # Add accounts (with cookies - more stable) cookies = "abc=12; ct0=xyz" await api.pool.add_account("user1", "pass1", "email@example.com", "mail_pass", cookies=cookies) # Or add accounts (with login/password - less stable) await api.pool.add_account("user2", "pass2", "email2@example.com", "mail_pass2") await api.pool.login_all() asyncio.run(main())
python# Search tweets await gather(api.search("elon musk", limit=20)) # Get user info await api.user_by_login("xdevelopers") user = await api.user_by_id(2244994945) # Get user tweets await gather(api.user_tweets(user_id, limit=20)) await gather(api.user_tweets_and_replies(user_id, limit=20)) await gather(api.user_media(user_id, limit=20)) # Get followers/following await gather(api.followers(user_id, limit=20)) await gather(api.following(user_id, limit=20)) # Tweet operations await api.tweet_details(tweet_id) await gather(api.retweeters(tweet_id, limit=20)) await gather(api.tweet_replies(tweet_id, limit=20)) # Trends await gather(api.trends("news"))
python# Parallel scraping async for tweet in api.search("elon musk"): print(tweet.id, tweet.user.username, tweet.rawContent)
search(query, limit, kv={})Search tweets by query string.
Parameters:
query (str): Search query (supports Twitter search syntax)limit (int): Maximum number of tweets to returnkv (dict): Additional parameters (e.g., {"product": "Top"} for Top tweets)Returns: AsyncIterator of Tweet objects
Example:
python# Latest tweets async for tweet in api.search("elon musk", limit=20): print(tweet.rawContent) # Top tweets await gather(api.search("python", limit=20, kv={"product": "Top"}))
user_by_login(username)Get user information by username.
Example:
pythonuser = await api.user_by_login("xdevelopers") print(user.id, user.displayname, user.followersCount)
user_by_id(user_id)Get user information by user ID.
followers(user_id, limit)Get user's followers.
following(user_id, limit)Get users that the user follows.
verified_followers(user_id, limit)Get only verified followers.
subscriptions(user_id, limit)Get user's Twitter Blue subscriptions.
tweet_details(tweet_id)Get detailed information about a specific tweet.
tweet_replies(tweet_id, limit)Get replies to a tweet.
retweeters(tweet_id, limit)Get users who retweeted a specific tweet.
user_tweets(user_id, limit)Get tweets from a user (excludes replies).
user_tweets_and_replies(user_id, limit)Get tweets and replies from a user.
user_media(user_id, limit)Get tweets with media from a user.
list_timeline(list_id)Get tweets from a Twitter list.
trends(category)Get trending topics by category.
Categories: "news", "sport", "entertainment", etc.
With cookies (recommended):
pythoncookies = "abc=12; ct0=xyz" # String or JSON format await api.pool.add_account("user", "pass", "email@example.com", "mail_pass", cookies=cookies)
With credentials:
pythonawait api.pool.add_account("user", "pass", "email@example.com", "mail_pass") await api.pool.login_all()
bash# Add accounts from file twscrape add_accounts accounts.txt username:password:email:email_password # Login all accounts twscrape login_accounts # Manual email verification twscrape login_accounts --manual # List accounts and status twscrape accounts # Re-login specific accounts twscrape relogin user1 user2 # Retry failed logins twscrape relogin_failed
pythonproxy = "http://login:pass@example.com:8080" await api.pool.add_account("user", "pass", "email@example.com", "mail_pass", proxy=proxy)
pythonapi = API(proxy="http://login:pass@example.com:8080")
bashexport TWS_PROXY=socks5://user:pass@127.0.0.1:1080 twscrape search "elon musk"
pythonapi.proxy = "socks5://user:pass@127.0.0.1:1080" doc = await api.user_by_login("elonmusk") api.proxy = None # Disable proxy
Priority: api.proxy > TWS_PROXY env var > account-specific proxy
bashtwscrape search "QUERY" --limit=20 twscrape search "elon musk lang:es" --limit=20 > data.txt twscrape search "python" --limit=20 --raw # Raw API responses
bashtwscrape user_by_login USERNAME twscrape user_by_id USER_ID twscrape followers USER_ID --limit=20 twscrape following USER_ID --limit=20 twscrape verified_followers USER_ID --limit=20 twscrape user_tweets USER_ID --limit=20
bashtwscrape tweet_details TWEET_ID twscrape tweet_replies TWEET_ID --limit=20 twscrape retweeters TWEET_ID --limit=20
bashtwscrape trends sport twscrape trends news
bashtwscrape --db custom-accounts.db <command>
pythonasync for response in api.search_raw("elon musk"): print(response.status_code, response.json())
pythonfrom contextlib import aclosing async with aclosing(api.search("elon musk")) as gen: async for tweet in gen: if tweet.id < 200: break
pythonuser = await api.user_by_id(user_id) user_dict = user.dict() user_json = user.json()
pythonfrom twscrape.logger import set_log_level set_log_level("DEBUG")
TWS_PROXY: Global proxy for all accountsExample: socks5://user:pass@127.0.0.1:1080
TWS_WAIT_EMAIL_CODE: Timeout for email verification (default: 30 seconds)TWS_RAISE_WHEN_NO_ACCOUNT: Raise exception when no accounts available instead of waitingValues: false, 0, true, 1 (default: false)
user_tweets and user_tweets_and_replies return approximately 3,200 tweets maximum per userThe library automatically:
pythonasync def collect_user_data(username): user = await api.user_by_login(username) # Collect tweets tweets = await gather(api.user_tweets(user.id, limit=100)) # Collect followers followers = await gather(api.followers(user.id, limit=100)) # Collect following following = await gather(api.following(user.id, limit=100)) return { 'user': user, 'tweets': tweets, 'followers': followers, 'following': following }
python# Language filter await gather(api.search("python lang:en", limit=20)) # Date filter await gather(api.search("AI since:2024-01-01", limit=20)) # From specific user await gather(api.search("from:elonmusk", limit=20)) # With media await gather(api.search("cats filter:media", limit=20))
pythonasync def process_users(usernames): tasks = [] for username in usernames: task = api.user_by_login(username) tasks.append(task) users = await asyncio.gather(*tasks) return users
--manual flagtwscrape accountspip install twscrapepip install git+https://github.com/vladkens/twscrape.gitFor detailed API documentation and examples, see the reference files in the references/ directory:
references/installation.md - Installation and setupreferences/api_methods.md - Complete API method referencereferences/account_management.md - Account configuration and managementreferences/cli_usage.md - Command-line interface guidereferences/proxy_config.md - Proxy configuration optionsreferences/examples.md - Code examples and patternsRepository: https://github.com/vladkens/twscrape Stars: 1998+ Language: Python License: MIT
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 6,051 | 5,245 | -13% | 1 | 1 | 0% | 1,065 | 3,986 | +274% | 0 | 0 | — |
case-02 | fail→pass | 12,987 | 1,767 | -86% | 1 | 1 | 0% | 1,318 | 3,301 | +150% | 0 | 0 | — |
case-03 | fail→pass | 13,418 | 2,830 | -79% | 1 | 1 | 0% | 2,092 | 3,443 | +65% | 0 | 0 | — |
case-04 | pass→pass | 15,527 | 17,752 | +14% | 1 | 1 | 0% | 2,688 | 4,581 | +70% | 0 | 0 | — |
case-05 | pass→pass | 17,398 | 10,880 | -37% | 1 | 1 | 0% | 2,774 | 4,774 | +72% | 0 | 0 | — |
case-06 | pass→pass | 10,722 | 5,344 | -50% | 1 | 1 | 0% | 1,733 | 3,938 | +127% | 0 | 0 | — |
case-07 | pass→pass | 10,787 | 4,118 | -62% | 1 | 1 | 0% | 1,911 | 3,792 | +98% | 0 | 0 | — |
case-08 | pass→pass | 7,190 | 3,133 | -56% | 1 | 1 | 0% | 1,024 | 3,600 | +252% | 0 | 0 | — |
case-09 | fail→pass | 11,041 | 4,195 | -62% | 1 | 1 | 0% | 1,996 | 3,423 | +71% | 0 | 0 | — |
case-10 | fail→pass | 9,764 | 2,402 | -75% | 1 | 1 | 0% | 1,648 | 3,451 | +109% | 0 | 0 | — |
case-11 | pass→pass | 8,282 | 3,395 | -59% | 1 | 1 | 0% | 1,593 | 3,642 | +129% | 0 | 0 | — |
case-12 | fail→pass | 11,173 | 3,143 | -72% | 1 | 1 | 0% | 1,805 | 3,580 | +98% | 0 | 0 | — |
case-13 | pass→pass | 9,189 | 11,407 | +24% | 1 | 1 | 0% | 1,542 | 3,849 | +150% | 0 | 0 | — |
case-14 | fail→pass | 27,492 | 2,943 | -89% | 1 | 1 | 0% | 2,140 | 3,575 | +67% | 0 | 0 | — |
case-15 | pass→pass | 5,106 | 2,515 | -51% | 1 | 1 | 0% | 896 | 3,481 | +289% | 0 | 0 | — |
case-16 | fail→pass | 16,318 | 3,914 | -76% | 1 | 1 | 0% | 2,739 | 3,649 | +33% | 0 | 0 | — |
case-17 | fail→pass | 4,965 | 2,266 | -54% | 1 | 1 | 0% | 879 | 3,371 | +284% | 0 | 0 | — |
case-18 | fail→pass | 9,619 | 3,600 | -63% | 1 | 1 | 0% | 1,568 | 3,324 | +112% | 0 | 0 | — |
case-19 | pass→pass | 11,682 | 3,087 | -74% | 1 | 1 | 0% | 1,826 | 3,514 | +92% | 0 | 0 | — |
case-20 | fail→pass | 12,348 | 3,886 | -69% | 1 | 1 | 0% | 2,337 | 3,313 | +42% | 0 | 0 | — |
case-21 | pass→pass | 6,220 | 2,550 | -59% | 1 | 1 | 0% | 1,087 | 3,446 | +217% | 0 | 0 | — |
case-22 | pass→pass | 5,417 | 2,752 | -49% | 1 | 1 | 0% | 804 | 3,533 | +339% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +50 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.