Skip to content

fa0311/twitter_api_safe_relay

Repository files navigation

twitter-api-safe

twitter-api-safe is a TypeScript monorepo for sending Twitter/X Web App API requests through a logged-in browser.

The workspace contains five main entry points:

The core idea is simple: X.com already has an authenticated Web App API client running in the browser. This project injects a small bridge into that page and lets requests run through that live client instead of reimplementing cookies, CSRF handling, auth state, feature flags, and request behavior in Node.js.

flowchart LR
	app["Your Node.js app"]
	extension["WXT browser extension"]
	curl["HTTP client"]
	agent["AI agent (MCP client)"]
	server["twitter-api-safe-relay"]
	mcp["twitter-api-safe-mcp"]
	package["twitter-api-safe-request"]
	wxt["twitter-api-safe-wxt"]
	xclient["X Web App<br/>internal API client"]

	app -->|"call package"|package
	extension -->|"call package"|wxt
	curl -->|"HTTP request"|server
	agent -->|"MCP"|mcp
	server -->|"call package"|package
	mcp -->|"call package"|package
	package -->|"browser bridge"|xclient
	wxt -->|"MAIN world bridge"|xclient
Loading

Use the package directly

Use twitter-api-safe-request when you already have a Playwright browser/page and do not need an HTTP server.

pnpm add twitter-api-safe-request playwright

If needed:

pnpm exec playwright install
import { chromium } from "playwright";
import { createTwitterBrowser } from "twitter-api-safe-request";

const context = await chromium.launchPersistentContext("./user_data/account1", {
  headless: false,
});

const page = await context.newPage();
const client = createTwitterBrowser(page);

await client.inject();
await client.goto("https://x.com/home");

const result = await client.dispatch({
  method: "GET",
  path: "/2/users/me",
  params: {},
});

Package README: packages/request/README.md

npm package page: twitter-api-safe-request

Use from a WXT browser extension

Add the module to wxt.config.ts:

export default defineConfig({
  modules: ["twitter-api-safe-wxt/module"],
});

Create the browser client from a document_start content script:

import { createTwitterBrowser, TWITTER_MATCHES } from "twitter-api-safe-wxt";

export default defineContentScript({
  matches: [...TWITTER_MATCHES],
  runAt: "document_start",
  allFrames: false,
  async main(ctx) {
    const client = createTwitterBrowser(ctx);
    await client.inject();
    await client.waitStartup();
    const result = await client.dispatch({
      method: "GET",
      path: "/2/example",
      params: {},
    });
    console.log(result);
  },
});

Package README: packages/wxt/README.md

npm package page: twitter-api-safe-wxt

Runnable example: examples/basic

Use the HTTP relay

Use twitter-api-safe-relay when another process should call the X Web App API over HTTP.

Once the relay is running, replace the X.com origin with the relay origin and keep the path/query/body shape:

You do not need to provide Cookie, CSRF, or x-client-transaction-id yourself; the relay adds those headers automatically.

https://x.com/i/api/graphql/{queryId}/{operationName}?...
http://localhost:3000/i/api/graphql/{queryId}/{operationName}?...

For example:

curl 'http://localhost:3000/i/api/graphql/gKia-nBM9kwuDEfSDeWMfQ/HomeTimeline'

Server README: packages/server/README.md

npm package page: twitter-api-safe-relay

Use from AI agents (MCP)

twitter-api-safe-mcp runs the full relay server (HTTP API + dashboard) and serves MCP in a single process. It exposes list_profiles and twitter_api_request tools.

claude mcp add twitter-api-safe -- pnpx twitter-api-safe-mcp ./settings.json

Package README: packages/mcp/README.md

npm package page: twitter-api-safe-mcp

Use from AI agents (Agent Skills)

twitter_api_safe_relay_skills provides Agent Skills for Claude Code and other agents, letting an AI turn natural-language instructions into relay-server GraphQL / v1.1 calls and summarize the results.

npx skills add fa0311/twitter_api_safe_relay_skills

Start the relay server, then point the skill at it with the TWITTER_RELAY_BASE_URL environment variable. The agent only sees the operation catalog — it never touches cookies, CSRF tokens, or other credentials directly.

Configuration

Configure the relay in the workspace-level settings.json.

{
  "port": 3000,
  "logger": {
    "level": "info"
  },
  "profiles": [
    {
      "name": "account1",
      "browser": {
        "type": "launch",
        "userDataDir": "./../../user_data/account1",
        "headless": false
      }
    }
  ]
}

Each profile uses either:

  • launch: Playwright opens a persistent browser profile. Sign in to X/Twitter on first launch.
  • cdp: the relay connects to an already-running Chromium browser over the Chrome DevTools Protocol.

Docker

Images are published to ghcr.io/fa0311/twitter_api_safe_relay. Every image has two tags: latest-<name> and <version>-<name>, where <version> is the npm package version (for init-profile, a build hash instead).

Tag (<name>) Contents
relay Relay server with bundled Chromium, for launch profiles.
relay-slim Relay server without a browser, for cdp profiles connecting to an external browser.
relay-firefox Relay server with bundled Firefox.
relay-webkit Relay server with bundled WebKit.
mcp MCP server (runs the relay + MCP) with bundled Chromium.
mcp-slim MCP server without a browser, for cdp profiles connecting to an external browser.
mcp-firefox MCP server with bundled Firefox.
mcp-webkit MCP server with bundled WebKit.
init-profile Helper that resets lock files and permissions on the browser profile volume.

The compose example in docker/ runs the relay with the debug dashboard enabled, using relay-slim connected over CDP to a kasmweb Chromium container, with init-profile preparing the shared profile volume.

docker compose -f docker/docker-compose.yml up

Open the browser UI at http://localhost:6901, sign in to X/Twitter, then call the relay or dashboard on http://localhost:6900.

Local development

pnpm install
pnpm build
pnpm dev:relay

This starts the relay server and the Vite UI.

If you use a launch profile and do not already have the browser installed:

pnpm exec playwright install chromium

Tests

pnpm --filter twitter-api-safe-relay-dashboard test
pnpm --filter twitter-api-safe-request test
pnpm --filter twitter-api-safe-relay test

About

A TypeScript monorepo for calling the internal Twitter/X Web App API client from a logged-in browser opened with Playwright.

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages