Skip to content

Repository files navigation

twitscraper

A Python library for interacting with Twitter/X — no API key required.

Uses cookie-based authentication and browser-level HTTP fingerprinting (curl_cffi) to bypass connection issues that affect standard httpx clients.

Demo

Features

  • No API key required
  • Cookie-based auth — paste cookies from your browser, no login flow needed
  • Supports 4 cookie input formats
  • Async API built on twikit internals

Install

pip install twitscraper

Getting your cookies

  1. Open x.com and log in
  2. Open DevTools → Application → Cookies → https://x.com
  3. Copy auth_token and ct0 (minimum required)

Or use a browser extension like EditThisCookie or Cookie-Editor to export all cookies at once.

Quick start

From a dict

import asyncio
from twitscraper import create_client

async def main():
    client = await create_client({
        "auth_token": "your_auth_token",
        "ct0": "your_ct0",
        "twid": "u%3D123456789",
    })

    me = await client.user()
    print(me.screen_name)

asyncio.run(main())

From a JSON file

from twitscraper import create_client_from_file

client = await create_client_from_file("cookies.json")

cookies.json:

{
  "auth_token": "...",
  "ct0": "...",
  "twid": "u%3D123456789"
}

From a raw cookie string (Network tab)

from twitscraper import create_client_from_string

raw = "auth_token=abc123; ct0=xyz789; twid=u%3D123456789"
client = await create_client_from_string(raw)

From a browser extension export

from twitscraper import create_client_from_browser_export

# Paste the JSON array copied from EditThisCookie / Cookie-Editor
raw_json = '[{"name": "auth_token", "value": "...", "domain": ".x.com"}, ...]'
client = await create_client_from_browser_export(raw_json)

Examples

Search tweets

tweets = await client.search_tweet("python", "Latest")
for tweet in tweets:
    print(tweet.user.screen_name, tweet.text)

Create a tweet

tweet = await client.create_tweet("Hello from twitscraper!")

Upload media

media_id = await client.upload_media("image.jpg")
await client.create_tweet("Tweet with image", media_ids=[media_id])

Send a DM

await client.send_dm("123456789", "Hello!")

Get trends

trends = await client.get_trends("trending")
for t in trends:
    print(t.name)

Download tweet media

tweet = await client.get_tweet_by_id("tweet_id")
for i, media in enumerate(tweet.media):
    if media.type == "photo":
        await media.download(f"photo_{i}.jpg")
    elif media.type == "video":
        await media.streams[-1].download(f"video_{i}.mp4")

Listen for new tweets

import asyncio
from twitscraper import Tweet

async def on_new_tweet(tweet: Tweet):
    print(f"New tweet: {tweet.text}")

USER_ID = "44196397"
before = (await client.get_user_tweets(USER_ID, "Tweets", count=1))[0]

while True:
    await asyncio.sleep(60)
    latest = (await client.get_user_tweets(USER_ID, "Tweets", count=1))[0]
    if latest.id != before.id:
        await on_new_tweet(latest)
        before = latest

Rate limits

See ratelimits.md for per-endpoint limits (reset every 15 minutes).

Testing

A full integration test suite is available in test_twitscraper/.

cd test_twitscraper
pip install -r requirements.txt
# add your cookies.json or .env (see test_twitscraper/README.md)
cd tests && python run_all.py

See test_twitscraper/README.md for full setup instructions.

License

MIT