X APIはBearer Token(読み取り)とOAuth 2.0 PKCE(書き込み)の2種類を使い分けることで安全に自動化できる。
- 要点1: Bearer Tokenは公開情報の読み取りのみ。投稿・フォローにはOAuth 2.0 PKCEが必要
- 要点2: CLIツール用途ではNative App(Public Client)が最適。Client Secretが不要でシンプル
- 要点3: macOS KeychainでAPIキーを管理することでコードへのハードコードを防げる
対象: Claude CodeでX APIを活用して業務自動化したいエンジニア・DX推進担当者
今日やること: Developer Portalでアプリを作成し、Bearer TokenとClient IDをKeychainに登録する
この記事の目次
X APIを使えば、Xの投稿作成・競合アカウントのリサーチ・タイムライン監視などの業務を自動化できます。しかし「認証設定でつまずいた」「Bearer Tokenは取れたが投稿できない」「OAuth 2.0 PKCEって何から始めればよいか分からない」という声は多くあります。
この記事では、あるメディア運営者がX APIを活用した投稿自動化を実現するまでの実装経験をもとに、Bearer TokenとOAuth 2.0 PKCEの使い分け、Native Appの選択理由、macOS Keychainによるセキュアな管理方法、そして実際に遭遇したトラブルと解決策を解説します。
X APIの認証方式は2種類 — Bearer TokenとOAuth 2.0 PKCEの使い分け
X API v2では、用途に応じて2つの認証方式を使い分ける必要があります。この違いを理解せずに実装を始めると、後から大幅な修正が必要になります。
Bearer Token(App-only認証)とは — 読み取り専用の認証
Bearer Tokenは「アプリ自体」として認証する方式です。特定のユーザーとして操作するのではなく、アプリケーションとして公開情報を読み取ります。
設定は簡単で、Developer PortalからBearer Tokenを1回コピーするだけです。有効期限もなく、更新不要で使い続けられます。
Bearer Tokenで可能な操作:– 公開ツイートの検索(/2/tweets/search/recent)- ユーザープロフィールの取得(/2/users)- ツイートの詳細取得(/2/tweets/:id)
一方、「誰かの代わりにツイートする」「特定ユーザーのフォローリストを見る」といった操作は、そのユーザーの許可が必要なためBearer Tokenでは行えません。
OAuth 2.0 PKCE — 投稿・フォローなどユーザー操作に使う認証
OAuth 2.0 PKCEは「ユーザーの代わりに」操作する方式です。PKCEとはProof Key for Code Exchangeの略で、認可コードを安全に交換するための仕組みです。
認証フローはこうなります。まず認可URLをブラウザで開きます。ユーザーがXにログインして「アプリを認証」を押すと、コールバックURLにアクセストークンの元となるコードが返ってきます。そのコードをアクセストークンに交換して保存することで、以降はそのトークンで操作できるようになります。
OAuth 2.0 PKCEで可能な操作:– ツイートの投稿・削除(/2/tweets)- リツイート・いいね- フォロー・アンフォロー- DM送受信(dm.read / dm.writeスコープ追加が必要)- メディアアップロード(media.writeスコープ追加が必要)
2つの認証方式の比較表
| 項目 | Bearer Token | OAuth 2.0 PKCE |
|---|---|---|
| 用途 | 公開情報の読み取り | ユーザーとしての操作 |
| 設定の手間 | 少ない(コピーするだけ) | やや多い(認証フロー実装が必要) |
| 有効期限 | なし | アクセストークンは2時間(リフレッシュトークンで自動更新可) |
| レート制限 | 標準 | OAuth 1.0aの3倍(15分あたり900リクエスト) |
| 必要なもの | Bearer Token | Client ID + 認証フロー実装 |
実務的には、競合アカウントのリサーチや検索はBearer Token、ツイート投稿や下書き作成はOAuth 2.0 PKCEと使い分けるのが基本です。
Developer Portalでアプリを作成する手順
Developer Portalへのアクセスと登録(2026年版)
2026年現在、X APIのDeveloper Portalは console.x.com で提供されています。以前の developer.twitter.com は統合済みです。
登録時の注意点として、2026年1月より従量課金制(pay-per-use)に移行しています。API利用を開始するには最低$5のクレジット購入が必要です。ただし、アプリの作成自体は無料で行えます。
重要な選択肢:Native AppとWeb Appの違い
アプリ作成時に「Type of App」を選択する画面が表示されます。ここでの選択がその後の設定に大きく影響するため、慎重に選んでください。
| アプリ種別 | クライアントタイプ | 必要な認証情報 | 用途 |
|---|---|---|---|
| Native App | Public Client | Client IDのみ | CLIツール、デスクトップアプリ |
| Web App / Automated App or Bot | Confidential Client | Client ID + Client Secret | Webサービス、サーバーサイドアプリ |
Claude CodeなどのCLIツールとして使う場合は、Native Appを選択してください。
実際の実装経験では、最初にWeb Appを選択してしまい、Client SecretとClient IDの両方が必要になって設定が複雑化しました。さらに、Web Appで取得したトークンはPublic ClientのNative App用とは互換性がなく、アプリを作り直す必要が生じました。
Native Appを選ぶと、PKCEのみでセキュリティが担保されるため、Client Secretの管理が不要でシンプルです。
User authentication settingsの設定(Callback URI設定)
アプリ作成後、「User authentication settings」でOAuth 2.0を有効化します。以下の設定が必要です。
| 設定項目 | 値 |
|---|---|
| App permissions | Read and write |
| Type of App | Native App |
| Callback URI / Redirect URL | http://127.0.0.1:3891/callback |
| Website URL | 任意(例: https://example.com) |
Callback URIの登録は必須です。 ここに http://127.0.0.1:3891/callback を登録しておかないと、認証フローの最終ステップで「このURLは登録されていません」というエラーが返ります。この設定を忘れて認証が完了しないというトラブルは非常によく起こります。
ポイントCallback URIは、認証後にブラウザがリダイレクトされるURLです。ローカルで実行する場合は
http://127.0.0.1:3891/callbackのようにlocalhostのポートを指定します。Developer Portalに事前登録していない場合、X側が「不正なリダイレクト先」として認証を拒否します。
Bearer TokenとClient IDの取得
設定が完了したら、「Keys and tokens」タブから以下の2つを取得します。
- Bearer Token: 「Authentication Tokens」の「Bearer Token」横の「Generate」をクリック
- Client ID: 「OAuth 2.0 Client ID and Client Secret」セクションに表示されている「Client ID」をコピー
Native Appの場合、Client Secretは表示されません(不要です)。
\ Claude Codeの導入、何から始めればいいかわかります /
法人向けClaude Code個別指導の無料相談はこちらmacOS KeychainにAPIキーをセキュアに保存する
なぜKeychainを使うのか — APIキー漏洩のリスクを避ける
APIキーをスクリプトに直接書き込む(ハードコード)と、コードをGitHubにプッシュした際に漏洩するリスクがあります。また、環境変数に設定する方法もありますが、シェルの履歴に残ったり、envコマンドで誰でも見られたりする問題があります。
macOS Keychainは、OSレベルでAES-256-GCM暗号化によって保護された認証情報の保管庫です。Macにログインした時点で自動的にアンロックされ、許可されたアプリケーションのみがアクセスできます。
APIキーの管理にKeychainを使うことで、コードへの直接記述を避けつつ、コマンドラインからも安全に値を取得できます。
securityコマンドでKeychainに登録する
macOSの security コマンドを使って、Keychainへの登録・取得が行えます。
登録:
# Bearer Tokenを登録security add-generic-password -a "$USER" -s "X_BEARER_TOKEN" -w "ここにBearer Token"# Client IDを登録security add-generic-password -a "$USER" -s "X_CLIENT_ID" -w "ここにClient ID"
取得:
security find-generic-password -s "X_BEARER_TOKEN" -w
削除(更新時):
security delete-generic-password -s "X_BEARER_TOKEN"# 削除後に再登録security add-generic-password -a "$USER" -s "X_BEARER_TOKEN" -w "新しいBearer Token"
スクリプトからKeychainの値を取得する
Pythonスクリプト内でKeychainの値を取得するには、subprocessモジュールで security コマンドを呼び出します。
import subprocessdef get_keychain_value(service_name: str) -> str: """macOS KeychainからAPIキーを取得する""" result = subprocess.run( ["security", "find-generic-password", "-s", service_name, "-w"], capture_output=True, text=True ) if result.returncode != 0: raise ValueError(f"{service_name}がKeychainに登録されていません") return result.stdout.strip()# 使用例bearer_token = get_keychain_value("X_BEARER_TOKEN")client_id = get_keychain_value("X_CLIENT_ID")
このパターンを使えば、コード内にAPIキーを直接書かずに済みます。(Claude Code Skillsの設計パターンについてはこちら →)
Claude Codeの導入や活用方法について、個別にご相談いただけます。「どの機能から使えばいいか」「自社業務への適用方法を知りたい」といった段階から対応しています。
OAuth 2.0 PKCEの認証フローを実装する
認証フローの全体像(PKCE方式の仕組み)
OAuth 2.0 PKCEの認証は、以下の流れで行います。
1. code_verifier(ランダム文字列)を生成2. code_verifier をSHA-256ハッシュ化して code_challenge を作成3. code_challenge を含む認可URLをブラウザで開く4. ユーザーがXでログインして「アプリを認証」を押す5. コールバックURLに認可コード(code)が返ってくる6. code + code_verifier をX APIに送ってアクセストークンに交換7. アクセストークンをファイルに保存8. 期限切れ(2時間後)になったらリフレッシュトークンで自動更新
PKCEの仕組みのポイントは「code_verifier」と「code_challenge」の関係です。code_verifierはランダム生成された秘密の値で、code_challengeはその変換値(ハッシュ)です。認可URLにはcode_challengeのみを含め、トークン交換時にcode_verifierを送ります。これにより、認可コードが傍受されても、code_verifierを知らない第三者はトークンを取得できません。
Pythonでの実装例 — ローカルコールバックサーバーを立てる
import hashlib, base64, os, secrets, urllib.parsefrom http.server import HTTPServer, BaseHTTPRequestHandlerimport webbrowserCLIENT_ID = get_keychain_value("X_CLIENT_ID")CALLBACK_URL = "http://127.0.0.1:3891/callback"SCOPE = "tweet.read tweet.write users.read offline.access media.write"def generate_pkce(): """code_verifier と code_challenge を生成する""" code_verifier = base64.urlsafe_b64encode(secrets.token_bytes(32)).rstrip(b'=').decode() code_challenge = base64.urlsafe_b64encode( hashlib.sha256(code_verifier.encode()).digest() ).rstrip(b'=').decode() return code_verifier, code_challengedef get_auth_url(code_challenge: str, state: str) -> str: """認可URLを生成する""" params = { "response_type": "code", "client_id": CLIENT_ID, "redirect_uri": CALLBACK_URL, "scope": SCOPE, "state": state, "code_challenge": code_challenge, "code_challenge_method": "S256", } return "https://x.com/i/oauth2/authorize?" + urllib.parse.urlencode(params)
注意点: favicon問題への対処
コールバックサーバーを実装する際、http.server.BaseHTTPRequestHandler を使って「1リクエストだけ受け付けて終了」という実装にすると、ブラウザが送るfavicon.ico取得リクエストが本来のコールバックより先に処理されてしまい、認証が失敗することがあります。
対処法は「認可コード(codeパラメータ)が含まれるリクエストが来るまでループで待ち続ける」実装にすることです。
received_code = Noneclass CallbackHandler(BaseHTTPRequestHandler): def do_GET(self): global received_code parsed = urllib.parse.urlparse(self.path) params = urllib.parse.parse_qs(parsed.query) # codeが含まれていないリクエスト(favicon等)は無視する if "code" in params: received_code = params["code"][0] self.send_response(200) self.end_headers() self.wfile.write(b"Authenticated. You can close this tab.") def log_message(self, format, *args): pass # ログを抑制# サーバーをcodeが取得できるまで動かし続けるserver = HTTPServer(("127.0.0.1", 3891), CallbackHandler)while received_code is None: server.handle_request()
トークンの自動リフレッシュ実装
offline.access スコープを含めて認証すると、リフレッシュトークンが発行されます。アクセストークンの有効期限(2時間)が切れた際に、ユーザーを再認証させることなく自動的にトークンを更新できます。
import json, timeTOKEN_FILE = "~/.x_tokens.json"def load_tokens() -> dict: with open(os.path.expanduser(TOKEN_FILE)) as f: return json.load(f)def save_tokens(tokens: dict): with open(os.path.expanduser(TOKEN_FILE), "w") as f: json.dump(tokens, f)def get_valid_access_token() -> str: """有効なアクセストークンを返す(期限切れなら自動リフレッシュ)""" tokens = load_tokens() # 有効期限の10分前にリフレッシュする if tokens["expires_at"] - time.time() < 600: tokens = refresh_access_token(tokens["refresh_token"]) save_tokens(tokens) return tokens["access_token"]
(X APIを使った競合アカウント分析の実装例はこちら →)
\ 業務自動化のお悩み、プロが30分で整理します /
法人向けClaude Code個別指導の無料相談はこちらよくあるエラーと解決策 — 実際に遭遇したトラブル事例
401エラーが続く — OAuth 1.0aからOAuth 2.0 PKCEへの切り替えで解決
あるメディア運用者が最初にOAuth 1.0aで実装を試みたところ、API KeyとAccess Tokenを正しく設定しているにも関わらず401エラーが続きました。Access Tokenを再生成しても、Keychain登録をやり直しても解消しませんでした。
原因は、X APIの現在の推奨認証方式がOAuth 2.0 PKCEであることを見落としていたことです。Developer ConsoleでUser authentication settingsを確認すると、OAuth 2.0が有効化されておらず、OAuth 1.0a専用の設定になっていました。
解決策: OAuth 2.0を有効化し、Native Appとして認証フローを実装し直すことで、401エラーが完全に解消しました。
補足 OAuth 1.0aも現在も利用できますが、Consumer KeyとAccess Tokenの4つのキー(Consumer Key / Consumer Secret / Access Token / Access Token Secret)を管理する必要があります。OAuth 2.0 PKCEは
X_BEARER_TOKENとX_CLIENT_IDの2つだけで管理できるため、よりシンプルです。
Native AppとWeb Appの選択ミス — CLIツールにはNative Appが最適
最初にWeb App(Confidential Client)を選択してアプリを作成してしまうと、Client IDに加えてClient Secretも必要になります。CLIツールとしてKeychainで管理する場合は問題ありませんが、トークン発行の仕組みが変わるため、既にNative Appで取得したトークンとの互換性がありません。
解決策: Developer Portalで「User authentication settings → Edit」からアプリタイプをNative Appに変更するか、アプリを作り直してください。Native Appに変更するとClient Secretは表示されなくなります(不要です)。
コールバックURIの未登録で認証が完了しない
認証フローを実行してブラウザでXの認証画面を開き、「アプリを認証」を押した後に「コールバックURIが登録されていません」というエラーが返る場合、Developer Portalのコールバック設定が抜けています。
解決策: Developer Portal → App → User authentication settings → Callback URI に http://127.0.0.1:3891/callback を追加してください。
v1.1 media/uploadの廃止 — v2エンドポイントへの移行
2025年3月にX APIのv1.1 media/upload エンドポイントが廃止されました。画像付き投稿が突然403エラーになる場合、このエンドポイントの廃止が原因です。
解決策: /2/media/upload(v2エンドポイント)に移行してください。また、v2のメディアアップロードには media.write スコープが必要なため、トークンを再取得する必要があります(スコープ変更後に再認証が必要です)。
1つのアプリで複数Xアカウントを管理する
OAuth 2.0の仕組み — Client IDは「アプリ」、トークンは「ユーザー認証」
「X Developer Portalで作ったアプリのアカウント以外は使えないのでは?」と思われることがありますが、それは誤解です。
OAuth 2.0の仕組みでは、Client ID(アプリのID)と、ユーザーが「このアプリを使うことを許可する」という認可(アクセストークン)は分離しています。1つのClient IDに対して、何人のユーザーでも認可フローを経てトークンを発行できます。
Client ID(アプリ): 1つ ├── @account_A のアクセストークン → tokens/account_a.json ├── @account_B のアクセストークン → tokens/account_b.json └── @account_C のアクセストークン → tokens/account_c.json
アカウントごとにトークンファイルを分けて管理する
複数アカウントのトークンを管理する実装パターンとして、アカウント名をキーにしたファイル管理が有効です。
import json, osTOKEN_DIR = os.path.expanduser("~/.x_tokens/")def get_token_file(account_name: str) -> str: return os.path.join(TOKEN_DIR, f"{account_name}.json")def switch_account(account_name: str) -> dict: """アカウントを切り替えてそのトークン情報を返す""" token_file = get_token_file(account_name) if not os.path.exists(token_file): raise ValueError(f"{account_name}のトークンが見つかりません。先にauthを実行してください") with open(token_file) as f: return json.load(f)
各アカウントの初回認証時に、ブラウザでそのアカウントにログインした状態で認可フローを実行することで、そのアカウントのトークンが tokens/アカウント名.json に保存されます。(Claude CodeでツイートをXに下書き投稿する方法はこちら →)
\ AI活用の「次の一手」を一緒に考えませんか /
法人向けClaude Code個別指導の無料相談はこちらよくある質問
Q. Bearer TokenとOAuth 2.0 PKCEはどう使い分ければよいですか?
ユーザーの操作を代替する必要があるかどうかで判断します。ツイート検索・ユーザープロフィール取得など「公開情報の読み取り」だけであればBearer Tokenで十分です。ツイートの投稿・いいね・フォローなど「アカウントとして何かを行う」操作にはOAuth 2.0 PKCEが必要です。
Q. Native AppとWeb App(Confidential Client)はどちらを選ぶべきですか?
Claude CodeなどのCLIツールやデスクトップアプリ用途であれば、Native App(Public Client)を選択してください。Web AppはClient Secretの管理が必要になり、CLIツールでは不要な複雑さが加わります。Webサービスやサーバーサイドアプリとして動作する場合はWeb Appが適しています。
Q. 複数のXアカウントを1つのAPIアプリで管理できますか?
できます。Client ID(アプリ)は1つのまま、OAuth 2.0の認可フローで「どのアカウントとして認証するか」を分けられます。各アカウントの認証時に、そのアカウントでXにログインした状態でブラウザを操作することで、アカウントごとに別々のアクセストークンが発行されます。
Q. アクセストークンの有効期限が切れたらどうなりますか?
offline.access スコープを含めて認証していれば、リフレッシュトークンが発行されます。アクセストークン(有効期限2時間)が切れた際に、リフレッシュトークンを使って自動的に新しいアクセストークンを取得できます。再認証(ブラウザでのログイン)は不要です。
Q. X APIの無料プランでできることに制限はありますか?
2026年1月より従量課金制(pay-per-use)に移行しました。最低$5のクレジット購入が必要ですが、使った分だけ課金されるため、個人・小規模での利用コストは抑えられます。ツイート投稿(POST /2/tweets)や読み取り系APIはFree Tierから利用可能です。
まとめ
X APIの認証設定は、最初の選択を誤ると後から修正コストが高くなります。本記事の要点を振り返ります。
- 認証方式の使い分け: 読み取りはBearer Token、書き込みはOAuth 2.0 PKCE
- アプリタイプの選択: CLIツールにはNative App(Client Secretが不要でシンプル)
- Callback URI登録:
http://127.0.0.1:3891/callbackをDeveloper Portalに必ず設定 - セキュアなキー管理: macOS KeychainでBearer TokenとClient IDを管理
- 複数アカウント管理: 1つのClient IDで複数アカウントのトークンを管理できる
次のアクションとして、まずDeveloper Portalで新規アプリを作成し(Native Appを選択)、Bearer TokenとClient IDをKeychainに登録するところから始めてみてください。
Claude Codeの導入・活用をサポートします
株式会社Nexaでは、Claude Codeを活用した業務自動化の個別指導・企業研修を提供しています。X API連携をはじめ、社内業務の自動化・スキル設計まで、3ヶ月で成果を出せるプログラムです。「何から始めればいいかわからない」という段階からご支援いたします。





