x-bridge
[ github ]

Scrape x.com using your own browser.

A Tampermonkey userscript captures X's own GraphQL responses in a logged-in tab and exposes them over localhost. No headless browsers, no reverse-engineered auth, no API keys.

Why this exists

In March 2026, x.com stopped shipping the ondemand.s.<hash>.js file that most Python-side X scrapers parsed to generate the client transaction id required for authenticated GraphQL calls.

The libraries aren't abandoned and the authors aren't at fault. The token-derivation pipeline they depended on no longer exists in the wire protocol. Reproducing it server-side means emulating a moving target.

x-bridge takes the other path. If the real browser already has the token, let the real browser do the request. A userscript listens to the fetches x.com is making anyway, forwards their responses to a local Python service, and exits the auth-replication arms race entirely.

"The browser is the SDK."

How it works

01

You open a pinned tab.

A Chrome tab logged into x.com, parked at /home?bridge=1. The userscript activates on that URL only.

02

The script intercepts GraphQL.

Every response from x.com's own fetches is cloned in-place and posted to the bridge at 127.0.0.1:8787.

03

Python reads from localhost.

When you hit /search, the bridge tells the tab to run a query and returns the captured JSON.

$ terminal [ copy ]
$ curl -s 'http://127.0.0.1:8787/search?q=postgres&count=20' | jq .
{
  "query": "postgres",
  "count": 20,
  "results": [
    {
      "id": "1781...",
      "author": "@rhaas",
      "text": "The planner now folds SRFs in the target list when...",
      "created_at": "2026-04-17T09:12:04Z",
      "metrics": { "likes": 142, "replies": 8, "retweets": 31 }
    },
    ...
  ],
  "cursor": "DAABCgABGZ...",
  "captured_at": "2026-04-18T22:04:11Z"
}

Install

$ tampermonkey [ copy ]
# Option A: Install from Greasy Fork
https://greasyfork.org/en/scripts/574864-x-bridge-claw

# Option B: Tampermonkey > Utilities > Install from URL
https://raw.githubusercontent.com/Bug-Finderr/x-bridge/main/x-bridge.user.js
$ bridge [ copy ]
$ git clone https://github.com/Bug-Finderr/x-bridge
$ cd x-bridge/service
$ pip install -r requirements.txt
$ python main.py
# bridge listening on 127.0.0.1:8787

Requires one Chrome tab signed into x.com and pinned to /home?bridge=1. Close the tab and the bridge reports tab_unavailable; no background automation, no headless fallback.

API

methodpathpurpose
GET /search Run a keyword query, return captured tweets.
GET /replies/{id} Fetch the reply tree for a given tweet id.
GET /queries List queries the tab is currently driving.
POST /captured Internal. Userscript posts intercepted responses here.
POST /abort Cancel an in-flight query and release the tab.
GET /debug/recent Last 50 captured payloads, newest first.

Maintained by an agent

This repo is autopatched by an OpenClaw agent when x.com drifts. Patch versions (0.3.x) are machine-authored; minor and major bumps stay human.