tweetkit-x
MCP server that allows posting, deleting, and reading X (Twitter) tweets using your own browser session cookie, bypassing the official paid API. Includes tools for auth setup, tweet creation, deletion, timeline reading, and regex search.
README
<!-- mcp-name: io.github.nsozturk/tweetkit-x -->
<p align="center"> <img src="assets/header.png" alt="tweetkit-x — post, delete and read on X (Twitter) from Python & MCP using your own web session" width="100%"> </p>
<h1 align="center">tweetkit-x</h1>
<p align="center"> <b>Post, delete & read on X (Twitter) — from Python <i>and</i> as an MCP server — using your own logged-in browser session.</b><br> No paid API. No developer app. No OAuth dance. Just your session cookie. </p>
<p align="center"> <img alt="PyPI" src="https://img.shields.io/pypi/v/tweetkit-x?style=flat-square&color=1d9bf0&label=pypi"> <img alt="Python" src="https://img.shields.io/badge/python-3.10+-1d9bf0?style=flat-square"> <img alt="License" src="https://img.shields.io/badge/license-MIT-3fb950?style=flat-square"> <img alt="MCP" src="https://img.shields.io/badge/MCP-server%20included-7856ff?style=flat-square"> <img alt="X API" src="https://img.shields.io/badge/X%20API-not%20required-3fb950?style=flat-square"> <img alt="Runs with" src="https://img.shields.io/badge/runs%20with-Claude%20%7C%20Cursor%20%7C%20uvx-111318?style=flat-square"> </p>
<p align="center"> <a href="#quick-start">Quick start</a> · <a href="#getting-your-session-cookie">Get your cookie</a> · <a href="#python-usage">Python</a> · <a href="#cli-usage">CLI</a> · <a href="#mcp-server">MCP server</a> · <a href="#how-it-works">How it works</a> · <a href="#disclaimer">Disclaimer</a> </p>
Why
Since February 6, 2026, X's official API has no free tier for new developers — it's pay-per-use: ~$0.015 per post, ~$0.20 per post with a link, plus per-read charges. For publishing your own tweets (a bot posting your content, a scheduled thread, a cleanup script that deletes old posts), that's a recurring bill for something your browser already does for free.
tweetkit-x skips the API entirely. It replays the exact internal HTTP calls your browser makes when you click Post, Delete, or scroll your profile — authenticated with the session cookie you already have. Post, delete, and read the full timeline, at zero API cost.
⚠️ Automating your web session is against X's Terms of Service. This is a grey-area tool for personal automation. Account risk is entirely yours. See the Disclaimer.
Features
- ✅ Post — text, up to 4 images, GIF & video (with alt text), replies, threads, quote-tweets, long-form note tweets, and scheduled tweets
- 🗑️ Delete — one id, a list of ids, or "find matching & delete" cleanup loops
- ❤️ Engage — like, retweet, bookmark, follow, block, mute, pin — each with an undo
- 🌐 Search all of X — the real
SearchTimeline(operators likefrom:,min_faves:,filter:media), plus local regex over your own tweets - 📖 Read — your home feed, any timeline, a tweet's replies/conversation, followers/following, likers/retweeters, bookmarks, a user's likes, notifications, and full profiles
- 🔌 MCP server — 40 tools; drop into Claude Desktop / Claude Code / Cursor; tools that explain the cookie and set it up with one paste
- 🔑 Frictionless auth — paste a
Cookie:header, drop a HAR file, or a storage-dump zip; store in a file or the macOS Keychain - 🐍 Python API and a CLI (
tweetkit …) - 🪶 Tiny footprint — no headless browser, no Selenium
Quick start
pip install "tweetkit-x[mcp]" # or: pip install tweetkit-x (library + CLI only)
# 1. Import your session cookie (three ways — see the next section)
tweetkit import --paste # paste the Cookie: header, Ctrl-D
# or: tweetkit import --file x.com.har
# or: tweetkit import --file storagedump_x.com.zip --keychain tweetkit
# 2. Verify (no network call)
tweetkit whoami
# {"ready": true, "user_id": "1986...", "ct0_len": 160}
# 3. Use it
tweetkit post "hello world 👋"
tweetkit search "xmr|monero" --regex # your tweets that match
tweetkit delete 2063240404980445603
Getting your session cookie
The only secret tweetkit needs is your X session cookie — the same Cookie: header your logged-in browser sends. It must contain at least two values:
| Cookie | What it is | Required | HttpOnly? |
|---|---|---|---|
auth_token |
your login/session token | yes | yes (hidden from document.cookie) |
ct0 |
CSRF token (sent back as x-csrf-token) |
yes | no |
twid |
your user id (u=<id>) — lets tweetkit read your timeline with no extra lookup |
recommended | no |
guest_id, kdt, att, personalization_id |
misc session state | optional | mixed |
❗
auth_tokenis HttpOnly, so adocument.cookiecopy in the JS console will NOT include it. Use one of the reliable methods below.
Method A — copy the Cookie: header (most reliable, one paste)
- Open x.com while logged in.
- Open DevTools (F12) → the Network tab.
- Click any request to
x.com(e.g.HomeTimeline). - Under Request Headers, find
cookie:and copy the entire value. - Feed it in:
tweetkit import --paste
# paste the cookie header, then press Ctrl-D
Method B — an F12 "Preserve log" HAR file
- Open x.com logged in → DevTools (F12) → Network.
- Tick "Preserve log", then reload / click around so requests are captured.
- Right-click any request → "Save all as HAR" (or use the ⬇ export icon).
- Import it:
tweetkit import --file ~/Downloads/x.com.har
Modern Chrome can redact cookies from exported HARs. If tweetkit reports
auth_tokenmissing, either enable "Allow to generate HAR with sensitive data" in the Network settings, or fall back to Method A / Method C.
Method C — the storagedump browser extension (zip)
The easiest no-DevTools route. storagedump (a Chrome extension built by this project's author) exports a tab's browser storage — including the HttpOnly auth_token, which document.cookie can't reach — as a .zip containing cookies.json. On x.com (logged in), click the extension → export, then:
tweetkit import --file storagedump_x.com_2026-07-05.zip
tweetkit reads the extension's native format, { "data": [ { "key": "...", "value": "..." }, ... ] }, and also accepts a plain list or a {name: value} map. Cookie-Editor / EditThisCookie JSON exports (--file export.json) work too.
Install: storagedump on the Chrome Web Store.
Where the cookie is stored
By default tweetkit import writes ~/.config/tweetkit/cookie.txt (chmod 600; also git-ignored). Prefer the macOS Keychain? Add --keychain <slug>:
tweetkit import --paste --keychain tweetkit
export TWEETKIT_COOKIE_KEYCHAIN=tweetkit
Resolution order at runtime (first hit wins): explicit arg → TWEETKIT_COOKIE → TWEETKIT_COOKIE_FILE → ./cookie.txt → ~/.config/tweetkit/cookie.txt → Keychain (TWEETKIT_COOKIE_KEYCHAIN).
Python usage
from tweetkit_x import TweetKit
tk = TweetKit(keychain_slug="tweetkit") # or cookie="auth_token=...; ct0=..."
tk.whoami() # {'ready': True, 'user_id': '...', 'ct0_len': 160}
# post
tk.post("hello world")
tk.post("with a picture", image_path="chart.png")
tk.post("a reply", reply_to="1800000000000000000")
# thread — strings or (text, image_path) tuples; each replies to the previous
tk.post_thread(["1/ intro", ("2/ chart", "chart.png"), "3/ outro"])
# read
mine = tk.get_tweets(limit=100) # your tweets, newest first
theirs = tk.get_tweets(username="jack", limit=50) # anyone's
# search (local filter over the timeline — no paid search API)
hits = tk.search("monero") # substring
hits = tk.search(r"xmr|monero", regex=True) # regex
# delete
tk.delete("1800000000000000000")
tk.delete_many([t["id"] for t in hits])
# quote-tweet
tk.quote("this is great", quote_tweet_id="1800000000000000000")
# engage (each has an undo)
tk.like("1800000000000000000"); tk.unlike("1800000000000000000")
tk.retweet("1800000000000000000"); tk.unretweet("1800000000000000000")
tk.bookmark("1800000000000000000"); tk.unbookmark("1800000000000000000")
# read a single tweet, and search ALL of X (real search + operators)
tk.get_tweet("1800000000000000000")
tk.search_x("mcp server", latest=True, limit=40)
tk.search_x("from:jack min_faves:1000") # X search operators work
Every write returns {'ok': True, 'id': '...', 'url': '...'} on success, or {'ok': False, 'status': ..., 'error': '...'} on failure — easy to log or retry.
See examples/ for a full "find my $XMR tweets and delete them" cleanup loop.
CLI usage
tweetkit whoami
tweetkit post "just some text"
tweetkit post "text + media" --image pic.png
tweetkit post "a reply" --reply-to 1800000000000000000
tweetkit thread thread.txt # tweets separated by blank lines
tweetkit delete 1800000000000000000 1800000000000000001
tweetkit tweets --limit 100 # your tweets
tweetkit tweets @jack --limit 50 # someone else's
tweetkit search monero # your tweets containing "monero"
tweetkit search "xmr|monero" --regex
tweetkit searchx "mcp server" --latest # search ALL of X (real search + operators)
tweetkit get 1800000000000000000 # one tweet by id
tweetkit quote "great thread" 1800000000000000000
tweetkit like 1800000000000000000 # also: unlike / retweet / unretweet / bookmark / unbookmark
A thread.txt is just tweets separated by blank lines.
MCP server
tweetkit ships a first-class MCP server so an AI client can post/delete/read for you — and it walks the user through auth, explaining what the cookie is and setting it up with a single paste.
Configure your client
Claude Desktop / Claude Code / Cursor — add to your MCP config (claude_desktop_config.json, .mcp.json, …):
{
"mcpServers": {
"tweetkit": {
"command": "uvx",
"args": ["--from", "tweetkit-x[mcp]", "tweetkit-mcp"],
"env": { "TWEETKIT_COOKIE_KEYCHAIN": "tweetkit" }
}
}
}
Already pip installed? Use the console script directly:
{ "mcpServers": { "tweetkit": { "command": "tweetkit-mcp",
"env": { "TWEETKIT_COOKIE_KEYCHAIN": "tweetkit" } } } }
If you don't set any cookie env var, that's fine — the server starts unauthenticated and asks the user to set the cookie from inside the chat (below).
Frictionless auth, from inside the chat
The server describes each value and offers the lowest-effort path. A typical first run:
- The client calls
auth_status→ not authenticated. - The server’s instructions tell the assistant to ask you for your cookie and explain what
auth_tokenandct0are and how to copy them. - You paste the
Cookie:header once →set_session_cookie("<paste>")→ stored (Keychain or file) and activated. Or pointimport_cookie_from_file("~/Downloads/x.com.har")at a HAR / storage-dump zip.
The raw cookie is never echoed back.
Tools
| Tool | What it does |
|---|---|
auth_status |
Is a valid session loaded? (call first) |
set_session_cookie(cookie_header) |
Set auth from a pasted Cookie: header — explains exactly what to copy |
import_cookie_from_file(path) |
Set auth from a HAR / storage-dump .zip / cookie JSON |
post_tweet(text, image_path?, reply_to?) |
Post a tweet (optional image / reply) |
post_thread(tweets[]) |
Post a thread |
quote_tweet(text, quote_tweet_id, image_path?) |
Quote-tweet an existing tweet |
delete_tweet(tweet_id) / delete_tweets(ids[]) |
Delete tweets |
like_tweet / unlike_tweet / retweet / unretweet / bookmark_tweet / unbookmark_tweet |
Engage (each reversible) |
get_my_tweets(limit?) / get_user_tweets(username, limit?) |
Read a timeline |
get_tweet(tweet_id) |
Fetch one tweet by id |
search_my_tweets(query, regex?, limit?) |
Find your own tweets (local filter — great for cleanup) |
search_x(query, latest?, limit?) |
Search all of X (real search, supports operators) |
post_note / schedule_tweet / unschedule_tweet |
Long-form note tweets; schedule / cancel |
follow_user / unfollow_user / block_user / unblock_user / mute_user / unmute_user |
Social-graph actions |
pin_tweet / unpin_tweet |
Pin / unpin to your profile |
get_home_timeline / get_replies / get_notifications / get_bookmarks |
Feeds & conversations |
get_user_profile / get_followers / get_following / get_likers / get_retweeters / get_user_likes |
People & profiles |
Not (yet) supported: DMs, polls (create/vote), Lists, profile editing, Spaces, hide-reply. These need a captured HAR of that exact action to pin down the endpoint — easy to add on request.
How it works
When you act in the browser, x.com calls a handful of internal endpoints. tweetkit reproduces them 1:1:
x-client-transaction-id— X requires an anti-bot header derived from the page'sondemand.sJS and a home fetch. Generated with the standalonex-client-transaction-idpackage.- Media upload (images) —
POST upload.x.com/i/media/upload.jsonasINIT→APPEND→FINALIZE, yielding amedia_id. - Write / delete —
POST /i/api/graphql/<queryId>/CreateTweetand.../DeleteTweet. - Read —
GET /i/api/graphql/<queryId>/UserTweets(paginated by cursor), plusUserByScreenNameto resolve@handles.
Auth is just your cookie + the public web bearer token (the same non-secret bearer embedded in x.com for every visitor) + the ct0 CSRF value echoed as x-csrf-token.
your cookie ──► x-client-transaction-id ──► CreateTweet / DeleteTweet / UserTweets ──► result
The GraphQL query IDs live in
tweetkit_x/constants.py. X rotates them every few weeks; if a call starts failing, refresh them from a fresh HAR (the file has step-by-step notes).
Security
- The cookie is the only secret. It's stored chmod 600 in
~/.config/tweetkit/cookie.txtor the macOS Keychain, and.gitignoreblockscookie.txt,.env,*.har, and*.zip. - tweetkit never prints the cookie value — importers report only which cookies were found and their lengths.
- The bundled bearer is X's public web bearer, identical for every visitor — not a secret.
Disclaimer
This project automates your own X web session for personal use. Automating the web session is against X's Terms of Service, and using it may put your account at risk of rate-limiting, suspension, or ban. You are solely responsible for how you use it. Provided as-is, without warranty. Not affiliated with X Corp.
License
MIT © 2026 ns0bj
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。