Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
[Unreleased]
Fixed
Public reads work again, without a browser
Scraper.getProfile()returnedHTTP 404 {"message":"Query not found"}for every call. The repo carried two independent tables of X GraphQL query IDs, and 11 of the client's had gone stale while the shared map stayed current. Query IDs now have exactly one home (src/scrapers/twitter/http/endpoints.js), and a test fails if a second copy reappears.- The HTTP client could not obtain a guest token at all. X answers a request with no browser
User-Agentwith a misleadingHTTP 404 "Sorry, that page does not exist", which reads like a removed endpoint rather than a rejected client. Every request the client makes now carries one. xactions profileprintedFollowers: 0and exited 0. X stopped serving profile and timeline content to logged-out browsers, so the Puppeteer scrape found an empty page and the CLI reported the nothing it found as success.profile,tweets,followers,following,search, andnon-followersnow use the HTTP client, which is roughly an order of magnitude faster and needs no Chromium download.xactions non-followersreported your entire following list as non-followers. It filtered on afollowsBackflag the GraphQL follow lists do not carry, so the predicate matched everything. It now diffs the follower and following lists.- The MCP server answered AI agents with every field set to
null(issue #27).x_get_profileandx_get_tweetshad the same browser-path problem, which is worse in an agent context: an assistant cannot tell an empty result from a missing one, so it reports confidently wrong answers. Both now prefer the HTTP client and fall back to the browser. - Unauthenticated failures now say what to do. X restricts search, followers, likes, bookmarks, and DMs to logged-in sessions and answers a guest request with a bare
404. That surfaced asHTTP 404: Not Found, which sent people looking for a bug in XActions. It now raisesAUTH_REQUIREDnaming the endpoint and the fix. Errors also carryendpoint,httpStatus, andrateLimitReset, which positional constructor calls had been silently dropping. xactions loginnow capturesct0as well asauth_token. Without the CSRF token X treats the session as logged out, so session-tier endpoints kept failing after an apparently successful login.
Paid API
- Every
/api/ai/*endpoint returned500instead of402.@x402/corev2 moved payment terms behind anacceptskey; the flat v1 route shape made the SDK throw during route validation on every request. All 95 payment tests now pass against a live server.
Cross-platform
- Every Bluesky scrape threw
Cannot read properties of undefined (reading '_client'). The XRPC helper detached the SDK method from its namespace before calling it. Profiles, posts, and follower lists all work again. - Mastodon bios and posts contained raw HTML entities (
&,') after tag stripping.
Tests
tests/mcp/server.test.jsnever ran. It importeddescribe/itfromnode:test, which registers with Node's runner rather than Vitest, so the file reported "No test suite found" and all 144 tool definitions went unvalidated.tests/x402-integration.test.jsfailed for every contributor. Its skip condition was inverted: it skipped in CI and ran on laptops, so a clean checkout produced 21 redECONNREFUSEDfailures. It now probes for a server and skips when there is not one.- Two A2A tests asserted a hardcoded
3.1.0against the real version.
Added
Examples and tutorials
examples/— 8 runnable programs, each verified against the live API before release: profile lookup, timeline analysis, offline sentiment reports, a three-network comparison, CSV export, non-follower analysis, a keyword monitor, and an MCP client that drives the server over stdio.tutorials/— four guided walkthroughs: first scrape, MCP with Claude, cleaning up a following list, and building a brand monitor.
Documentation that cannot rot
npm run docs:checkfails on a dead relative link, a dead heading anchor, a referenced script that no longer exists, a stale version claim, a wrong MCP tool count, or a documented CLI command that does not exist. It is dependency-free and runs as its own CI job. It found 87 dead links, 25 stale version and tool-count claims, and 11 invented CLI commands on its first run; all are fixed.npm run docs:scriptsregenerates the browser-script catalog from the scripts themselves, so a 93-entry list cannot drift.npm run check:endpointsprobes every GraphQL endpoint and distinguishes a rotated query ID from an endpoint that merely needs a session, which is the failure that silently broke the client above.- Five docs the index had promised but never had: browser-scripts, configuration, database, skills, troubleshooting.
40 new browser tools, and the Command Center now covers 108
- Added a full wave of browser-console tools so the toolkit covers essentially every X action, and folded them all into the Command Center (now 108 tools across 11 categories, with two new categories: Create & Post and Lists):
- Create & Post: post a tweet, post a thread, schedule a post, create a poll, quote tweet, pin/unpin.
- Posting actions: auto-repost, auto-reply to mentions, vote in polls, and bulk-delete your own posts by age/keyword/engagement (dry-run by default).
- Scrape everything: followers, following, post likers, reposters + quote-tweeters, a user's likes, search results, a hashtag, a List, profile media, tweet replies, notifications, DMs, and Spaces. Each exports JSON + CSV.
- Lists: create/rename/delete a List, add users to a List, follow all List members.
- DMs & account: bulk/welcome DM, auto-reply DMs, edit full profile, privacy/settings toggles, manage muted words, notification cleaner.
- Grow & moderate: follow-back everyone, remove a follower (dry-run), block-list import/export + block-chaining (dry-run).
- Diagnostics: shadowban checker, tweet performance ranking, sentiment analyzer, audience overlap, trending monitor.
- Every new tool follows the same conventions as the rest: real
data-testidDOM automation (no fragile hardcoded API IDs), randomized rate limiting, awindow.stop<Tool>()switch on long loops, page guards, and JSON/CSV export on the scrapers. Bulk/irreversible tools default to a dry run. - Docs: each tool gets its own page at
/scripts, plus a Command Center tutorial (docs/examples/tutorials/command-center-tutorial.md).
Build fix
- Fixed a Command Center bundler bug where a tool containing a
$-anchored regex template literal (e.g.`/${x}/?$`) corrupted the generated file,String.replacewas interpreting the `$`` sequence as a special replacement pattern. The injector now uses a function replacer.
⚡ XActions Command Center: one script for every tool
- New
scripts/twitter/xactions-command-center.js: paste one script into the browser console and get a searchable command palette of all 68 browser tools, no more hunting for the right file. Search and arrow-key navigation, nine categories (Scrape, Analytics, Grow, Engage, Clean Up, Moderate, Communities, Profile, Utilities), favorites and recents, and a per-tool options form (rendered from each tool's own config, with an "Edit as JSON" mode) so you never edit source by hand. - Safety built in: every tool is tagged Safe / Writes / Bulk-irreversible, destructive tools require a second confirming click and show a warning, the palette tells you which page each tool expects (and warns if you're not on it), and a run dock lets you Stop long-running tools individually or all at once.
- Works within x.com's strict CSP: it bundles every tool directly (no remote fetch, no
eval). Reopen anytime with the floating ⚡ button or Cmd/Ctrl+K. - Generated by a new build (
scripts/build-toolkit.mjs+_command-center-shell.js) that stays in sync with the tool files and fails the build on any drift. Docs:scripts/twitter/README-command-center.md.
Fixed
Browser scripts: re-paste crash fixed repo-wide
- Converted the remaining 40 tools that still declared a top-level
const CONFIGtovar CONFIG. Pasting a script a second time into the same DevTools tab threwIdentifier 'CONFIG' has already been declaredand the script never ran, breaking the documented "run it again later" workflow. This finishes the fix an earlier pass started on part of the collection; every tool now re-pastes cleanly.
[3.4.0] - 2026-07-20
Fixed
Hosted API server crash on boot
api/routes/teams.jsdefault-importedauthMiddlewarefrom a module that only has named exports — in ESM that's a hardSyntaxErrorat startup, not a warning, so the hosted API server crashed before it could ever answer a health check. This is why xactions.app's dashboard pages (graph, analytics, unfollowers, admin, price-correlation) were showing "backend offline." Fixed and verified with a full local Docker build + boot against a real Postgres container: server starts cleanly, migrations run,/api/health, register, login, and authenticated reads all respond correctly. Swept the wholeapi/,src/, andworker/tree for the same class of bug — no other instances found.
Browser console scripts: 64 files audited
- Every script in
scripts/twitter/(beyond the two already rewritten) was read end-to-end and fixed where real bugs were found. Highlights: all scripts using top-levelconst CONFIGbroke on re-paste into an already-open DevTools console (aSyntaxError, sinceconst/letbindings persist across console pastes in the same tab) — fixed tovareverywhere. Added consistentwindow.stopX()abort switches to every long-running loop that lacked one. Fixed stale-DOM bugs inmass-unblock.js/mass-unmute.js(cached elements pointing at rows already removed from a virtualized list), a wrong-author-attribution bug on quote-tweets inbookmark-exporter.js, a duplicate-processing risk in the hashtag/location commenters, severalwindow.location.hrefreloads that silently killed the running script mid-workflow, and wired up half-implemented options (filters, reply templates, video quality selection) that were declared but never actually checked.
Added
Google Cloud Run deployment for the hosted API
deploy/gcp/provision-api.sh+deploy/gcp/cloudbuild-api.yaml: one-shot provisioning (Cloud SQL Postgres, Secret Manager, IAM) and build/deploy for thexactions-apiCloud Run service, reusing the existing Memorystore Redis instance instead of standing up new infra.api/services/jobQueue.js's Bull queue now namespaces its Redis keys so it can safely share that instance.
Cloudflare Workers Deployment
- Full-site Cloudflare deploy: one Worker serves the landing page, dashboard, docs, blog, and static assets from Workers static assets, replacing the Vercel deployment
- Edge API in the Worker:
/api/health,/api/ai/health,/api/ai/pricing,/openapi.json,/.well-known/x402, and the x402 402 payment gate for/api/ai/* API_ORIGINproxy: heavy API routes (auth, user, unfollowers, video) forward to the Node backend on Railway/Fly/Docker; a clear 503 with setup instructions when unsetnpm run build:cloudflareassemblesdist-cloudflare/fromsite/,dashboard/,public/, andllms*.txt, mirroring thevercel.jsonroute tablenpm run deploy:cloudflarebuilds and deploys viawrangler deploy
Browser extension install page + extension-first account actions
- New
/extensionpage: what the extension does, a 30-second load-unpacked install guide (Chrome/Edge/Brave/Firefox), all 11 automations, and why it runs locally (your X login never leaves your browser) - Wired into the integrations page, footer, and sitemap
- Hosted service no longer executes X account actions server-side: follow/unfollow/like/reply/post routes return
501pointing to the extension, so the service never custodies your session token or drives your account from a datacenter. Paid reads (scrape, analytics) are unaffected
[3.3.0] - 2026-07-19
Improved
Site-wide visual glow-up (X.com-clone kept)
- Enhanced the shared styling (common.css, components.css, docs.css, the injected sidebar) so ~400 pages level up at once: accent gradient + glow, depth shadows, active-nav gradient pill, glowing buttons, card hover lift, refined badges/tabs/inputs/code, ambient background glow, and load-in motion. Layout and blue identity unchanged.
- Landing page and every app page got the same treatment in their own styles.
Fixed
- App pages (agent, graph, monitor, analytics, thread, video, login, admin, team, unfollowers, price-correlation, and more) now degrade gracefully when the hosted API is offline: designed "backend offline" notices and empty states instead of infinite spinners or console error floods. Stopped runaway polling and socket reconnection. Fixed a broken element id, a stuck loading overlay, and graph's cross-origin CORS calls (now same-origin).
- Docs pages that embedded full script source no longer run 20,000px tall (long code scrolls in a capped box).
- Footer column headings no longer render inline with their first link.
- Repaired every broken documentation cross-link (664 .md links plus repo-file links) and rebuilt the sitemap from 47 stale URLs to 535 real ones.
[3.2.2] - 2026-07-19
Added
xactions.app is live again, on Cloudflare Pages (free)
deploy/cloudflare/: build script +_redirectsdeploying the full site (landing page, dashboard app, docs, tutorials, blog, scripts directory) to Cloudflare Pages, free of charge (the prior Vercel deployment was disabled and the domain has been down)- Live now at the Pages project URL;
xactions.appcustom domain pending the nameserver switch to Cloudflare at the registrar deploy/gcp/(Cloud Run + nginx) kept as a fallback path for environments without Cloudflare access
[3.2.1] - 2026-07-19
Fixed
Browser script audit (103 bugs across 52 files)
- Full audit of every paste-in-console script in
scripts/twitter/; report indocs/audits/2026-07-19-browser-scripts.md - Fatal bugs: 6 scripts killed themselves by navigating mid-run; 3 infinite loops; an action script that liked/followed whatever page was open; blind menu clicks that could trigger unintended actions
- Correctness: quoted-tweet ID misattribution (9 scripts), locale-dependent repost/reply detection (8), K/M/B engagement multiplier and NaN bugs, CSV corruption from unquoted dates, React value-tracker bugs that made update-bio and DM sending silently no-op, wrong-DM-recipient matching, false clipboard success claims
- Reliability: end-of-list stall detection that never fired, missing
videoComponentselectors, unrevoked Blob URLs, setInterval re-entrancy src/cli/index.js:awaitin a non-async SIGINT handler crashed the whole CLI on load
Added
Cloud Run deployment for xactions.app
deploy/gcp/: Dockerfile, nginx config, and Cloud Build pipeline serving the landing page, dashboard, docs, tutorials, and blog with the same clean-URL routing the Vercel deployment had (Vercel deployment is disabled and the domain has been down)
[3.2.0] - 2026-07-19
Added
Scraper Toolbox (browser console)
scripts/twitter/scraper-toolbox.js: interactive on-page control panel for scraping any X timeline (profile, search, list, likes, bookmarks, home)- Start / pause / resume / stop, live progress, draggable panel, settings persisted in localStorage
- Captures X's own GraphQL responses: exact like/repost/reply/view/bookmark counts, full text of long posts, media URLs, language codes; promoted posts skipped
- Live filters applied at export time: keywords (include/exclude), only/skip specific users, min likes/reposts/views, date range, repost/reply/quote/pinned toggles, media, language
- Exports: JSON, CSV, Markdown, TXT, HTML downloads plus clipboard copy (JSON or clear text)
- Console API:
window.XActionsToolbox - Docs:
scripts/twitter/README-scraper-toolbox.md
Fixed
scrape-profile-posts.js (v2.1.0)
- Elapsed time was reported 3x too small (divided by 3000 instead of 1000)
- HTML export table rendered at 300% width; text export separators were 300 chars wide
- Tweet IDs could be attributed to a quoted tweet's URL instead of the post itself
- Pinned posts were counted as reposts; repost/reply detection no longer depends on the English UI
- End-of-timeline detection never triggered when
verbose: false - Video attachments using the newer
videoComponenttestid were not detected
[3.1.0] - 2026-02-25
Added
Plugin System
- Community plugin architecture — create
xactions-plugin-*npm packages - Plugin loader, manager, and template in
src/plugins/ - CLI commands:
xactions plugin install/list/remove - MCP server auto-discovers and registers plugin tools
Real-Time Streaming
- Live event streams for tweets, followers, and mentions via Socket.IO
- Puppeteer-based polling with Redis deduplication and rate limit backoff
- Browser pool management (max 3 concurrent instances)
- MCP tools:
x_stream_start,x_stream_stop,x_stream_list
Workflow Engine
- Declarative JSON automation pipelines with triggers, actions, and conditions
- Cron scheduling, webhook triggers, event-based triggers
- 3 example workflows: competitor monitor, auto-engage keywords, follower growth report
- CLI:
xactions workflow create/run/list - MCP tools:
x_workflow_create,x_workflow_run,x_workflow_list
Cross-Platform Scrapers
- Unified scraper interface:
scrape(platform, type, options) - Bluesky support via AT Protocol (@atproto/api) — no Puppeteer needed
- Mastodon support via public REST API — any instance URL
- Threads support via Puppeteer
- Backward compatible — existing Twitter imports unchanged
Sentiment Analysis & Reputation Monitoring
- Built-in rule-based sentiment analyzer (works offline, zero dependencies)
- Optional LLM mode via OpenRouter for nuanced analysis
- Reputation monitoring with trend detection and anomaly alerts
- Alert delivery via webhook, Socket.IO, or console
- Daily/weekly reputation reports
Account Portability
- Full account export: profile, tweets, followers, following, bookmarks, likes
- Output formats: JSON, CSV, Markdown, self-contained HTML archive viewer
- Export diff tool — compare two snapshots to see changes
- Migration stubs for Bluesky and Mastodon
Social Graph Analysis
- Graph builder crawls N degrees from seed account
- Algorithms: mutual connections, bridge accounts, cluster detection, influence scoring
- Exports to D3.js JSON and Gephi GEXF formats
- Self-contained HTML visualization with force-directed layout
Browser Extension
- Manifest V3 Chrome/Firefox extension
- Popup UI to run automations without console access
- Content script injection, settings persistence, activity badge
Dashboard Enhancements
automations.html— automation control panel with start/stop togglesmonitor.html— real-time activity feed with Chart.js visualizationsworkflows.html— visual workflow builderanalytics.html— sentiment timeline, mention analysis, alert configuration- Full docs site generated at
dashboard/docs/
New API Routes
/api/streams— real-time stream management/api/workflows— workflow CRUD and execution/api/analytics— sentiment analysis and monitoring/api/portability— account export and migration/api/graph— social graph building and analysis/api/automations— automation start/stop control- 15+ additional routes for bookmarks, discovery, engagement, posting, etc.
New Browser Scripts
engagementBooster.js— systematic engagement with target accountssentimentAnalyzer.js— in-browser sentiment scoringshadowbanChecker.js— detect account restrictionsviralTweetDetector.js— find viral content earlyfollowerGrowthTracker.js— track growth over timetweetScheduleOptimizer.js— find best posting timeswelcomeNewFollowers.js— auto-welcome with templatesquoteTweetAutomation.js— strategic quote tweetingthreadComposer.js— multi-tweet thread buildercontentCalendar.js— plan and schedule contentaudienceDemographics.js— analyze follower demographicsaccountHealthMonitor.js— monitor account health signalspinTweetManager.js— manage pinned tweetsbulkDeleteTweets.js— mass delete old tweetsautoReply.js— automated reply with templates
Other
- TypeScript type declarations (
types/index.d.ts) - Docker support (Dockerfile + docker-compose)
- New npm exports:
xactions/streaming,xactions/analytics,xactions/plugins xactions-mcpandxactions-agentbin commands
Changed
- MCP server expanded from ~200 to 140+ registered tools
- Package exports updated for multi-platform scraper paths
- Dependencies updated: vitest 4.x, puppeteer 24.x, added node-cron, better-sqlite3, exceljs
[1.0.0] - 2026-02-11
Added
- Initial release