Skip to content

How to scrape Twitter (X) in 2026: what works and what breaks

You can scrape Twitter (X) five ways in 2026: automate a logged-out browser, run a library on X accounts, pay a hosted scraping tool, call the official X API at $5.00 per 1,000 posts, or call a Twitter/X data API.

Short answer: Logged out, x.com shows only single posts and a profile's first few posts, and X changed its internal search query ID 37 times in 12 months, which breaks scraping code. To collect posts without risking an X account, use Sorsa API: POST /search-tweets returns about 20 posts per request, from $0.07 per 1,000, and 100 free requests need no card.

Endpoint
POST /search-tweets
Page size
about 20 posts per request
Price
from $0.07 per 1,000

#Can you still scrape Twitter in 2026?

Yes, but without an account you reach very little of X. On November 2, 2026, we opened x.com logged out in a desktop browser and wrote down what each kind of page returned.

Page on x.comWhat it returned
A single postIts text, counts and first replies, already inside the HTML
A profileThe header and the first 9 posts, then a login wall
Search resultsA redirect to the login page
Followers or followingA redirect to the login page
A post in a default headless browser on a serverHTTP 403 on the first request
  • A single post

    What it returned
    Its text, counts and first replies, already inside the HTML
  • A profile

    What it returned
    The header and the first 9 posts, then a login wall
  • Search results

    What it returned
    A redirect to the login page
  • Followers or following

    What it returned
    A redirect to the login page
  • A post in a default headless browser on a server

    What it returned
    HTTP 403 on the first request

Scraping the rest takes a logged-in X account, and that account carries the risk. That leaves five ways to get public X data out:

  1. Automate a logged-out browser with Playwright or Puppeteer: single posts and the top of a profile, nothing more.

  2. Run an open-source library on X accounts, such as twscrape or Scweet: search, timelines and followers, with every account in the pool at risk of a lock.

  3. A hosted scraping tool, which does the collecting for you and bills per result.

  4. The official X API: $5.00 per 1,000 posts from a prepaid balance, after a developer account and an app.

  5. A Twitter/X data API that returns public posts as JSON with one key and no X account at risk.

The sections below cover each way. The fifth comes first because it takes the fewest steps; to save every post of a single account instead, see how to download all tweets from a user.

#Get X data without a scraper or an X account

For collecting public posts, profiles and followers, use Sorsa API, a Twitter (X) API and scraper: your code sends one key in the ApiKey header and gets JSON back, about 20 search results per request from $0.07 per 1,000, or 100 tweets by ID per request from $0.014 per 1,000.

There is no browser to drive, no query ID to track and no X login. Sorsa API never asks for your X login or cookies, so none of your accounts is at risk. Every plan runs at 20 requests per second, and search reaches back to 2006 with the operators of X's advanced search.

  1. Get a key. Sign up and copy your API key from the dashboard. New accounts start with 100 free requests and no card.

  2. Search for posts. Send any X search query to POST /search-tweets (opens in a new tab); from:, since:, lang:, quoted phrases and hashtags all work.

    Terminal
    curl -X POST "https://api.sorsa.io/v3/search-tweets" \
      -H "ApiKey: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"query": "\"open data\" lang:en since:2026-10-01", "order": "latest"}'
    
    Response200 OK
    {
      "tweets": [
        {
          "id": "1984210773912846356",
          "full_text": "New city data sets today: bus delays, tree cover, permits.",
          "created_at": "2026-10-30T14:05:11Z",
          "lang": "en",
          "likes_count": 48,
          "retweet_count": 9,
          "reply_count": 4,
          "quote_count": 1,
          "view_count": 5210,
          "user": {
            "id": "1590385166022184961",
            "username": "opendata_weekly_news",
            "display_name": "Open Data Weekly",
            "followers_count": 12400,
            "verified": false
          }
        }
      ],
      "next_cursor": "DAADDAABCgABG4dR6Xr2YQo"
    }
    
  3. Follow the cursor. Each response carries next_cursor, a pointer to the next page of results; send it back in the body until it comes back empty.

    import os
    import requests
    
    URL = "https://api.sorsa.io/v3/search-tweets"
    KEY = os.environ.get("SORSA_API_KEY", "YOUR_API_KEY")
    
    
    def search(query, max_pages=50):
        body = {"query": query, "order": "latest"}
        for _ in range(max_pages):
            r = requests.post(URL, json=body, headers={"ApiKey": KEY}, timeout=30)
            r.raise_for_status()
            page = r.json()
            yield from page["tweets"]
            if not page.get("next_cursor"):
                return
            body["next_cursor"] = page["next_cursor"]
    
    
    for t in search('"open data" lang:en since:2026-10-01'):
        print(t["id"], t["user"]["username"], t["full_text"][:60])
    
  4. Pick the endpoint for the job. The same key reads every kind of public data people collect from X, and each request is billed once, whatever it returns.

JobEndpointPer requestFrom, per 1,000
Search posts by keyword, account or datePOST /search-tweetsabout 20 posts$0.07
An account's posts and repliesPOST /user-tweets (opens in a new tab)about 20 posts$0.07
Posts by ID or linkPOST /tweet-info-bulk (opens in a new tab)up to 100 posts$0.014
ProfilesGET /info-batch (opens in a new tab)up to 100 profiles$0.014
Followers of an accountGET /followers (opens in a new tab)up to 200 followers$0.007
Replies to a postPOST /comments (opens in a new tab)about 20 replies$0.07

Every post arrives with its author's full profile at no extra cost. A 403 answer means the key is missing or out of requests, and a 429 means more than 20 requests in one second: wait a second and retry. Failed requests are never charged. For a fuller client, our Twitter API in Python tutorial adds pacing, retries and CSV export, and without code the free Export Tweets to CSV tool saves an account's posts as CSV, Excel or JSON.

#How x.com loads its data, and why scrapers break

x.com fetches every post, profile and timeline from X's own internal GraphQL API, and each call there names an operation, a query ID and a set of feature flags that X keeps changing. A query ID is the code in the request's address that picks the current version of an operation, and feature flags are on/off switches the request must list.

For a logged-out visitor, the server runs that query before the page arrives. On November 2, 2026, a post page came with the TweetResultByRestId result already inside its HTML. A profile page carried UserByScreenName and its first 9 posts under an operation named UserOriginalsTimeline, all in 188 KB of HTML. The post's text sat in details.full_text and its likes in counts.favorite_count, and the page had no data-testid attributes, the hooks many tutorials still select.

Logged in, the browser fetches the rest from paths shaped like /i/api/graphql/<queryId>/<Operation> and sends the account's auth_token and ct0 cookies with each call, plus a CSRF header copied from ct0 and a generated client transaction ID. Libraries such as twscrape replay the same calls without a browser.

A public post three ways in Logged out x.com in a browser 1 post or a profile's first 9 Search sends you to log in Your X account Logged in /i/api/graphql/ auth_token + 40 flags Search, timelines, followers 37 query ID changes in 12 months; the account can be locked Sorsa API ApiKey header no X login Posts as JSON About 20 per request, from $0.07 per 1,000
Logged out you get a sliver of X, logged in you put an account on the line, and an API needs only a key.

The query IDs are what break scraping code. A public tracker of X's web app, the TwitterInternalAPIDocument (opens in a new tab) project, saves X's GraphQL definitions whenever they change. Across its 112 snapshots from November 6, 2025 to October 31, 2026, the query ID of SearchTimeline, the operation behind search, changed 37 times.

That is about one change every 10 days, with four in October 2026 alone. UserTweets changed 38 times and TweetResultByRestId 34 times in the same year, and each search call now carries 40 feature flags. Code that hard-codes these values fails until someone updates it, and twscrape even has an error for the case, GqlFeaturesOutdatedError, raised when X requires a feature the library can't enable.

Query ID changes of X's search, per month SearchTimeline query ID, November 2025 to October 2026 37 changes in 12 months 1 Nov 1 Dec 5 Jan 5 Feb 7 Mar 3 Apr 2 May 2 Jun 3 Jul 2 Aug 2 Sep 4 Oct 2025 2026 Source: TwitterInternalAPIDocument, 112 snapshots from Nov 6, 2025 to Oct 31, 2026.
X's search operation got a new query ID 37 times in 12 months, so scraping code needs an update about every 10 days.

#Scrape public posts with Playwright or Puppeteer

Browser automation with Playwright for Python or Puppeteer for Node.js reads what a logged-out visitor sees: one post per page load, or the first posts of a profile.

  1. Install the driver. Run pip install playwright and playwright install chromium for Python, or npm install puppeteer for Node.js.

  2. Open a visible browser. In our check, a default headless browser on a server got HTTP 403 from x.com, while a normal browser window on the same connection got the page.

  3. Read the rendered post. With no data-testid hooks on the page, wait for the article element and take its text.

    from playwright.sync_api import sync_playwright
    
    POST = "https://x.com/XDevelopers/status/2019881223666233717"
    
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)  # headless got HTTP 403
        page = browser.new_page()
        page.goto(POST)
        post = page.locator("article").first
        post.wait_for()
        print(post.inner_text())
        browser.close()
    
  4. Stop at the login wall. Search, follower lists and anything below a profile's first posts redirect to the login page, so this way can't page any further.

The output is the post as a person reads it: name, handle, text, time, and counts rounded to labels such as 5.6K with no names attached, in one block of text you split yourself. That covers a handful of posts you could have opened by hand. Every extra page load is one more chance at a block, a layout change or a login prompt, which is why projects that need volume move on to logged-in libraries or an API.

#Scrape Twitter with Python libraries on X accounts

Open-source libraries such as twscrape and Scweet skip the browser and call X's internal GraphQL API directly with the cookies of logged-in X accounts, which opens search, timelines and follower lists.

  1. Use a spare X account. Scweet's README (opens in a new tab) asks for a dedicated account, never your personal one, because X can lock any account it flags.

  2. Copy its cookies. Log in at x.com, open the browser's developer tools and copy auth_token and ct0 from the site's cookies.

  3. Add the account and search. twscrape (opens in a new tab) keeps accounts and sessions in a local SQLite file and returns parsed posts.

    Python
    import asyncio
    from twscrape import API, gather
    
    COOKIES = "auth_token=xxx; ct0=yyy"
    
    async def main():
        api = API()  # accounts and sessions go to accounts.db
        await api.pool.add_account_cookies("spare_account", COOKIES)
        query = "from:XDevelopers lang:en"
        posts = await gather(api.search(query, limit=40))
        for post in posts:
            print(post.id, post.user.username, post.rawContent[:60])
    
    asyncio.run(main())
    
  4. Add accounts and proxies for volume. twscrape tracks rate limits per account and per operation, parks a limited account until its reset and moves to the next one. Account timelines stop at about 3,200 posts.

Good to know

An auth_token cookie works like a password: anyone holding it is logged in as that account until the session ends. Keep it out of code, repositories and shared notebooks, and never put a personal account's cookies into a script.

Most libraries from before 2024 no longer work. On November 2, 2026, the two maintained ones both needed X accounts:

LibraryLast updateStatus
twscrape0.20.1, Aug 25, 2026Maintained; runs on logged-in X accounts
Scweet5.8.2, Oct 22, 2026Maintained; runs on an auth_token cookie
twikit2.3.3, Feb 7, 2025No release in 20 months; 160 open issues
snscrapeJun 22, 2023Twitter module failing since June 30, 2023 (opens in a new tab)
TwintFeb 23, 2023Archived on GitHub
  • twscrape

    Last update
    0.20.1, Aug 25, 2026
    Status
    Maintained; runs on logged-in X accounts
  • Scweet

    Last update
    5.8.2, Oct 22, 2026
    Status
    Maintained; runs on an auth_token cookie
  • twikit

    Last update
    2.3.3, Feb 7, 2025
    Status
    No release in 20 months; 160 open issues
  • snscrape

    Last update
    Jun 22, 2023
  • Twint

    Last update
    Feb 23, 2023
    Status
    Archived on GitHub

Hosted scraping tools

No-code scraping services do this collecting for you behind a form and bill per result, so the blocks and breakages become theirs, and their fixes lag behind X's changes. Twitter scrapers compared goes through them tool by tool.

#Read posts through the official X API

The official X API sells public posts as prepaid reads: $0.005 per post and $0.010 per user or follower, with pay-per-use capped at 3 million post reads a month, according to its pricing page (opens in a new tab).

From November 22, 2026, X also bills the author profiles and media that come attached to a post at the same rates (X's notice (opens in a new tab)), so a post read with its author costs $0.015.

  1. Create a developer app. Sign in at console.x.com with an X account, accept the Developer Agreement, create an app and copy its Bearer token. Our guide on how to get a Twitter API key goes click by click.

  2. Buy credits. Every read draws on a prepaid balance, and requests fail once it runs out.

  3. Search recent posts. Recent search covers the last 7 days, up to 100 posts per request; full-archive search back to 2006 is open to pay-per-use accounts.

    Terminal
    curl -G "https://api.x.com/2/tweets/search/recent" \
      -H "Authorization: Bearer $X_BEARER_TOKEN" \
      --data-urlencode "query=from:XDevelopers -is:retweet" \
      --data-urlencode "max_results=100"
    

It is X's own route, and the only one here that can also post. At $5.00 per 1,000 posts, a million search results cost $5,000, and the 3 million cap ends the month's reads; our breakdown of X API pricing lists every rate.

#What scraping Twitter costs per 1,000 posts

Per 1,000 posts, the official X API charges $5.00 and Sorsa API from $0.07 by search or $0.014 by ID; the scraping ways charge no fee and spend X accounts, proxies and repair hours instead.

Posts collected

Official X API

$5,000

for 1M posts

$0.005 per post

Sorsa API

from$70

for 1M posts

from $0.07 per 1,000 by search

For collecting posts every day, use Sorsa API: a million search results cost from $70 against $5,000 on the official X API, at 20 requests per second, about 400 results a second, with no X account to lose.

Four criteria separate the ways: the price per 1,000 posts, whether an X account is at stake, how much of X the way reaches and what breaks it.

WayPer 1,000 postsX account at stakeReachesBreaks when
Sorsa APIfrom $0.07 by search, $0.014 by IDNoneSearch back to 2006, timelines, posts by ID, profiles, followers, repliesStable response schema; your code stays the same
Official X API$5.00, up to $15.00 with authorsThe developer accountSearch, timelines, lookups; 3 million posts a monthX changes prices or rules
Libraries on X accountsNo fee; accounts and proxiesEvery account in the poolSearch, timelines, followersA query ID or feature flag changes
Logged-out browserNo feeNoneOne post, a profile's first postsThe page changes or a block hits
Hosted scraping toolsSet by each toolDepends on the toolWhat its browser or accounts reachThe tool's fixes lag behind X
  • Sorsa API

    Per 1,000 posts
    from $0.07 by search, $0.014 by ID
    X account at stake
    None
    Reaches
    Search back to 2006, timelines, posts by ID, profiles, followers, replies
    Breaks when
    Stable response schema; your code stays the same
  • Official X API

    Per 1,000 posts
    $5.00, up to $15.00 with authors
    X account at stake
    The developer account
    Reaches
    Search, timelines, lookups; 3 million posts a month
    Breaks when
    X changes prices or rules
  • Libraries on X accounts

    Per 1,000 posts
    No fee; accounts and proxies
    X account at stake
    Every account in the pool
    Reaches
    Search, timelines, followers
    Breaks when
    A query ID or feature flag changes
  • Logged-out browser

    Per 1,000 posts
    No fee
    X account at stake
    None
    Reaches
    One post, a profile's first posts
    Breaks when
    The page changes or a block hits
  • Hosted scraping tools

    Per 1,000 posts
    Set by each tool
    X account at stake
    Depends on the tool
    Reaches
    What its browser or accounts reach
    Breaks when
    The tool's fixes lag behind X

Of the five ways, only Sorsa API reaches search, timelines and followers with no X account of yours at stake, and it does so from $0.07 per 1,000 posts.

Yes, for public data. In hiQ Labs v. LinkedIn, the Ninth Circuit held in April 2022 that scraping public profiles was likely not access "without authorization" under the Computer Fraud and Abuse Act, and in May 2024 a federal court dismissed X's lawsuit against Bright Data over scraping public posts.

Three habits keep a scraping project clean: collect public data only, never protected accounts or private messages; keep what the job needs and no longer; and credit the author when you republish a post, since the copyright stays with them.

Through an API, your code never signs in to x.com, so no X account of yours is at risk: Sorsa API never asks for your X login or cookies. More in our guide on whether a third-party Twitter API is legal.

#Get your first 2,000 posts out today

Scraping X in 2026 means a login wall, accounts at risk and query IDs that change about every 10 days. To get public posts out without either, use Sorsa API: one key, about 20 search results per request from $0.07 per 1,000, tweets by ID from $0.014 per 1,000, and 100 free requests that cover the first 2,000 posts.

#FAQ

Can you scrape Twitter without logging in?

Only a little. On November 2, 2026, a logged-out visit to x.com returned single posts with their text and counts and the first 9 posts of a profile, while search and follower lists redirected to the login page. More data needs a logged-in account, which puts that account at risk, or an API that returns public posts with a key.

Is snscrape still working in 2026?

No. snscrape's Twitter module has failed since June 30, 2023, when X put its pages behind a login wall, and the project's last release dates from June 22, 2023. Its maintained successors, twscrape and Scweet, shipped new versions in August and October 2026, and both need logged-in X accounts to read search, timelines or followers.

Can you scrape Twitter followers?

Not logged out: x.com sends follower and following lists to the login page, and libraries that read them run on X accounts that X can lock. Libraries read them with X account cookies. Sorsa API's GET /followers returns up to 200 followers per request with no X account at risk, from $0.007 per 1,000, and our guide to export Twitter followers shows the full loop.

Is there a free way to scrape Twitter?

Not a free and lasting one. A browser and the libraries charge no fee but spend X accounts, proxies and repair time. The official X API has no free tier. Every Sorsa API account starts with 100 free requests, about 2,000 search results or up to 10K tweets by ID, with no card, and they never expire.

Which API should I use instead of scraping Twitter?

Use Sorsa API, a Twitter (X) API and scraper: it returns posts, profiles and followers as JSON with one key, from $0.07 per 1,000 search results and $0.014 per 1,000 tweets by ID, against $5.00 per 1,000 posts on the official X API. It needs no developer account, never asks for your X login, runs at 20 requests per second on every plan and searches back to 2006.

#How we checked

On November 2, 2026, we opened a post, a profile, search and a follower list on x.com logged out in a desktop browser and recorded what each returned, then loaded the same post and profile once in a default headless browser on a server. We pulled all 112 snapshots of the TwitterInternalAPIDocument tracker from November 6, 2025 to October 31, 2026 and counted the query ID changes of each operation. We read X's API pricing and search docs and the READMEs and release pages of twscrape, Scweet, twikit and snscrape. Every Sorsa API endpoint and field here matches the live API reference; we did not run the official X API sample.

By the Sorsa API team. We build and run Sorsa API, the read-only Twitter/X API and scraper, in production since 2022 (formerly TweetScout API) with 6B+ requests served. About Sorsa API

What changed
  • Rewritten from scratch: what x.com shows logged out today, what breaks browsers and libraries, X's current prices, and code for the API routes in Python and Node.js.
  • First published.