Skip to content
amanetoki7Public
forked from d60/twikit

About

すきくん におしえてもらった ↓ のforkしました パッチあてるといいって聞きました

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

twikit

API キー不要で使える、Python 用の Twitter / X API スクレイピングライブラリ。
d60/twikit をベースに、PawiX25/twifork の修正と機能追加(2026 年時点で本家が動かなくなった不具合の修正、X スペース対応など)を取り込んだフォークです。

Python 3.10+ MIT License Stars

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

既存コードはそのまま動きます。 パッケージ名もインポート名も twikit のままなので、from twikit import Client などのコードを書き換える必要はありません。


インストール

このリポジトリは PyPI には公開していません。git から直接インストールしてください。

pip install git+https://github.com/amanetoki7/twikit.git

Warning

pip install twikit で入るのは本家(d60/twikit)の 2.3.3 です。2026 年現在、本家はいくつもの箇所が壊れており、このリポジトリの修正は含まれていません。

オプション機能は extras で指定します。

# ブラウザの TLS フィンガープリントを偽装して、一部の 403 を回避する(curl_cffi)
pip install "twikit[impersonate] @ git+https://github.com/amanetoki7/twikit.git"

# X スペースの WebRTC 音声(発言 / 聴取)とライブチャットの WebSocket(aiortc + websockets)
pip install "twikit[spaces] @ git+https://github.com/amanetoki7/twikit.git"

clone して開発する場合:

git clone https://github.com/amanetoki7/twikit.git
cd twikit
pip install -e ".[impersonate,spaces]"

Python 3.10 以上が必要です(anext() と辞書の | 演算子を使っています)。

本家からの修正点

本家の PyPI 版(twikit==2.3.3)は 2026 年現在、以下の箇所が壊れています。このリポジトリでは twifork の修正を取り込み、すべて解消しています。各項目は対応する本家の Issue にリンクしています。

  • ClientTransaction / Couldn't get KEY_BYTE indices — X の新しい webpack バンドルに合わせて ondemand.s.js の解析を更新し、GraphQL リクエストが再び通るようにしました。(#408, #409, #304)
  • SearchTimeline や friends/list で散発的に出て、そのまま居座る 404 — x-client-transaction-id のアニメーションキー計算で X 側の frame_time の丸め処理が抜けており、一部の Client では作り直すまで厳格なリクエストがすべて 404 になっていました。丸め処理を復元し、ランダムな 404 は解消されています。(#357, #397)
  • 任意フィールド欠落時の KeyError(User.__init__ と Client.request)— .get() で安全に読むようにしました。(#417)
  • ユーザーの name / screen_name が空になる(検索結果などで発生)— X が name・screen_name・created_at・アイコン・場所などを legacy から新しいサブオブジェクトへ移したため、新しい場所を読みつつ legacy にもフォールバックするようにしました。
  • get_tweet_by_id の KeyError: 'itemContent' — 旧形式と新しい末尾カーソル形式の両方に対応しました。(#332, #363)
  • ツイートが無いアカウントでの get_user_tweets の KeyError: 'entries' / IndexError — 空・カーソル無しのタイムラインでも落ちずに空の結果を返します。(#361, #216)
  • get_trends が非推奨で何も返さない — GenericTimelineById ベースに作り直し、あわせて get_explore_page() を追加しました。(#389)
  • レート制限時の RecursionError — 429 のリカバリ処理が再帰しないようにしました。
  • GuestClient は動作しません。これはライブラリ側では直せません。 User-Agent ヘッダーの送信とユーザー情報の安全な解析は入っていますが(#402, #385)、activate() はそこまで到達しません。実際の X に対して確認したところ、すべてのリクエストは先に x-client-transaction-id のハンドシェイクを通りますが、未ログインのリクエストには webpack マニフェストを含まない約 34 KB のページの殻しか返ってこないため、ハンドシェイクを完了できず、activate() 自体が InvalidSession を送出します。/1.1/guest/activate.json エンドポイントは生きていますが、そこに辿り着けません。ゲストアクセスは X 側で閉じられているため、Cookie を使ってください。(#192)
  • get_latest_friends の 404 — v1.1 エンドポイントが廃止されたため、GraphQL の Following エンドポイント経由にしました。(#397)
  • 'Client' object has no attribute '_ui_metrix' — captcha 解除の処理を修正しました。(#333)
  • get_bookmark_folders().next() が無限ループ — 壊れていたページネーション用パラメータを修正しました。(#334, #335)
  • get_latest_timeline / get_list_tweets が会話ツイートを取りこぼす — home / list の会話エントリも展開するようにしました。(#336, #337, #340)
  • フル解像度の画像 URL を返す Media.source_url(#376)と、引用元ツイートの ID を返す Tweet.quoted_status_id(#222)を追加しました。

その他の修正

上記のほかにも、twifork のコミット履歴から次の修正を取り込んでいます。

  • import twikit がプロセス全体を書き換えない — Windows でイベントループポリシーを勝手に差し替えていたため、playwright などサブプロセスを使うライブラリと併用すると NotImplementedError になっていました。従来の動作が必要な場合だけ、環境変数 TWIKIT_WINDOWS_SELECTOR_LOOP=1 を設定してください。
  • ページネーション — カーソルの無いページで next() / previous() が同じページを取り直し続ける問題、get_lists がリストの無いページで打ち切られる問題を修正しました。count は指定どおりに切り詰め、余剰分は next() で取れます。
  • impersonate= 使用時の送信内容 — json= ボディと files=(メディアのチャンク)が送られず、GraphQL の POST(タイムライン取得や create_tweet)が 422 になったり upload_media が失敗したりする問題を修正しました。Cookie が無関係なホストに送られる問題、古い auth_token が残る問題、twitter.com 向けの csrf Cookie が最初のレスポンス以降で消える問題も修正しています。
  • Replies タブと DM — get_user_tweets(..., 'Replies') で本人の返信ではなく相手のツイートが返っていた問題、固定ツイートの取りこぼし・重複、send_dm の送信者の誤りを修正しました。
  • X の拒否を隠さない — 権限エラー(コード 37 など)を空の結果として握りつぶさず例外を送出します。create_tweet の日次上限のメッセージもそのまま表示します。存在しないリスト・ユーザーは空のオブジェクトではなく NotFound / UserNotFound になります。
  • 通知 — get_notifications('Mentions') で notifications キーが無い新形式のレスポンスに対応しました。
  • get_trends — 無限リトライを修正し、news / sports / entertainment のカテゴリが空で返る問題を修正しました。
  • X が legacy から移動したフィールド — User / Community / Tweet.media(複数枚の添付)/ リツイートの全文 / 開催中の投票などを新しい場所から読みます。Poll.vote は選択肢の番号も受け付けるようになりました(破壊的変更)。
  • 新しいプロパティ — Tweet.url、Tweet.article(Article)、Tweet.source、Tweet.conversation_ids、User.verified_type、パロディ / 自動化ラベル、Conversation、Message.reply_data など。Tweet.urls は常にリストを返します。
  • ログイン — ログインチャレンジをどの順序で来ても処理し、code_callback でコードの入力方法を差し替えられるようにしました。ただしパスワードログイン自体は X 側で廃止されており、LoginRetired を送出します(後述)。
  • x-client-transaction-id のハンドシェイク — 直列化して失敗時にリトライし、Cookie を更新したあとは古いハンドシェイクを捨てます。長時間動かすプロセスでは client.refresh_transaction() で手動更新もできます。
  • エンドポイント — GraphQL の query id と features フラグを 2026 年時点のものへ更新しました。プロフィール取得は listed_count などの統計を返す旧ドキュメントを維持しています。
  • パッケージ — Python の下限を実態(3.10)に合わせ、py.typed を同梱し、httpx>=0.26 の下限を宣言しました。twikit.errors のモジュール docstring に、実際に観測した X のエラーコード一覧と散発的な 404 の原因をまとめています。

X 側の制限(アカウント凍結、Cloudflare / IP ブロック、captcha、自動化の制約)が原因の問題は、ライブラリ側では直しようがないため対象外です。

ブラウザ TLS の偽装(任意)

X の一部のエンドポイントは、リクエスト自体が正しくても httpx 既定の TLS フィンガープリントを 403(HTML)で弾いてきます。オプションの curl_cffi を入れて impersonate= を渡すと、実際のブラウザの TLS フィンガープリントで通信し、この種の 403 を避けられます。

client = Client('ja', impersonate='chrome124')

使い方

Important

パスワードではなく Cookie でログインしてください。 X は Client.login() が使うオンボーディングフローを廃止しており、code 366, "flow name LoginFlow is currently not accessible" を返します。2026-07-29 に実際の x.com で確認したところ、/i/flow/login は /i/jf/onboarding/web にリダイレクトされ、サイトは /i/jfapi/onboarding/web/actions/begin_login に POST します。この POST には難読化されたページ内 JavaScript が生成する約 5 KB の $castle_token が必要で、第一要素としてパスキー / WebAuthn も提示されます。いずれも素の HTTP クライアントからは到達できないため、パスワードログインは動作させられません(ライブラリ側の修正では直りません)。代わりに、ブラウザでログインしたセッションの Cookie を取り出して使ってください。

Cookie の取り出し方: ブラウザで x.com にログインし、開発者ツール(Application / Storage → Cookies)から auth_token と ct0 の値をコピーします。この 2 つだけで十分です。

クライアントを用意して Cookie をセットする。

import asyncio
from twikit import Client

# impersonate= には extras が必要: pip install "twikit[impersonate] @ git+https://github.com/amanetoki7/twikit.git"
# 無いと v1.1 のエンドポイントが Cloudflare のページとともに 403 を返すことがあります。
client = Client('ja', impersonate='chrome124')

async def main():
    # auth_token と ct0 だけで十分です
    client.set_cookies({'auth_token': '...', 'ct0': '...'})
    # または: client.load_cookies('cookies.json')

    if not await client.is_logged_in():
        raise SystemExit('Cookie が無効です。ブラウザから取り直してください。')

    # 次回以降のために保存しておく
    client.save_cookies('cookies.json')

asyncio.run(main())

set_cookies には、ブラウザの拡張機能や Playwright が書き出す形式(name と value を持つ辞書のリスト)もそのまま渡せます。

メディア付きツイートを投稿する。

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)

キーワードで最新のツイートを検索する。

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

その他、よく使う呼び出し。

await client.get_user_tweets('123456', 'Tweets')   # ユーザーのツイート
await client.send_dm('123456789', 'Hello')          # DM を送る
await client.get_trends('trending')                 # トレンド

さらに詳しい例は examples にあります。

主な機能

  • API キー不要 — Web 版をスクレイピングして動作します。

  • 無料・オープンソース(MIT)。

  • twikit の置き換え — インポート名は同じなので、コードはそのままで構いません。

  • ツイート、検索、タイムライン、トレンド、ユーザー、DM、メディア、ブックマークなど。

  • X スペース(Spaces) — 読み取り・検索・作成・公開・モデレーション・終了、HLS ストリーム URL、チャット履歴・ライブチャットに対応。コア機能に追加パッケージは不要です(WebRTC 音声とライブチャットの WebSocket は twikit[spaces])。詳しくは docs/spaces.rst と examples/spaces.py を参照してください。

    space = await client.spaces.get_space('1DXGydznBYWKM')
    stream = await client.spaces.get_stream(space.media_key)   # HLS URL
    chat = await client.spaces.chat(space)                     # 履歴
    created = await client.spaces.create_space(title='こんにちは')  # ライブ開始
    await client.spaces.end_space(created['broadcast']['id'])

本家に無い追加 API

  • Client(impersonate=...) — curl_cffi によるブラウザ TLS の偽装。
  • Client.is_logged_in() — Cookie がまだ有効かを確認します。
  • Client.rate_limit_remaining / Client.rate_limit_reset — 直近のレスポンスに含まれるレート制限の残りとリセット時刻。
  • Client.refresh_transaction() — x-client-transaction-id のハンドシェイクをやり直します。
  • Client.get_dm_inbox()、create_group()、delete_dm_conversation() — DM の受信箱一覧、グループ作成、会話の削除。
  • Client.update_profile()、get_about_account()、get_user_spotlights()、get_user_lists()、get_muted_users()、get_blocked_users()。
  • Client.get_user_mentions()、search_tweets_by_date()、get_thread()、get_tweet_by_url()、get_explore_page()。
  • Client.highlight_tweet()、unhighlight_tweet()、is_tweet_highlighted() と Tweet.highlighted / Tweet.highlight() / Tweet.unhighlight() / Tweet.is_highlighted() — プロフィールの「ハイライト」タブへの追加・解除と、ハイライト済みかの確認(Premium 限定)。X はタイムラインにこのフラグを含めないため、Tweet.highlighted は get_user_highlights_tweets() で取得したツイートか、is_highlighted() を呼んだあとだけ値が入ります。get_user_highlights_tweets() の query id / features も 2026-10 時点のものへ更新しました。
  • Client.pin_tweet()、unpin_tweet() と Tweet.pin() / Tweet.unpin() — プロフィールへのツイートのピン留めと解除(v1.1 account/pin_tweet.json / unpin_tweet.json)。ピンは 1 件だけで、別のツイートをピン留めすると置き換わります。他人のツイートは NotFound、ピン留めしていないツイートの解除は何もせず成功します。レート制限はヘッダーの値ではなく pin / unpin それぞれ 100 回で、詳細は ratelimits.md の脚注にあります(twifork 47c8eff から取り込み)。
  • Client.translate_tweet() と Tweet.translate()、twikit.TweetTranslation — Grok によるポストの翻訳(「ポストを翻訳」ボタンの api.x.com/2/grok/translation.json)。初回はトークン単位のストリームで返り、以後は X 側のキャッシュから全文が 1 回で返ります。翻訳先は dst_lang(省略時はクライアントの言語)。
  • Client.get_original_content_rewards_eligibility()、get_creator_subscriptions_eligibility() — クリエイタースタジオの「オリジナルコンテンツ報酬」「サブスクリプション」の参加条件一覧と達成状況(CreatorEligibility / CreatorRequirement: 条件文、達成済みか、現在値、進捗、注記)。X はこのページを GraphQL ではなく server-driven UI(/i/jfapi/、text/plain の生バイナリ)で返すため、そのデコーダ(client.jetfuel.get() で他のページも取得可)も含みます。
  • Client.get_draft_tweets()、create_draft_tweet()、delete_draft_tweets() / delete_draft_tweet()、post_draft_tweet() と twikit.DraftTweet — 「未送信ポスト」の下書きの一覧・保存(本文、メディア、引用 URL、返信先)・削除・投稿。X に下書き投稿専用の API は無く、Web クライアントと同じく通常の CreateTweet を送ってから下書きを削除します。
  • Client.get_community_notes()、get_community_notes_profile()、get_contributor_community_notes()、get_community_notes_timeline()、rate_community_note() と Tweet.get_community_notes() / CommunityNote.rate() / twikit.CommunityNotesProfile — コミュニティノート。投稿に提案された全ノート(表示前のものを含む)、協力者プロフィール(評価の効果 rating_impact と執筆の効果 writing_impact を Web クライアントと同じ式で算出、参加状態、執筆解放までに必要な評価数)、自分(または任意のエイリアス)が書いたノート、x.com/i/communitynotes の 3 タブ(評価が必要 / 新しいノート / 「役に立った」と評価済み)、ノートの評価(Helpful / SomewhatHelpful / NotHelpful と理由タグ)。GenericTimelineById と BirdwatchFetchOneNote の query id も 2026-10 時点のものへ更新しました。
  • twikit.SearchOptions / twikit.build_query — 検索クエリの組み立て。
  • twikit.Article、twikit.Conversation — 長文記事と DM の会話。
  • twikit.spaces — スペース関連のクラス群(Spaces、Space、SpaceChat、SpaceVoiceSession など)。
  • 例外: ClientTransactionError、InvalidSession(Cookie が無効)、LoginRetired(パスワードログインは廃止)。

ドキュメント

アカウントを守るために

このライブラリは非公式 API を使うため、使い方を誤るとアカウントが凍結される可能性があります。リクエストを送りすぎない、Cookie を使い回す、といった対策を ToProtectYourAccount.md にまとめています。

コミュニティ

本家 twikit の Discord: Discord

コントリビュート

不具合を見つけたとき、修正があるときは、Issues に Issue や Pull Request をお願いします。

役に立ったら、すたー を付けてもらえると励みになります。

クレジット

  • d60/twikit(@d60)— 元になる実装。功績はすべて原作者に帰属します。
  • PawiX25/twifork(@PawiX25 とコントリビューターの皆さん)— 2026 年時点の不具合修正と X スペース対応。このリポジトリはその成果を取り込んでいます(取り込み済みの最新コミット: 47c8eff、2026-10-09、d60/twikit + 97 commits )。
  • 八雲ゆかり ( X/Twitter: @yukari-557fd8 ) - わたしの彼氏です。公式APIしか使ったことないわたしを救ってくれた。このリポジトリがうまれるきっかけにもなりました。彼の実装をまず第一に尊重し、動作を保証します。(取り込み済みの最新コミット: aba1f0e、2026-09-29、d60/twikit + 11 commits )。

GitHubリポジトリは、いずれも MIT ライセンスで公開されています。

免責事項

このリポジトリは独立した非公式プロジェクトであり、X Corp. とは一切の提携・承認・スポンサー関係はありません。「X」および「Twitter」は X Corp. の商標です。利用にあたっては、適用される規約および法令を守ってください。

About

すきくん におしえてもらった ↓ のforkしました パッチあてるといいって聞きました

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages