Skip to main content

twifork

A Twitter / X API scraper for Python — no API key required.
A maintained fork of d60/twikit, fixed for the 2026 breakages that make the upstream release unusable.

PyPI Python 3.8+ MIT License Stars

[English] · [日本語] · [中文]

Drop-in replacement — the package still imports as twikit, so existing code (from twikit import Client) keeps working unchanged.


Install

pip install twifork

With optional browser-TLS impersonation (gets past some 403 walls):

pip install "twifork[impersonate]"

Or grab the latest straight from git:

pip install git+https://github.com/PawiX25/twifork.git

Why this fork?

The upstream PyPI release (twikit==2.3.3) is broken in several ways as of 2026. twifork fixes them — each item links to the upstream issue it resolves:

  • ClientTransaction / Couldn't get KEY_BYTE indices — updated ondemand.s.js parsing for the new X webpack bundle, so GraphQL requests work again. (#408, #409, #304)
  • Intermittent / sticky 404 on SearchTimeline and friends/list — the x-client-transaction-id animation key was missing X's frame_time rounding step, so on some Client sessions every strict request 404'd until the client was recreated. Restored, so the semi-random 404s are gone. (#357, #397)
  • KeyError on missing optional fields in User.__init__ and Client.request — defensive .get() parsing. (#417)
  • Empty user name / screen_name (e.g. in search results) — X moved name, screen_name, created_at, avatar, location, and more out of legacy into new sub-objects; these are now read with a legacy fallback.
  • get_tweet_by_id KeyError: 'itemContent' — handles both the legacy and the new trailing-cursor shapes. (#332, #363)
  • KeyError: 'entries' / IndexError on get_user_tweets for accounts with no visible tweets — empty / cursor-less timelines return an empty result instead of crashing. (#361, #216)
  • get_trends deprecated / returns nothing — rebuilt on top of GenericTimelineById; also adds get_explore_page(). (#389)
  • RecursionError on rate-limit — the 429 recovery path no longer recurses.
  • GuestClient.activate() 404 — the guest client now sends a User-Agent header and parses user fields defensively. (#402, #385)
  • get_latest_friends 404 — routed through the GraphQL Following endpoint after the v1.1 endpoint was retired. (#397)
  • 'Client' object has no attribute '_ui_metrix' — fixed the captcha unlock path. (#333)
  • get_bookmark_folders().next() infinite loop — fixed malformed pagination variables. (#334, #335)
  • get_latest_timeline / get_list_tweets dropping conversation entries — home- and list-conversation entries are now unpacked. (#336, #337, #340)
  • Media.source_url for the full-resolution image (#376), and Tweet.quoted_status_id for the quoted tweet id (#222).

Issues that stem from X-side restrictions (account suspension, Cloudflare/IP blocks, captcha, automation limits) aren't fixable in the library and are out of scope.

Browser TLS impersonation (optional)

Some X endpoints reject the default httpx TLS fingerprint with a 403 (HTML) response even when the request is valid. Installing the optional curl_cffi backend and passing impersonate= routes requests through a real browser TLS fingerprint, which avoids those 403s:

client = Client('en-US', impersonate='chrome124')

Quick start

Define a client and log in.

import asyncio
from twikit import Client

client = Client('en-US')

async def main():
    await client.login(
        auth_info_1='example_user',
        auth_info_2='email@example.com',
        password='password0000',
        cookies_file='cookies.json'
    )

asyncio.run(main())

Post a tweet with media attached.

media_ids = [
    await client.upload_media('media1.jpg'),
    await client.upload_media('media2.jpg'),
]
await client.create_tweet(text='Example Tweet', media_ids=media_ids)

Search the latest tweets for a keyword.

tweets = await client.search_tweet('python', 'Latest')
for tweet in tweets:
    print(tweet.user.name, tweet.text, tweet.created_at)

A few more common calls.

await client.get_user_tweets('123456', 'Tweets')   # a user's tweets
await client.send_dm('123456789', 'Hello')          # send a DM
await client.get_trends('trending')                 # trending topics

More examples (upstream, still apply): https://github.com/d60/twikit/tree/main/examples

Features

  • No API key — works by scraping the web client.
  • Free & open source (MIT).
  • Drop-in twikit replacement — same import, your code doesn't change.
  • Tweets, search, timelines, trends, users, DMs, media, bookmarks, and more.

Documentation

Full API reference (upstream — the package surface is the same): https://twikit.readthedocs.io/en/latest/twikit.html

Community

Discord

Contributing

Found a bug or have a fix? Open an issue or PR on twifork issues.

If twifork saved you a headache, consider leaving a ⭐.

Credits

twifork is a fork of d60/twikit by @d60 — all upstream credit goes to the original authors. Licensed under the MIT License.

Disclaimer

twifork is an independent, unofficial project. It is not affiliated with, endorsed by, or sponsored by X Corp. "X" and "Twitter" are trademarks of X Corp. Use it in accordance with applicable terms and laws.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

twifork-2.3.5.tar.gz (74.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

twifork-2.3.5-py3-none-any.whl (88.1 kB view details)

Uploaded Python 3

File details

Details for the file twifork-2.3.5.tar.gz.

File metadata

  • Download URL: twifork-2.3.5.tar.gz
  • Upload date:
  • Size: 74.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for twifork-2.3.5.tar.gz
Algorithm Hash digest
SHA256 43c7f2ce0a359f51c5d1a68f1f471fdd43e94dca5519ed421e141ccfec000828
MD5 4ab103b4660add30a9e3f2dc27d3d877
BLAKE2b-256 113af794d6bb63604fac6774c6b398d0687ef677cfa33757b874213c8d55f720

See more details on using hashes here.

File details

Details for the file twifork-2.3.5-py3-none-any.whl.

File metadata

  • Download URL: twifork-2.3.5-py3-none-any.whl
  • Upload date:
  • Size: 88.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for twifork-2.3.5-py3-none-any.whl
Algorithm Hash digest
SHA256 1da58ac3dd0172c0656797fefe542dc67d26fb433fdfbfd0da122c4fbd316357
MD5 ae1833576031dc7db0bc7288f1524fa7
BLAKE2b-256 a19e57ad45735d8ffd55ac4eecd6a6b91bf9cc598a2fc83be0c9a45e8d413fa5

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

2.3.5 This release

2 files

2.3.4

2 files

2.3.3

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page