Skip to content

Instantly share code, notes, and snippets.

@jmanhype
Created February 4, 2026 17:28
Show Gist options
  • Select an option

  • Save jmanhype/782b54892527e06720274f8ed2c5419d to your computer and use it in GitHub Desktop.

Select an option

Save jmanhype/782b54892527e06720274f8ed2c5419d to your computer and use it in GitHub Desktop.
Automating X (Twitter) Article Publishing with agent-browser and Python

X Article Publisher Automation with agent-browser

This guide demonstrates how to automate publishing rich-text articles to X (Twitter) using agent-browser, Python, and the MacOS clipboard. It bypasses X's lack of an API for long-form articles by automating the web editor.

The Strategy

  1. Parse Markdown: Extract title, cover image, and convert body to HTML.
  2. Browser Automation: Open X editor, upload cover, and fill title.
  3. Rich Text Paste: Use Python to put HTML on the system clipboard as rich text, then paste (Cmd+V) into the browser.
  4. Inline Images: Copy images to clipboard and paste them at specific insertion points.

1. Python Helper: Copy HTML to Clipboard (MacOS)

Save as copy_to_clipboard.py. Requires pyobjc-framework-Cocoa.

import argparse
import sys
from AppKit import NSPasteboard, NSPasteboardTypeHTML, NSPasteboardTypeString
from Foundation import NSData

def copy_html_macos(html):
    pasteboard = NSPasteboard.generalPasteboard()
    pasteboard.clearContents()
    
    # Set HTML content for rich text paste
    html_data = html.encode('utf-8')
    ns_data = NSData.dataWithBytes_length_(html_data, len(html_data))
    pasteboard.setData_forType_(ns_data, NSPasteboardTypeHTML)
    
    # Fallback plain text
    pasteboard.setString_forType_(html, NSPasteboardTypeString)
    return True

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('content', nargs='?')
    args = parser.parse_args()
    
    # Read from stdin if no argument
    content = args.content if args.content else sys.stdin.read()
    copy_html_macos(content)

2. Python Helper: Copy Image to Clipboard

Save as copy_image.py. Requires Pillow and pyobjc-framework-Cocoa.

import sys
import io
from PIL import Image
from AppKit import NSPasteboard, NSPasteboardTypeTIFF
from Foundation import NSData

def copy_image(path):
    img = Image.open(path)
    buffer = io.BytesIO()
    img.save(buffer, format='TIFF')
    data = buffer.getvalue()
    
    pasteboard = NSPasteboard.generalPasteboard()
    pasteboard.clearContents()
    ns_data = NSData.dataWithBytes_length_(data, len(data))
    pasteboard.setData_forType_(ns_data, NSPasteboardTypeTIFF)

if __name__ == "__main__":
    copy_image(sys.argv[1])

3. The Automation Script (Bash)

This script coordinates the entire process. It assumes you have Chrome open with remote debugging enabled (--remote-debugging-port=9222).

#!/bin/bash

# 1. Parse Markdown to HTML (using a parser script, or simple pandoc)
# python3 parse_markdown.py my_post.md > article.json

TITLE="My Awesome Article"
COVER_IMG="cover.png"
BODY_HTML="<h1>Hello World</h1><p>This is a test.</p>"

# 2. Connect to Chrome & Open Editor
agent-browser --cdp 9222 open https://x.com/compose/articles
agent-browser --cdp 9222 wait 5000

# 3. Create New Article
# Click the 'Create' button (ref may vary, snapshot to find it)
agent-browser --cdp 9222 click "button[aria-label='Create']" 

# 4. Upload Cover Image & Set Title
agent-browser --cdp 9222 upload "input[type='file']" "$COVER_IMG"
agent-browser --cdp 9222 fill "textarea[placeholder='Title']" "$TITLE"

# 5. Paste Rich Text Body
# Copy HTML to clipboard using our helper
echo "$BODY_HTML" | python3 copy_to_clipboard.py

# Focus the editor body
agent-browser --cdp 9222 click "div[role='textbox']"

# Paste!
agent-browser --cdp 9222 press Meta+v

# 6. Insert Inline Image
# Copy image to clipboard
python3 copy_image.py "inline_graph.png"

# Navigate to insertion point (e.g., click a specific header)
agent-browser --cdp 9222 click "h2" 
agent-browser --cdp 9222 press End  # Move cursor to end of line
agent-browser --cdp 9222 press Enter # New line
agent-browser --cdp 9222 press Meta+v # Paste image

Setup Notes

  1. Chrome Debugging: You must start Chrome with: /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
  2. Dependencies: pip install pyobjc-framework-Cocoa Pillow
  3. X Premium: Required to access the Articles feature.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment