Instagram Reelsの自動投稿をAPIで組んだら、コードではなくトークン取得でハマった話
YouTubeに公開されたショート動画を、Instagram Reelsへ自動投稿する仕組みを作りました。コード自体は1時間ほどで動いたのですが、Metaの認証トークンを取得して入れるまでに丸4時間かかりました。同じように管理画面や権限の依存関係でハマる人がいそうなので、実際に動かした手順を共有します。
「歴史の雨音」のショート動画を、Instagram Reelsにも同時に展開するため、自動投稿の仕組みを作りました。YouTubeで新しいショートが公開されたら、30分以内に同じ動画をReelsへ自動投稿するというシンプルなパイプラインです。
動画をダウンロードしてInstagramのサーバーにアップロードし、公開をリクエストするスクリプト自体は1時間ほどで書き上がったのですが、そのスクリプトを動かすために必要な「有効なアクセストークンを1本取得する」という作業に、丸4時間ほど費やすことになりました。
この記事では、Metaのややこしい管理画面や権限設定にどう対処して動く状態まで持っていったのか、その手順とハマりどころをまとめます。
コードは1時間で動いた
Instagram Reelsへの投稿は、Instagram Graph APIを使えば以下の2ステップで完結します。
- 動画の公開URLを渡し、処理コンテナを作成する(
POST /{ig-user-id}/media) - コンテナのステータスが
FINISHEDになるのを待って、公開をリクエストする(POST /{ig-user-id}/media_publish)
コードにすれば数十行の処理です。公開のトリガーも、30分おきにcronで走るシェルスクリプトからYouTube Data APIを叩き、直近で公開された動画があればこのPythonスクリプトを呼び出すだけでした。
問題は、このシンプルなエンドポイントを叩くためのアクセストークンを発行することでした。
アカウントと権限の複雑な依存関係
Meta(旧Facebook)の開発者プラットフォームを触ったことがある方ならご存知かもしれませんが、管理画面や権限まわりの構造はかなりややこしい設計になっています。
Instagramに投稿するためには、以下の要素が正しく紐づいている必要があります。
- 個人用のFacebookアカウント
- Meta for Developersのアプリ
- Facebookページ
- Instagramのプロアカウント(ビジネスまたはクリエイター)
- 上記を束ねるMeta Business Suiteの権限
開発者ポータルでアプリを作ろうとすると、「ビジネス」「消費者」「その他」といった用途を選択する画面になります。用途ごとに選べるパーミッション(権限)が異なり、どれを選べばReelsの投稿ができるのか、公式ドキュメントをざらっと読んだだけでは分かりません。
さらに、Graph API Explorerというテストツールで発行したトークンは、わずか1〜2時間で失効します。サーバーから自動実行するためには、これを60日間有効な「長期トークン」に変換しなければなりません。

画面を行き来しながらトークンを取得し、テスト投稿のコマンドを叩くたびにエラーが返ってきました。
{
"error": {
"message": "(#10) Application does not have permission for this action",
"type": "OAuthException",
"code": 10
}
}
「権限がありません」と言われるものの、どの権限が足りないのか、どの画面で何を許可すればいいのかはエラーメッセージからはわかりませんでした。
ドキュメントを読むのをやめてAPIで直接確認する
管理画面のヘルプや公式ドキュメントを読めば読むほど、説明の矛盾や古いUIの記述に突き当たり、混乱が深まっていきました。AIエージェントに調べてもらっても、「ページ設定のここを開いてリンクしてください」という指示が、実際の画面に存在しないボタンを指していたりします。UIが頻繁に変わっているのかもしれません。
堂々巡りで埒が明かなくなってきたので、私はAIエージェントに「余計な推測を重ねる前に、いま手元にあるトークンの中身を直接APIに問い合わせて確認してほしい」と頼みました。
結果的に、これが突破口になりました。
Metaには、トークンの状態を詳細に検査するためのデバッグエンドポイント(/debug_token)が用意されています。そこに手元のトークンを投げてみると、何が起きているのかがそのまま返ってきました。
- アプリのタイプが「ビジネス」ではなく「なし」になっている
- 必要なパーミッション(
instagram_content_publish)がそもそも付与されていない - 紐づいているInstagramユーザーIDが、プロアカウントのものではない
APIが返してくる情報をもとに設定をひとつずつ見直していくと、何が足りていなかったのかが具体的に整理できるようになりました。
一番手戻りが少なかった認証手順
最終的に、手戻りが少なく、確実に長期トークンを取得できた手順は以下の通りでした。
- アプリの作成:Meta for Developersで「ビジネス」タイプのアプリを作成し、「Instagram Graph API」製品を追加する。
- アカウントの連携:Instagramのアカウント設定からプロアカウント(クリエイター)に切り替え、空のFacebookページを1つ作って紐づける。
- ブラウザでのFacebookログイン:Pythonの軽量ローカルサーバー(
localhost:8000)を立ち上げ、ブラウザからMetaのOAuth認証画面を開いて、instagram_basicとinstagram_content_publishを許可する。 - トークンの長期化:返ってきた認証コードを短期トークンに交換し、さらにアプリのシークレットキーを使って60日有効な長期トークンへと交換する。
管理画面のあちこちにある「トークン生成」ボタンを触るのをやめ、一般的なOAuthのログイン画面を自分のブラウザで踏む形にしたところ、ようやく有効な長期トークンをスムーズに取得できました。
AI生成の申告は投稿したあとからは付けられない
トークンが手に入り、自動投稿が動き出したあとに、もうひとつ落とし穴がありました。
Instagramには、AIによって生成された画像や動画を投稿する際、「AIラベル」を明示するポリシーがあります。手動で投稿していたときは、投稿画面で「AIラベル」のスイッチをオンにしていました。
ところが、API経由で投稿されたReelsをアプリから確認すると、どこにもAIラベルが付いていませんでした。
慌ててInstagramアプリから投稿を編集し、ラベルを後付けしようとしましたが、一度公開されたReelsには、あとからAIラベルを付与する設定項目が存在しないことがわかりました。

MetaのAPIドキュメントを再調査したところ、メディアコンテナを作成する最初のリクエストに、以下のパラメータを添える必要があることがわかりました。
data = {
'media_type': 'REELS',
'video_url': video_url,
'caption': caption,
'is_shared_to_feed': 'true',
'has_consumer_generated_ai_content': 'true', # これが必要
}
このパラメータを指定せずに投稿してしまったReels動画は、プラットフォームの規約を守るため、手作業で一度削除してAPI経由で再投稿することにしました。
自動化で本当に時間を食う場所
今回の実装を通じて改めて感じたのは、現代のAPI連携においては、コードを書く時間以上に、認証と権限の前提を揃えることのほうに多くのエネルギーと時間が取られる、ということでした。
動画をアップロードして公開するロジック自体は、ライブラリを使えば1時間ほどで書けてしまいます。ただ、巨大なプラットフォームが要求する複雑なアカウント間の依存関係や、UI変更で古くなったWeb上の情報やエージェントのアドバイスを読み解く作業には、その何倍もの時間がかかりました。
管理画面のテキストや古い情報を睨んで悩むより、デバッグAPIを叩いて手元のトークンが持っている権限の生データを直接確かめるほうが、結果的に一番の近道でした。
外部プラットフォームとのAPI連携や、SNS運用の自動化パイプラインの構築でお困りの方は、お気軽にご相談ください。現場で実際に試行錯誤した知見をもとに、日々の運用を支える自動化のお手伝いができると思います。