Post an original tweet (new, not a reply) on X/Twitter with arbitrary text and, OPTIONALLY, an attached image, from the logged-in account.
{"text":"tweet content (string, max 280 chars unless Premium account)","image":"OPTIONAL: local path of the image file to attach (e.g. /Users/.../photo.png). If omitted, posts text only."}{}Post an original tweet (new, not a reply) on X/Twitter with arbitrary text and, OPTIONALLY, an attached image, from the logged-in account. Opens the composer at /compose/post, types the text into the Draft.js contenteditable [data-testid=tweetTextarea_0]; if image (local file path) is passed it uploads it to the media input [data-testid=fileInput] and waits for the preview [data-testid=attachments]; publishes with [data-testid=tweetButton]. Goes via UI (Playwright), NOT via API: the CreateTweet endpoint returns 200 but X silently drops the write without the anti-bot signature x-client-transaction-id (same reason as x-reply). write-irreversible: posts a real PUBLIC tweet. Params: text (max 280 unless Premium) and image (optional, local path of the image to attach). Requires an active X session.
Drive the rendered page with your browser (selectors are CSS; {{var}} = a param):
[data-testid=tweetTextarea_0]{{text}} into [data-testid=tweetTextarea_0]{{image}} to [data-testid=fileInput] (optional)[data-testid=attachments] (optional)[data-testid=tweetButton]Step 6 is the commit: it performs the write-irreversible action.
{
"expr": "document.querySelector('[data-testid=tweetButton]') === null && document.querySelector('[data-testid=primaryColumn]') !== null",
"type": "dom",
"within_ms": 10000
}