はじめに (対象読者・この記事でわかること)
この記事は、Flutterでモバイルアプリ開発を行っているエンジニア、特にInstagramのデータを活用したい方を対象としています。Flutterの基本的な知識はあるが、外部API、特にInstagram Graph API の認証フローやエンドポイントの扱いに不安があるという方に最適です。本記事を読むことで、以下ができるようになります。
- Instagram ビジネスアカウントまたはクリエイターアカウントのアクセストークン取得手順
- Flutter アプリから Graph API を呼び出し、指定したユーザーのメディアオブジェクト(画像・動画・キャプション)を取得
- 取得したデータを
ListViewで表示し、簡易的なフィード UI を実装
背景として、2024 年に Instagram が従来の旧 API を完全に廃止し、Graph API が唯一の公式手段となった点があります。そのため、最新の認証方式とデータ取得手順を把握しておくことが、今後のアプリ開発で必須となります。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。
- Flutter の基本的なプロジェクト構成と Dart の文法
- HTTP 通信(
httpパッケージ)や JSON パースの経験 - Instagram ビジネスアカウントまたはクリエイターアカウントの取得手順(管理画面での設定)
Instagram API の概要と取得したい情報
Instagram Graph API は、Facebook の Graph API の一部として提供されており、認証には OAuth 2.0 が必須です。取得できる主なエンドポイントは次のとおりです。
| エンドポイント | 主な取得項目 | 必要な権限 |
|---|---|---|
/me/media |
メディア ID、キャプション、メディアタイプ、URL、タイムスタンプ | instagram_basic、pages_read_engagement |
/media/{media-id} |
画像/動画の URL、サムネイル、コメント数、いいね数 | 同上 |
今回の目的は、他人のクリエイター/ビジネスアカウント の最新投稿を取得し、アプリ内で一覧表示することです。Graph API では、対象ユーザーのアクセストークン が必要になります。つまり、アプリ側で 自らが所有するビジネスアカウント を通じて、対象アカウントのメディア情報を取得できる構成になります。これにより、サーバーサイドでのプロキシ を介さずに直接 Flutter アプリからデータを取得可能です。
必要な権限と許可取得
instagram_basic
- ユーザーの基本プロフィール情報とメディアへのアクセス権限。pages_read_engagement
- Facebook ページ(ビジネスアカウント)が所有する Instagram アカウントのデータ取得に必要。
これらは Facebook 開発者コンソールでアプリに追加し、認証時に scope パラメータでリクエストします。
具体的な手順と実装
以下では、Flutter アプリ単体 で Instagram Graph API にアクセスし、他人アカウントの投稿を取得するまでのフローをステップごとに示します。
ステップ 1: Facebook 開発者コンソールの設定
- アプリ作成
- https://developers.facebook.com/ へログインし「My Apps」 > 「Create App」 → 「Consumer」テンプレートで作成。 - Instagram Graph API の追加
- 「Add Product」 > 「Instagram」 → 「Set Up」ボタンをクリック。 - アクセストークン取得用のリダイレクト URI 設定
-https://{your-domain}/auth/callbackなど、Flutter 側で受け取れるエンドポイントを登録。ローカル開発の場合はhttps://localhost:8080/auth/callbackを使用。 - 権限のリクエスト
- 「App Review」 > 「Permissions and Features」 でinstagram_basicとpages_read_engagementを追加し、必要なら審査依頼(テストユーザー限定なら不要)。
ステップ 2: OAuth2 認証フローの実装
Flutter 側では flutter_web_auth パッケージを利用し、外部ブラウザで認証画面を表示します。
Dartimport 'package:flutter_web_auth/flutter_web_auth.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; Future<String> obtainAccessToken() async { final clientId = 'YOUR_FACEBOOK_APP_ID'; final redirectUri = 'myapp://auth'; final authUrl = 'https://www.facebook.com/v20.0/dialog/oauth?client_id=$clientId' '&redirect_uri=$redirectUri' '&scope=instagram_basic,pages_read_engagement' '&response_type=code'; // ブラウザで認証させ、リダイレクトされた URL を取得 final result = await FlutterWebAuth.authenticate( url: authUrl, callbackUrlScheme: 'myapp', ); // URL から認可コードを抽出 final code = Uri.parse(result).queryParameters['code']; // 認可コードからアクセストークンを取得 final tokenResponse = await http.get(Uri.parse( 'https://graph.facebook.com/v20.0/oauth/access_token?client_id=$clientId' '&redirect_uri=$redirectUri' '&client_secret=YOUR_APP_SECRET' '&code=$code')); final tokenJson = json.decode(tokenResponse.body); return tokenJson['access_token']; }
ポイント
-redirect_uriはカスタムスキーム (myapp://auth) にすると、認証後に自アプリに戻ることができ、外部サーバー不要です。
- アプリ内でclient_secretを保持するとセキュリティ上問題があるため、実運用ではバックエンドプロキシでトークン取得を行うことが推奨されます。
ステップ 3: 対象アカウントのビジネスアカウント ID を取得
取得したユーザーアクセストークンを使い、自分のビジネスアカウント が管理する 対象アカウント の IG User ID を取得します。
DartFuture<String> getIgUserId(String userAccessToken, String targetUsername) async { // まず自分の Facebook ページ ID を取得 final pagesResp = await http.get(Uri.parse( 'https://graph.facebook.com/v20.0/me/accounts?access_token=$userAccessToken')); final pagesJson = json.decode(pagesResp.body); final pageId = pagesJson['data'][0]['id']; // 1 件目のページを使用 // ページに紐付く Instagram ビジネスアカウント情報を取得 final igResp = await http.get(Uri.parse( 'https://graph.facebook.com/v20.0/$pageId?fields=instagram_business_account&access_token=$userAccessToken')); final igJson = json.decode(igResp.body); final igBusinessAccountId = igJson['instagram_business_account']['id']; // ビジネスアカウントから Username を検索し、対象ユーザーの IG User ID を特定 final searchResp = await http.get(Uri.parse( 'https://graph.facebook.com/v20.0/$igBusinessAccountId?fields=followers_count,username&access_token=$userAccessToken')); // 直接検索 API が無いため、対象ユーザーが自アカウントのフォロワーである前提で取得 // 企業側で公開情報から手動で IG User ID を取得し、コードにハードコーディングする手段もある // ここでは例として取得済みの IG User ID を返す return 'TARGET_IG_USER_ID'; }
注意点
- Graph API には「任意のユーザー ID を検索」するエンドポイントは提供されていません。取得できるのは、自分が管理するビジネスアカウント もしくは 自分がフォローしているユーザー に限られます。そのため、対象アカウントは自社・クライアントが所有するビジネスアカウント に限定するか、事前に IG User ID を取得してコードに組み込む必要があります。
ステップ 4: メディア情報取得エンドポイント呼び出し
対象 IG User ID とアクセストークンが揃ったら、/media エンドポイントで最新 10 件の投稿情報を取得します。
DartFuture<List<dynamic>> fetchMedia(String accessToken, String igUserId) async { final mediaUrl = Uri.parse( 'https://graph.facebook.com/v20.0/$igUserId/media' '?fields=id,caption,media_type,media_url,permalink,thumbnail_url,timestamp' '&limit=10' '&access_token=$accessToken'); final resp = await http.get(mediaUrl); final jsonData = json.decode(resp.body); return jsonData['data']; // List of media objects }
取得したデータは以下のように Flutter の UI にバインドします。
Dartclass InstagramFeedPage extends StatefulWidget { @override _InstagramFeedPageState createState() => _InstagramFeedPageState(); } class _InstagramFeedPageState extends State<InstagramFeedPage> { List<dynamic> _media = []; @override void initState() { super.initState(); _loadFeed(); } Future<void> _loadFeed() async { final token = await obtainAccessToken(); // ステップ2 final igUserId = await getIgUserId(token, 'target_user'); // ステップ3 final media = await fetchMedia(token, igUserId); // ステップ4 setState(() => _media = media); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Instagram Feed')), body: _media.isEmpty ? Center(child: CircularProgressIndicator()) : ListView.builder( itemCount: _media.length, itemBuilder: (context, index) { final item = _media[index]; return Card( margin: EdgeInsets.symmetric(vertical: 8, horizontal: 12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (item['media_type'] == 'IMAGE' || item['media_type'] == 'CAROUSEL_ALBUM') Image.network(item['media_url'], fit: BoxFit.cover, width: double.infinity), if (item['media_type'] == 'VIDEO') Stack( alignment: Alignment.center, children: [ Image.network(item['thumbnail_url'], fit: BoxFit.cover, width: double.infinity), Icon(Icons.play_circle_fill, size: 64, color: Colors.white70), ], ), Padding( padding: const EdgeInsets.all(8.0), child: Text( item['caption'] ?? '', style: TextStyle(fontSize: 14), ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Text( DateTime.parse(item['timestamp']) .toLocal() .toString() .split('.') .first, style: TextStyle(fontSize: 12, color: Colors.grey), ), ), ], ), ); }, ), ); } }
コードのポイント
| ポイント | 説明 |
|---|---|
flutter_web_auth |
外部ブラウザで OAuth2 認証を実施し、カスタムスキームでリダイレクトを捕捉 |
http パッケージ |
Graph API への GET リクエストをシンプルに実装 |
ListView.builder |
取得したメディア配列をスクロール可能なカードリストで表示 |
| メディアタイプ別表示 | 画像と動画で表示ロジックを分岐し、サムネイル上に再生アイコンを重ねる |
ハマった点やエラー解決
-
redirect_uriが一致しないエラー
- 認証時に設定したリダイレクト URL と実際に受信した URL が不一致になるとError validating verification codeが返ります。対策は、開発者コンソールの「Valid OAuth Redirect URIs」 に正確にmyapp://auth(カスタムスキーマ)を登録し、Flutter 側でも同一スキーマでFlutterWebAuth.authenticateを呼び出すことです。 -
instagram_basic権限が不足
- テストユーザーでしか権限が付与されないケースがあります。開発コンソールで「Roles > Test Users」へ対象アカウントを追加し、テストモードで認証すると取得できます。実運用時は Facebook の審査が必要です。 -
Media URL が
nullになる
-media_typeがVIDEOの場合、media_urlは動画本体の URL であり、プレビューにはthumbnail_urlを使用する必要があります。取得フィールドにthumbnail_urlを必ず含めるようにしましょう。 -
取得した IG User ID が取得できない
- Graph API では任意のユーザー ID を直接検索できません。解決策として、対象アカウントの IG User ID(数値)を事前に取得し、ハードコード するか、自社が管理するビジネスページのフォロワーとして対象アカウントを追加 して ID を取得します。
解決策まとめ
| 発生した問題 | 具体的な対処法 |
|---|---|
| リダイレクト URI が不一致 | コンソール側とコード側で同一スキーマを設定、myapp://auth を正確に登録 |
| 権限不足でデータ取得エラー | テストユーザーに権限付与、必要なら審査依頼 |
| 動画サムネイルが表示されない | fields に thumbnail_url を追加し、動画はサムネイルで表示 |
| IG User ID が取得できない | 事前に ID を取得してコードに埋め込むか、対象アカウントを自社ページのフォロワーに追加 |
まとめ
本記事では、Flutter アプリから Instagram Graph API を利用し、クリエイター/ビジネスアカウントの投稿を取得・表示する方法 をステップごとに解説しました。
- OAuth2 認証とアクセストークン取得 の流れを実装し、カスタムスキーマでリダイレクトを処理。
- 対象 IG User ID の取得 は、ビジネスページに紐づくアカウントか、事前に取得した ID を使用する必要がある点を整理。
/mediaエンドポイント で最新投稿を取得し、Flutter のListViewで画像・動画を適切に表示。- 実装時に遭遇しやすいエラー(リダイレクト不一致、権限不足、ID 取得不可)とその具体的な解決策を提示。
これにより、自社アプリ内で Instagram のフィードをシームレスに再現 でき、ユーザーエンゲージメント向上やマーケティング効果の測定が可能になります。次のステップとして、取得したコメントやいいね数の集計、無限スクロール実装、バックエンドでのキャッシュ戦略 など、より高度な機能拡張を検討していきます。
参考資料
- Instagram Graph API 公式ドキュメント
- Flutter Web Auth パッケージ
- Facebook Login の OAuth 2.0 フロー解説記事
- 「実践 Flutter アプリ開発」技術書(2023年版)
