How to Scrape Twitter/X Without an API Key in Python (2026 Guide)

Published: (April 3, 2026 at 03:52 PM EDT)
4 min read
Source: Dev.to

Source: Dev.to

Why use Scweet instead of the official API?

Twitter/X’s official API now starts at $200 / month just to read tweets. The free tier is write‑only – you can post, but you can’t search, pull timelines, or read anything except your own profile.

Scweet bypasses the need for an API key by re‑using the same GraphQL endpoints that the web app uses internally. It sends HTTP requests with the same cookies (auth_token and ct0) that your browser sends, so from X’s perspective it looks like normal browser activity.

  • No headless browser, Selenium, or Playwright required.
  • Runs locally for $0 (or about $0.30 / 1 000 tweets on the hosted cloud version).
  • Works with a single free X account plus an optional proxy.

Twitter/X API pricing (2026)

TierPrice (USD)What you get
Free$0Write‑only. 500 posts/month. No search, no read access. Only endpoint: GET /2/users/me
Basic$200/month15 000 read requests/month. 7 days of search history
Pro$5 000/month1 million tweets. Full‑archive search
Enterprise$42 000+/monthCustom, compliance streams
Pay‑as‑you‑go (Feb 2026)~ $575/month for Basic‑equivalent usageNot cheaper than the Basic plan

Sources: TechCrunch, X Developer Community, xpoz.ai pricing breakdown.

Installation

pip install -U scweet

Obtaining auth_token

  1. Log in to x.com in Chrome or Firefox.
  2. Open DevTools (F12) → ApplicationCookieshttps://x.com.
  3. Find the auth_token cookie and copy its value.

Scweet will automatically bootstrap the ct0 CSRF token from this cookie, so you only need the auth_token. It stays valid for weeks to months; when it expires Scweet raises an AuthError.

Basic usage (Python)

from Scweet import Scweet

s = Scweet(
    auth_token="YOUR_AUTH_TOKEN",
    proxy="http://user:pass@host:port"   # optional but recommended
)

# Search for tweets about Bitcoin from 2025 onward
tweets = s.search(
    "bitcoin",
    since="2025-01-01",
    limit=200,
    save=True               # writes results to a CSV file
)

print(f"Collected {len(tweets)} tweets")

You can change the output format:

s.search("bitcoin", limit=100, save=True, save_format="json")   # JSON
s.search("bitcoin", limit=100, save=True, save_format="both")   # CSV + JSON

Each tweet record includes:

  • tweet_id, timestamp, text, likes, retweets, comments, tweet_url
  • user (screen_name, name)
  • image_links
  • Full raw GraphQL payload (if needed)

CLI usage (no Python code)

scweet --auth-token YOUR_AUTH_TOKEN \
       --proxy http://user:pass@host:port \
       search "bitcoin" --since 2025-01-01 --limit 200 --save

Available endpoints

EndpointDescription
s.search()Full‑text tweet search
s.get_profile_tweets(usernames, limit=…)Timeline of a user’s own tweets
s.get_followers(usernames, limit=…)Followers list
s.get_following(usernames, limit=…)Following list
s.get_user_info(usernames)Bio, follower count, verification status, creation date

All methods accept a list of usernames, enabling batch requests. Asynchronous variants (asearch(), aget_profile_tweets(), etc.) are also provided.

Multi‑account pooling

For larger scrapes you can rotate several accounts, each with its own proxy:

[
  {
    "username": "account_1",
    "cookies": { "auth_token": "TOKEN_1" },
    "proxy": "http://user1:pass1@host1:port1"
  },
  {
    "username": "account_2",
    "cookies": { "auth_token": "TOKEN_2" },
    "proxy": "http://user2:pass2@host2:port2"
  }
]
s = Scweet(cookies_file="cookies.json")
tweets = s.search("AI startups", limit=10000, save=True)

Scweet stores pool state in SQLite (leases, heartbeats, daily counters, cooldowns) and automatically fails over when an account hits its limit.

Resuming interrupted scrapes

tweets = s.search("AI startups", limit=10000, save=True, resume=True)

resume=True picks up exactly where the previous run left off.

Apify actor integration (no code)

Scweet is also available as an Apify actor (altimis/scweet). The hosted version includes a free tier (up to 1 000 tweets/day) and scales to millions at $0.25 / 1 000 tweets.

from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("altimis/scweet").call(run_input={
    "search_query": "bitcoin",
    "max_items": 500,
})
tweets = client.dataset(run["defaultDatasetId"]).list_items().items
print(f"Got {len(tweets)} tweets")

This is handy for pipelines, cron jobs, or n8n/Zapier workflows without managing Python dependencies or cookies.

Resources

  • GitHub repository: (MIT license, 250+ tests)
  • PyPI package: pip install scweet
  • Apify actor: (hosted, no‑code)
  • Full documentation:
0 views
Back to Blog

Related posts

Read more »

How to Use rs-trafilatura with Firecrawl

Introduction Firecrawl is an API service for scraping web pages. It handles JavaScript rendering, anti‑bot bypass, and rate limiting — you send it a URL, it re...