Post Content -- Tutorial
Step-by-step guide to posting tweets with text, photos, GIFs, videos, and links using XActions browser scripts and Node.js/Puppeteer.
Prerequisites
- Logged into x.com in your browser
- Browser DevTools console (F12 -> Console tab)
- For Node.js usage:
npm install xactionsand a valid session cookie
Quick Start
- Navigate to x.com
- Open DevTools (F12)
- Copy the script from
src/postComposer.js - Edit the CONFIG section
- Paste into Console and press Enter
Two Approaches
Approach 1: Browser Console (Manual)
The simplest way to post is to use the compose dialog directly via DOM manipulation:
// Open the compose dialog
document.querySelector('[data-testid="SideNav_NewTweet_Button"]').click();
// Wait a moment, then type into the compose box
setTimeout(() => {
const textarea = document.querySelector('[data-testid="tweetTextarea_0"]');
textarea.focus();
document.execCommand('insertText', false, 'Hello from XActions!');
}, 1500);
To post the tweet, click the Post button:
document.querySelector('[data-testid="tweetButton"]').click();
Approach 2: Node.js / Puppeteer (src/postComposer.js)
The postTweet function automates the full flow using Puppeteer:
import { postTweet } from './src/postComposer.js';
// Simple text post
const result = await postTweet(page, 'Hello from XActions!');
// Post with an image and alt text
const result = await postTweet(page, 'Check out this photo!', {
media: '/path/to/image.jpg',
altText: 'A scenic mountain landscape at sunset',
});
// Reply to an existing post
const result = await postTweet(page, 'Great thread!', {
replyTo: 'https://x.com/user/status/123456789',
});
Configuration
The postTweet function accepts these options:
| Option | Type | Default | Description |
|---|---|---|---|
media |
string |
null |
Local file path to an image, GIF, or video |
altText |
string |
null |
Accessibility description for the media |
replyTo |
string |
null |
URL of the post to reply to |
Step-by-Step Guide
Posting Text
- The script navigates to
https://x.com/compose/tweet - It clicks the tweet textarea (
[data-testid="tweetTextarea_0"]) - Text is typed character by character with a 30ms delay to mimic human typing
- The tweet button (
[data-testid="tweetButton"]) is clicked - A 3-second wait ensures the post completes
Posting with Media
- After typing text, the script finds the file input (
[data-testid="fileInput"]) uploadFile()attaches the local file- A 2-second wait allows X to process the upload
- If
altTextis provided, the script clicks[data-testid="altTextInput"]and types the description
Posting with Links
Links are automatically detected by X when included in the tweet text. Simply include the URL in your text:
await postTweet(page, 'Check out this article https://example.com/article');
X will generate a link preview card automatically. The URL counts toward your character limit.
Quoting a Post
Use the quotePost function to add your commentary to an existing post:
import { quotePost } from './src/postComposer.js';
await quotePost(page, 'https://x.com/user/status/123456789', 'This is so insightful!');
Reposting
Use the repost function for a simple repost (no added commentary):
import { repost } from './src/postComposer.js';
await repost(page, 'https://x.com/user/status/123456789');
Tips & Tricks
- Character limit: Standard accounts have 280 characters. Premium accounts get 25,000.
- Rate limits: X enforces aggressive rate limits. Always include 1-3 second delays between posts.
- Media types: Supported formats include JPG, PNG, GIF (up to 15MB), and MP4 video (up to 512MB).
- Link previews: To suppress a link preview, place the URL at the very end and remove it after posting (edit within the 1-hour window).
- Typing delay: The 30ms delay per character in
postTweetmimics human behavior and reduces detection risk.
Troubleshooting
| Issue | Solution |
|---|---|
| Compose box not found | Make sure you are logged in and on x.com. The selector [data-testid="tweetTextarea_0"] must exist. |
| Media upload fails | Check the file path is absolute and the file exists. Puppeteer requires local file paths. |
| Alt text input not found | The alt text button may need to be clicked first. This varies by X UI version. |
| Tweet button not clickable | The button is disabled if the tweet is empty or exceeds the character limit. |
| Rate limited | Wait 15-30 minutes before retrying. Reduce posting frequency. |
Related Scripts
src/postThread.js-- Post multi-tweet threads (browser console)src/threadComposer.js-- Advanced thread composer with drafts (browser console)src/schedulePosts.js-- Schedule posts for later (browser console)src/textFormatting.js-- Format text with bold, italic, etc.src/createPoll.js-- Create poll tweets (browser console)
⚡ Ready to try Post Content -- Tutorial?
XActions is 100% free and open-source. No API keys, no fees, no signup.
Browse All Scripts