The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Tweetkit X listing page.
Post, delete & read on X (Twitter) — from Python and as an MCP server — using your own logged-in browser session.
No paid API. No developer app. No OAuth dance. Just your session cookie.
Quick start · Get your cookie · Python · CLI · MCP server · How it works · Disclaimer
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.
SearchTimeline (operators like from:, min_faves:, filter:media), plus local regex over your own tweetsCookie: header, drop a HAR file, or a storage-dump zip; store in a file or the macOS Keychaintweetkit …)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.
Cookie: header (most reliable, one paste)x.com (e.g. HomeTimeline).cookie: and copy the entire value.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.
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 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.
By default tweetkit import writes ~/.config/tweetkit/cookie.txt (chmod 600; also git-ignored). Prefer the macOS Keychain? Add --keychain <slug>:
Resolution order at runtime (first hit wins): explicit arg → TWEETKIT_COOKIE → TWEETKIT_COOKIE_FILE → ./cookie.txt → ~/.config/tweetkit/cookie.txt → Keychain (TWEETKIT_COOKIE_KEYCHAIN).
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.
A thread.txt is just tweets separated by blank lines.
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.
Claude Desktop / Claude Code / Cursor — add to your MCP config (claude_desktop_config.json, .mcp.json, …):
Already pip installed? Use the console script directly:
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).
The server describes each value and offers the lowest-effort path. A typical first run:
auth_status → not authenticated.auth_token and ct0 are and how to copy them.Cookie: header once → set_session_cookie("<paste>") → stored (Keychain or file) and activated. Or point import_cookie_from_file("~/Downloads/x.com.har") at a HAR / storage-dump zip.The raw cookie is never echoed back.
| 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.
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's ondemand.s JS and a home fetch. Generated with the standalone x-client-transaction-id package.POST upload.x.com/i/media/upload.json as INIT → APPEND → FINALIZE, yielding a media_id.POST /i/api/graphql/<queryId>/CreateTweet and .../DeleteTweet.GET /i/api/graphql/<queryId>/UserTweets (paginated by cursor), plus UserByScreenName to 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.
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).
~/.config/tweetkit/cookie.txt or the macOS Keychain, and .gitignore blocks cookie.txt, .env, *.har, and *.zip.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.
MIT © 2026 ns0bj