Automate X Posts with Playwright and Node.js

mixer
Overview
This repository ships a single script, tweet.js, that opens X (Twitter) in Playwright, logs in automatically (or with your help), and publishes a post. It can run headless for fully automated flows or visible for the first manual login. Auth state is persisted to twitter-auth.json so you do not have to sign in on every run.

Why it is useful
  • Automates posting to X without using the public API or access tokens.
  • Works with chromium (default) or webkit; can run headless or with a visible browser.
  • Handles 2FA: reads a one-time code from env or generates TOTP from a secret.
  • Saves and reuses session state to avoid repeated logins.
  • Supports a manual-login mode to survive captchas or unusual prompts.

Quick start
1) Install dependencies and Playwright browsers:
git clone https://github.com/127/ixer
npm install && npx playwright install
2) Configure environment:
cp .env.example .env
Fill .env with:
TWITTER_USERNAME=your_login
TWITTER_PASSWORD=your_password
TWITTER_2FA_SECRET=your_totp_secret (optional for 2FA)
or a single-use code: TWITTER_2FA_CODE=123456

Running the script
Automatic login with credentials from .env:
TWEET_TEXT="Post via Playwright" npm run tweet
First run with manual login (if you expect captchas or verification):
MANUAL_LOGIN=true HEADLESS=false npm run tweet
log in in the opened browser, then press Enter in the terminal

Subsequent headless run using the saved session:
HEADLESS=true TWEET_TEXT="New post" npm run tweet
Key environment variables
TWEET_TEXT — post text (default: "Привет, X!").
BROWSER — chromium (default) or webkit.
HEADLESS — true|false; ignored when MANUAL_LOGIN=true (window stays visible).
MANUAL_LOGIN — true|false; enables manual sign-in before posting.
TWITTER_2FA_SECRET or TWITTER_2FA_CODE — allows automatic 2FA.

Session handling
After a successful login, Playwright stores cookies and tokens in twitter-auth.json. Keep this file alongside tweet.js to reuse the session. Delete it if you need to force a fresh login or rotate accounts.

Tips and safeguards
  • Prefer MANUAL_LOGIN=true for the very first run to confirm the UI path and handle any security prompts.
  • Do not commit .env or twitter-auth.json; they contain credentials and session data.
  • If X changes its UI, rerun with HEADLESS=false to watch the flow and adjust selectors if needed.
Back to articles

About

Explore Marat Mamyashev's blog for expert articles on programming, software development, and DevOps. Dive into practical guides on JavaScript, C++, mobile app development, neural networks, and more to enhance your tech skills.