Automate X/Twitter Posts via API: Write API Guide
What is the Write API?
XCROP is the only crypto data API that also lets you write to X/Twitter programmatically. Create tweets, reply to threads, quote-tweet, like, retweet, follow/unfollow, and delete posts — all via simple API calls.
Perfect for building:
Want ready-to-run bot code instead of the full reference? See [How to Automate Twitter Posts](/blog/automate-twitter-posts-api) for a scheduled posting bot, a KOL engagement bot, and an auto-reply bot built on the endpoints below.
Connecting Your X Account
Before using write operations, you need to connect your X/Twitter account to XCROP. A residential proxy is required — all write operations are routed through your proxy to protect your account from detection.
Connect via API (Credentials)
import requests import os response = requests.post( "https://xcrop.io/api/v2/account/connect", headers={ "Authorization": "Bearer " + os.environ["XCROP_API_KEY"], "Content-Type": "application/json" }, json={ "email": "[email protected]", "password": "your-x-password", "proxy": "http://user:pass@host:port", "totp_secret": "JBSWY3DPEHPK3PXP" # Optional: base32 TOTP secret for 2FA } ) result = response.json() print("Status: " + result["status"]) # "connected" — ready to use write operations
Connect via Cookies (Alternative)
If you prefer not to store credentials, you can connect using browser cookies:
response = requests.post( "https://xcrop.io/api/v2/account/connect", headers={ "Authorization": "Bearer " + os.environ["XCROP_API_KEY"], "Content-Type": "application/json" }, json={ "auth_token": "your_auth_token_cookie", "ct0": "your_ct0_cookie", "proxy": "http://user:pass@host:port" } )
> Note: Cookie-based sessions do not auto-refresh. When cookies expire, you'll need to provide new ones. Credential-based connections auto-refresh sessions automatically.
Proxy Requirements
http://user:pass@host:port or socks5://user:pass@host:portCheck Connection Status
const response = await fetch("https://xcrop.io/api/v2/account/status", { headers: { "Authorization": "Bearer " + apiKey } }); const result = await response.json(); console.log("Connected: " + result.connected); if (result.data) { console.log("Username: @" + result.data.username); console.log("Proxy configured: " + result.data.proxy_configured); }
Security: How We Protect Your Credentials
Your X account security is our top priority:
# Disconnect and remove all stored credentials + proxy response = requests.delete( "https://xcrop.io/api/v2/account/disconnect", headers={"Authorization": "Bearer " + os.environ["XCROP_API_KEY"]} ) print(response.json()["status"]) # "disconnected"
Creating Tweets
Simple Tweet
response = requests.post( "https://xcrop.io/api/v2/tweets/create", headers={ "Authorization": "Bearer " + os.environ["XCROP_API_KEY"], "Content-Type": "application/json" }, json={ "text": "GM crypto! Markets looking bullish today." } ) tweet = response.json()["data"] print("Tweet posted! ID: " + tweet["tweet_id"])
Long-Form Content (Note Tweets)
For content over 280 characters, XCROP automatically uses X's Note Tweet feature — no extra code needed:
long_text = ( "Market Analysis - March 2026\n\n" "Key observations:\n" "- BTC holding strong above $95k support\n" "- ETH/BTC ratio recovering after months of decline\n" "- DeFi TVL hitting new ATH at $180B\n" "- Solana ecosystem showing strong developer growth\n\n" "My thesis: We are in the early stages of a macro bull run. " "The combination of ETF inflows, halving effects, and increasing " "institutional adoption creates a perfect storm.\n\n" "DYOR. Not financial advice." ) response = requests.post( "https://xcrop.io/api/v2/tweets/create", headers=headers, json={"text": long_text} ) # Automatically posted as a Note Tweet (>280 chars)
Replying to Tweets
Build conversational bots that reply to specific tweets:
response = requests.post( "https://xcrop.io/api/v2/tweets/reply", headers=headers, json={ "tweet_id": "1234567890123456789", "text": "Great analysis! I agree with your take on the ETH/BTC ratio." } ) reply = response.json()["data"] print("Reply posted! ID: " + reply["tweet_id"])
Quote Tweeting
Share and comment on others' content:
response = requests.post( "https://xcrop.io/api/v2/tweets/quote", headers=headers, json={ "quoted_tweet_id": "1234567890123456789", "text": "This is exactly the kind of on-chain analysis traders need." } ) quote = response.json()["data"] print("Quote tweet posted! ID: " + quote["tweet_id"])
Like, Retweet, Follow
# Like a tweet requests.post(BASE_URL + "/tweets/1234567890/like", headers=headers) # Retweet requests.post(BASE_URL + "/tweets/1234567890/retweet", headers=headers) # Follow a user requests.post(BASE_URL + "/users/elonmusk/follow", headers=headers) # Unfollow requests.delete(BASE_URL + "/users/elonmusk/follow", headers=headers) # Unlike requests.delete(BASE_URL + "/tweets/1234567890/like", headers=headers) # Unretweet requests.delete(BASE_URL + "/tweets/1234567890/retweet", headers=headers)
Deleting Tweets
Remove tweets programmatically:
response = requests.delete( "https://xcrop.io/api/v2/tweets/1234567890123456789", headers=headers ) print(response.json()["status"]) # "deleted"
Use Case: Trading Signal Bot
Here's a complete example that combines XCROP's read and write APIs to build a trading signal bot:
import requests import time import os API_KEY = os.environ["XCROP_API_KEY"] HEADERS = { "Authorization": "Bearer " + API_KEY, "Content-Type": "application/json" } BASE_URL = "https://xcrop.io/api/v2" def check_kol_signals(): """Monitor KOL tweets and auto-post signals.""" tweets = [] for kol in ["CryptoHayes", "DefiIgnas", "Pentosh1"]: response = requests.get( f"{BASE_URL}/users/{kol}/tweets", headers=HEADERS, params={"count": 20} ) tweets += response.json().get("data", []) tweets = response.json()["data"] for tweet in tweets: likes = tweet["metrics"]["likes"] # Only post about high-engagement tweets if likes > 5000: author = tweet["author"]["username"] signal_text = ( "KOL Alert!\n\n" + "@" + author + " just posted with " + str(likes) + " likes:\n\n" + "\"" + tweet["text"][:200] + "\"\n\n" + "#crypto #alpha" ) # Post the signal post_resp = requests.post( BASE_URL + "/tweets/create", headers=HEADERS, json={"text": signal_text} ) if post_resp.status_code == 200: tweet_id = post_resp.json()["data"]["tweet_id"] print("Signal posted: " + tweet_id) # Run every 5 minutes while True: check_kol_signals() time.sleep(300)
Credit Usage for Write Operations
Write operations use a flat rate of 100 credits per operation:
With the Pro plan ($9.9/mo, 2M credits), you can make 20,000 write operations per month plus thousands of read operations for signal detection.