Advanced Twitter Automation AI
Advanced Twitter Automation AI is a modular Python-based framework for automating X (Twitter) at scale. It supports multiple accounts, robust Selenium automation (with optional undetected Chrome + stealth), per‑account proxies and rotation, structured LLM generation/analysis (OpenAI, Azure OpenAI, Gemini), community posting, and per‑account metrics/logs.
Table of Contents
- Advanced Twitter Automation AI
Features
- Multi-Account Management: Seamlessly manage and automate actions for multiple Twitter accounts.
- Content Scraping:
- Scrape tweets based on keywords, user profiles, and news/research sites.
- Extract tweet content, user information, and engagement metrics.
- Content Publishing:
- Post new tweets, including text and media.
- Reply to tweets based on various triggers.
- Repost (retweet) content from competitor profiles or based on engagement metrics.
- LLM Integration:
- Utilize OpenAI (GPT models) and Google Gemini for:
- Generating tweet content and replies.
- Analyzing tweet threads and sentiment.
- Summarizing articles for posting.
- Flexible LLM preference settings at global and per-account levels.
- Utilize OpenAI (GPT models) and Google Gemini for:
- Engagement Automation:
- Engage with tweets through likes, replies, and reposts.
- Analyze competitor activity and engage strategically.
- Configurable Automation:
- Fine-grained control over automation parameters via JSON configuration files.
- Per-account overrides for keywords, target profiles, LLM settings, and action behaviors.
- Browser Automation: Uses Selenium for interacting with Twitter, handling dynamic content and complex UI elements.
- Modular Design: Easily extendable with new features and functionalities.
- Logging: Comprehensive logging for monitoring and debugging.
- Community Posting: Switch audience and post into configured communities (by ID or name).
- Stealth Mode (Chrome): Optional undetected-chromedriver + selenium-stealth to reduce fingerprinting.
- Proxies: Per-account proxies, named proxy pools, and rotation strategies (hash/round-robin) with env interpolation.
- LLM Structured Prompts: Strict JSON prompting with few-shots, system prompts, and robust extraction.
- Metrics: Per-account JSON summaries and JSONL event logs for observability.
Technology Stack
- Programming Language: Python 3.9+
- Browser Automation: Selenium, WebDriver Manager
- HTTP Requests: Requests
- Data Validation: Pydantic
- LLM Integration: Langchain (for Google GenAI), OpenAI SDK
- Stealth: undetected-chromedriver, selenium-stealth (optional)
- Configuration: JSON, python-dotenv
- Web Interaction: Fake Headers (for mimicking browser headers)
Project Structure
The project is organized as follows:
twitter-automation-ai/
├── config/
│ ├── accounts.json # Configuration for multiple Twitter accounts
│ └── settings.json # Global settings (API keys, automation parameters)
├── src/
│ ├── core/ # Core modules (browser, LLM, config)
│ │ ├── browser_manager.py
│ │ ├── config_loader.py
│ │ └── llm_service.py
│ ├── features/ # Modules for Twitter features (scraper, publisher, etc.)
│ │ ├── scraper.py
│ │ ├── publisher.py
│ │ └── engagement.py
│ ├── utils/ # Utility modules (logger, file handler, etc.)
│ │ ├── logger.py
│ │ ├── file_handler.py
│ │ ├── progress.py
│ │ └── scroller.py
│ ├── data_models.py # Pydantic models for data structures
│ ├── main.py # Main orchestrator script
│ └── __init__.py
├── .env # Environment variables (optional, for API keys)
├── requirements.txt # Python dependencies
├── .gitignore # Specifies intentionally untracked files
├── LICENSE # Project license
├── CODE_OF_CONDUCT.md # Contributor Code of Conduct
├── CONTRIBUTING.md # Guidelines for contributing
└── README.md # This file
Prerequisites
- Python 3.9 or higher.
- A modern web browser (e.g., Chrome, Firefox) compatible with Selenium.
Recommended Proxy Providers
Twitter's per-IP detection kills automation at scale. Use a quality proxy provider to keep your multi-account setup running reliably. The providers below are tested and recommended.
⭐ ScrapingAnt — Featured Provider
Private residential network with premium grade IPs — not resold traffic. Supports sticky sessions required for Twitter's IP consistency checks.
Top-notch, fast residential ScrapingAnt’s proxies for best performance |
Affordable datacenter proxies for cost-effective operations |
RapidProxy
Dynamic and static residential proxies with free testing and unlimited, non-expiring traffic.
Setup and Configuration
Follow these steps to set up and run the project:
Presets (Beginner-Friendly)
Quick-start templates are available in presets/.
- Settings presets:
presets/settings/*.json(defaults, Chrome undetected, proxies hash/round-robin) - Accounts presets:
presets/accounts/*.json(growth, brand_safe, replies_first, engagement_light, community_posting) - How to apply:
- cp
presets/settings/beginner-chrome-undetected.jsonconfig/settings.json - cp
presets/accounts/growth.jsonconfig/accounts.json - Edit placeholders for API keys, cookie paths, and community IDs.
- See
presets/README.mdanddata/README.md(dummy cookies/proxies).
- cp
1. Clone Repository
git clone https://github.com/ihuzaifashoukat/twitter-automation-ai
cd twitter-automation-ai
2. Create Virtual Environment
It's highly recommended to use a virtual environment:
python -m venv venv
# On Windows
venv\Scripts\activate
# On macOS/Linux
source venv/bin/activate
3. Install Dependencies
Install the required Python packages:
pip install -r requirements.txt
4. Configure Accounts (config/accounts.json)
This file manages individual Twitter account configurations. It should be an array of account objects.
-
Key Fields per Account:
account_id: A unique identifier for the account.is_active: Boolean, set totrueto enable automation for this account.cookie_file_path: Path to a JSON file containing cookies for the account (e.g.,config/my_account_cookies.json).cookies: Alternatively, an array of cookie objects can be provided directly.proxy(optional): Per-account proxy URL. Examples:http://user:pass@host:port,socks5://host:port.post_to_community(optional): Whentrue, switch the audience to a community before posting.community_id(optional): Community ID used to select the audience (preferred).community_name(optional): Fallback visible name in the audience picker if ID selection fails.- Overrides: You can specify per-account overrides for various settings like
target_keywords_override,competitor_profiles_override,llm_settings_override, andaction_config_override. If an override is not present, the global defaults fromconfig/settings.jsonwill be used.
-
Example
config/accounts.jsonentry:// Minimal example: ONLY add the community fields you need; keep your existing structure as-is. // Below shows adding community + (optional) proxy to one of your existing account objects: { "account_id": "your_existing_account_id", "is_active": true, "cookie_file_path": "config/your_existing_cookie_file.json", // ... all your existing fields remain unchanged ... "proxy": "http://127.0.0.1:8888", // optional "post_to_community": true, // optional "community_id": "1737236915810627584", // preferred when known "community_name": "One Piece" // fallback by visible name }(Refer to the example in the original README section for a more detailed structure if needed, or adapt based on current
data_models.py.) -
Obtaining Cookies: Use browser developer tools (e.g., "EditThisCookie" extension) to export cookies for
x.comafter logging in. Save them as a JSON array of cookie objects if usingcookie_file_path. -
Per-Account Proxy: If set, the proxy overrides the global
browser_settings.proxyfor that account. Chrome uses--proxy-server; Firefox is configured via profile preferences (proxy auth prompts are not handled automatically). -
Community Posting: When
post_to_communityis true, the publisher clicks the "Choose audience" button in the composer and selects your community usingcommunity_id(preferred) orcommunity_nameas a fallback, then posts. -
Important: We do not require changing your existing
accounts.jsonstructure. Simply add the optional fields (post_to_community,community_id,community_name, and/orproxy) to the appropriate account objects. -
For rewrite-based posting to communities or personal profiles, ensure each account has competitor sources configured via
competitor_profiles(orcompetitor_profiles_overridein your current structure). The scraper uses these as input for rewriting and posting.
5. Configure Global Settings (config/settings.json)
This file contains global configurations for the application.
- Key Sections:
api_keys: Store API keys for LLM services (e.g.,openai_api_key,gemini_api_key).twitter_automation:action_config: Default behaviors for automation actions (e.g.,max_posts_per_run,min_likes_for_repost).response_interval_seconds: Default delay between actions.media_directory: Path to store downloaded media.analysis_config: Enable/disable relevance filters per pipeline and thresholds.
enable_relevance_filter.competitor_reposts(bool),thresholds.competitor_reposts_min(0–1)enable_relevance_filter.likes(bool),thresholds.likes_min(0–1)
engagement_decision: Ifenabled: true, automatically chooses between repost/retweet/quote/like based on relevance and sentiment.
use_sentiment: include sentiment in decisionthresholds.quote_min|retweet_min|repost_min: relevance cutoffs (0–1)
logging: Configuration for the logger.
browser_settings: Settings for Selenium WebDriver (e.g.,headlessmode).type:chromeorfirefox. For best anti-detection, use Chrome withuse_undetected_chromedriver.use_undetected_chromedriver(Chrome only): Whentrue, usesundetected-chromedriverfor stealthier automation.enable_stealth(Chrome only): Whentrueandselenium-stealthis installed, applies additional anti-detection tweaks.user_agent_generation:randomorcustomwithcustom_user_agentstring.proxy: Global proxy (can be overridden per account).driver_options: Extra Chrome/Firefox CLI options.page_load_timeout_seconds,script_timeout_seconds,window_size.
LLM prompt engineering
- LLM prompts now use stronger, schema-first instructions for structured JSON with optional few-shot examples and hard character limits.
LLMService.generate_textaccepts an optionalsystem_promptandmessagesfor OpenAI/Azure; Gemini concatenates system+user.LLMService.generate_structuredaddsfew_shots,system_prompt, andhard_character_limitto guide safer, parsable outputs.proxy_pools: Named pools for per-account proxies. Use"pool:<name>"in accountproxyto select from a pool.proxy_pool_strategy:hash(stable per-account) orround_robin(rotates across runs/accounts).proxy_pool_state_file: Persist file for round-robin counters (defaultdata/proxy_pools_state.json).
- Important Note: Content source lists like
target_keywords,competitor_profiles, etc., are primarily managed per-account inconfig/accounts.json. The globalaction_configinsettings.jsondefines default how actions run, which can be overridden per account.
6. Environment Variables (.env) (Optional)
For sensitive data like API keys, you can use a .env file in the project root. python-dotenv is included in requirements.txt to load these variables.
- Create a
.envfile:OPENAI_API_KEY="your_openai_api_key" GEMINI_API_KEY="your_gemini_api_key" # Add other sensitive variables as neededThe application is designed to prioritize environment variables for API keys if available.
Running the Application
Execute the main orchestrator script from the project root:
python src/main.py
The orchestrator will iterate through active accounts in config/accounts.json and perform actions based on their respective configurations and global settings.
Community Posting
To post into a community instead of your public timeline, set the following on the account object in config/accounts.json:
post_to_community: true- Provide at least one of:
community_id: preferred (appears in URLs like/i/communities/<id>)community_name: fallback by the visible label in the audience picker
How selection works:
- The app opens the "Choose audience" control, locates the audience menu container (dialog or
data-testid="HoverCard"), and attempts to click your community. - It scrolls the virtualized list to reveal off-screen items and uses JS-click fallbacks to avoid overlay interception.
- After selection, it posts using the chosen audience.
If it fails to select your community:
- Verify the account has joined the community and it appears under "My Communities".
- Provide a DOM snapshot from the audience menu in a GitHub issue so selectors can be tuned.
Keyword Engagement
Controls live under twitter_automation.action_config (globally) and per-account action_config_override:
- Replies:
enable_keyword_replies,max_replies_per_keyword_run, optional recencyreply_only_to_recent_tweets_hours. - Likes:
enable_liking_tweets,max_likes_per_run,like_tweets_from_keywords(defaults to accounttarget_keywordswhen omitted). - Retweets (new):
enable_keyword_retweets,max_retweets_per_keyword_run.
Relevance filters (optional):
enable_relevance_filter_keyword_replies,relevance_threshold_keyword_repliesenable_relevance_filter_likes,relevance_threshold_likes
Troubleshooting
-
ElementClickInterceptedException or "not clickable":
- The app automatically scrolls into view, waits for the composer mask to disappear, and uses JS-click or Ctrl+Enter fallbacks.
- If it persists, consider adding small delays or switching to Chrome (
browser_settings.type: "chrome").
-
Community not selected:
- Ensure
post_to_community: trueand setcommunity_id(best) orcommunity_name. - The audience list is virtualized; the app scrolls within the menu to reveal items. If your UI differs, open an issue with a DOM snippet.
- Ensure
-
WebDriver downloads blocked or offline:
- The app prefers local drivers (
chromedriver,geckodriver) if found in PATH or viachrome_driver_path/gecko_driver_path. Install via your OS package manager or ensure they're in PATH.
- The app prefers local drivers (
-
Gemini errors (429/500):
- Use
gemini-1.5-flash-latest, reduce calls, or configure OpenAI/Azure.
- Use
LLM Prompting
- Structured analysis and generation use strict schema-first prompts with robust JSON extraction. OpenAI JSON mode is attempted when available.
- Internally supports system prompts and few-shot examples for more controllable outputs.
- Content generation for posts composes final text (with optional hashtags) within 280 chars.
Browser & Stealth
- Chrome: set
browser_settings.typeto"chrome"and enableuse_undetected_chromedriver. Optionalenable_stealthapplies extra anti-detection tweaks. - Firefox: standard Selenium with proxy prefs; auth prompts are not auto-handled.
- Headless: Chrome uses
--headless=newfor better parity. User-Agent randomized by default.
Proxies
- Per-account
proxyoverrides global. Use"pool:<name>"to select frombrowser_settings.proxy_pools. - Rotation strategies:
hash(stable per-account) orround_robin(usesdata/proxy_pools_state.json). - Env interpolation:
${ENV_VAR}inside proxy strings is expanded at runtime.
Cookies
- Point
cookie_file_pathto a JSON array of cookies forx.com. The app navigates tobrowser_settings.cookie_domain_urlbefore injecting cookies. - Example file:
data/cookies/dummy_cookies_example.json.
Metrics & Logs
- Summary per account:
data/metrics/<account_id>.json(counters for posts, replies, retweets, quote_tweets, likes, errors; last run timestamps) - Structured events per account:
logs/accounts/<account_id>.jsonl(JSON lines of each action attempt with metadata)
Configuration Reference
See docs/CONFIG_REFERENCE.md for a concise schema of config/settings.json and config/accounts.json, including per-account action_config_override fields and decision thresholds.
Development Notes
- Logging: Detailed logs are output to the console. Configuration is in
config/settings.jsonand managed bysrc/utils/logger.py. - Selenium Selectors: Twitter's (X.com) UI is subject to change. XPath and CSS selectors in
src/features/scraper.pyandsrc/features/publisher.pymay require updates if the site structure changes. - Error Handling: The project includes basic error handling. Enhancements with more specific exception management and retry mechanisms are potential areas for improvement.
- Extensibility: To add new features:
- Define necessary data structures in
src/data_models.py. - Create new feature modules within the
src/features/directory. - Integrate the new module into the
TwitterOrchestratorinsrc/main.py.
- Define necessary data structures in
Contributing
Contributions are welcome! Please read our CONTRIBUTING.md for guidelines on how to contribute, report bugs, or suggest enhancements.
Code of Conduct
To ensure a welcoming and inclusive environment, this project adheres to a Code of Conduct. Please review and follow it in all your interactions with the project.
License
This project is licensed under the MIT License. See the LICENSE file for details.
TODO / Future Enhancements
- GUI or web interface for managing accounts, settings, and monitoring.
- Advanced error handling, including robust retry logic for network issues or UI changes.
- Integration with proxy services for enhanced multi-account management and anonymity.
- More detailed per-account activity logging and analytics.
- Improved AI-driven content analysis and decision-making.