⚡ XActions
📖 Guides & Reference

Configuration

XActions is configured in four places, and which ones you need depends entirely on which surface you use.

Surface Configuration needed
Browser console scripts None. Edit the CONFIG block in the script.
CLI ~/.xactions/config.json, written by xactions login.
Node.js library Cookies passed in code, or X_AUTH_TOKEN / X_CSRF_TOKEN.
MCP server Environment block in your AI client's MCP config.
Self-hosted API and dashboard .env.

Only the last one needs a .env file at all. Copy .env.example if you are running the server.


Session cookies

Everything that reads private or session-tier data needs two cookies from a logged-in x.com session.

Where to get them: open x.com, log in, then DevTools (F12) → ApplicationCookieshttps://x.com.

Cookie What it is Required
auth_token Your session. Treat it like a password. yes
ct0 CSRF token X requires as a request header. yes

Both are required. With only auth_token, X still treats the request as logged out, and search, followers, likes, bookmarks, and DMs all answer 404. This is the single most common configuration mistake.

CLI

npx xactions login

Prompts for both and writes ~/.xactions/config.json:

{
  "authToken": "...",
  "csrfToken": "..."
}

xactions logout removes it.

Library and examples

export X_AUTH_TOKEN=...
export X_CSRF_TOKEN=...

or in code:

import { Scraper } from 'xactions/client';

const scraper = new Scraper();
await scraper.setCookies(`auth_token=${authToken}; ct0=${csrfToken}`);

A full cookie jar exported from the browser also works and is preferred when you have one, because it carries everything X expects:

await scraper.loadCookies('./cookies.json');   // [{ "name": "auth_token", "value": "..." }, ...]
await scraper.saveCookies('./cookies.json');   // persist a refreshed session

MCP server

Set them in the env block of your AI client's MCP configuration, not in a .env file. MCP servers are spawned with a minimal environment:

{
  "mcpServers": {
    "xactions": {
      "command": "npx",
      "args": ["-y", "xactions-mcp"],
      "env": {
        "XACTIONS_SESSION_COOKIE": "your_auth_token",
        "XACTIONS_CSRF_TOKEN": "your_ct0"
      }
    }
  }
}

Without them the server still starts and still serves all 144 tools; the guest-tier ones (profiles, public timelines) work and the rest report that they need a session.

Keeping them out of your repo

.env, .env.local, and cookies.json are gitignored. A leaked auth_token is a full account takeover, so:

  • Never paste one into an issue, a screenshot, or a PR.
  • Log out of x.com in that browser to invalidate a token you think leaked.
  • Prefer a secondary account for automation.

Environment variables

Only relevant when self-hosting the API server or dashboard. Grouped by what they turn on; nothing here is needed for the CLI, the library, or console scripts.

Server

Variable Default Notes
NODE_ENV development production enables stricter startup checks.
PORT 3001 HTTP port.
API_URL http://localhost:3001 Public base URL, used in generated links.
FRONTEND_URL http://localhost:3000 Used for CORS and redirects.
CORS_ORIGINS localhost origins Comma-separated allowlist.
LOG_LEVEL info debug, info, warn, error.

Security

Variable Notes
JWT_SECRET Required in production. The server refuses to start without it.
SESSION_SECRET Required in production. Same.
ADMIN_API_KEY Guards the admin endpoints. Generate with openssl rand -hex 32.

Database and queue

Variable Notes
DATABASE_URL PostgreSQL connection string. See database.md.
REDIS_HOST / REDIS_PORT / REDIS_PASSWORD Backing store for the background job queue.

Scraping

Variable Notes
XACTIONS_SESSION_COOKIE auth_token value.
XACTIONS_CSRF_TOKEN ct0 value.
XACTIONS_MODE local (Puppeteer, free) or remote (hosted API).
XACTIONS_API_URL Endpoint used in remote mode.
XACTIONS_SCRAPER_ADAPTER puppeteer (default), playwright, or http.

Puppeteer

Variable Notes
PUPPETEER_HEADLESS true in servers, false to watch a run.
PUPPETEER_NO_SANDBOX Set true in Docker and when running as root.
PUPPETEER_EXECUTABLE_PATH Point at a system Chromium instead of the bundled one.

Optional integrations

Variable Enables
OPENROUTER_API_KEY LLM-backed sentiment mode and AI tweet generation.
TWITTER_CLIENT_ID / TWITTER_CLIENT_SECRET OAuth 2.0 login in the dashboard.
STRIPE_* Subscription billing.
X402_* Per-request payments on the hosted API. Documented inline in .env.example; verify a setup with npm run verify:x402.
SENTRY_DSN Error reporting.

Personas and niches

The autonomous agent reads two JSON files that decide what it talks about and how it sounds. Both live in config/ and are plain data, so adding your own is a matter of dropping in a file.

Personas — how the agent writes

config/personas/ ships three: thought-leader, technical-builder, community-builder.

{
  "name": "ThoughtLeader",
  "tone": "opinionated, visionary, contrarian but well-reasoned",
  "expertise": ["technology trends", "industry analysis"],
  "opinions": ["The next decade belongs to builders, not fundraisers"],
  "avoid": ["empty platitudes", "engagement farming", "corporate jargon"],
  "exampleTweets": ["..."]
}

avoid matters more than it looks. It is the difference between output that reads like a person and output that reads like a bot, and it is the first field worth editing.

Niches — what the agent looks at

config/niches/ ships ai-engineering, saas-startups, and web3-crypto.

{
  "name": "AI Engineering",
  "searchTerms": ["AI agents", "LLM engineering", "prompt engineering"]
}

The agent uses these to find accounts and posts worth engaging with, which is also how it trains your timeline algorithm toward a topic.

Agent settings

Copy config/agent-config.example.json to data/agent-config.json and edit, or run the wizard:

npx xactions agent setup

Console script settings

Browser scripts are configured in the script itself. Every one opens with a CONFIG block:

const CONFIG = {
  maxUnfollows: Infinity,
  whitelist: [],
  dryRun: true,       // Preview without acting — SET FALSE TO RUN
  delay: 2000,
};

dryRun defaults to true on everything destructive. See browser-scripts.md.


⚡ Free and open source

No API keys, no monthly fees, no signup. Star the repo if it saved you a subscription.

View on GitHub