要するに
InstagramグラフAPIは、開発者がInstagramビジネスアカウントおよびクリエイターアカウントをプログラムで管理できるようにします。FacebookログインOAuth 2.0認証、コンテンツ公開、インサイト、コメント、メッセージングのためのGraphQLベースのエンドポイントを使用し、アプリごとに1時間あたり200件のAPI呼び出しというレート制限があります。このガイドでは、認証設定、コンテンツ公開、インサイト取得、コメント管理、および本番環境での統合戦略について説明します。
はじめに
Instagramには20億人を超える月間アクティブユーザーがおり、2億以上の企業がInstagramビジネスアカウントを利用しています。ソーシャルメディア管理ツール、分析プラットフォーム、またはEコマース統合を構築する開発者にとって、この膨大なオーディエンスにリーチするためにInstagramグラフAPIとの統合は不可欠です。
現実として、10以上のアカウントを管理するソーシャルメディアマネージャーは、手動での投稿、コメント返信、分析の作成に毎週20〜30時間を費やしています。堅牢なInstagram API統合により、コンテンツの公開、コメントのモデレーション、感情分析、およびパフォーマンスレポートが自動化されます。
このガイドでは、完全なInstagramグラフAPI統合プロセスを順を追って説明します。Facebookログイン認証、コンテンツ公開、メディアインサイト、コメント管理、Webhook統合、および本番環境でのデプロイ戦略を学びます。このガイドを読み終える頃には、本番環境に対応したInstagram統合が完了しているでしょう。
InstagramグラフAPIとは?
InstagramグラフAPIは、FacebookグラフAPIを介してInstagramビジネスアカウントおよびクリエイターアカウントへのプログラムによるアクセスを提供します。このAPIは以下を処理します。
- コンテンツ公開(写真、動画、リール、カルーセル)
- メディアインサイトと分析
- コメントとメンションの管理
- ダイレクトメッセージング(InstagramグラフAPI + Messenger Platform経由)
- ハッシュタグとメンションの追跡
- ストーリーの管理
- ショッピングと商品タグ
主な機能
| 機能 | 説明 |
|---|---|
| グラフベースAPI | ノードベースのリソースアクセス |
| OAuth 2.0 | Facebookログイン認証 |
| Webhooks | コメント、メンションのリアルタイム通知 |
| レート制限 | アプリごとに1時間あたり200回の呼び出し |
| コンテンツ公開 | 写真、動画、リール、カルーセル |
| インサイト | エンゲージメント、リーチ、インプレッションの指標 |
| モデレーション | コメント、メンション、メッセージの管理 |
アカウント要件
| アカウントタイプ | APIアクセス |
|---|---|
| ビジネスアカウント | 全APIアクセス |
| クリエイターアカウント | 全APIアクセス |
| 個人アカウント | APIアクセスなし(変換が必要) |
| 非公開アカウント | 限定的なインサイト |
APIアーキテクチャの概要
InstagramはFacebookグラフAPIの構造を使用しています。
https://graph.facebook.com/v18.0/
APIバージョンの比較
| バージョン | ステータス | 終了日 | ユースケース |
|---|---|---|---|
| v18.0 | 現在 | 2026年3月 | すべての新しい統合 |
| v17.0 | 非推奨 | 2026年1月 | 既存の統合 |
| v16.0 | 廃止済み | 期限切れ | 使用不可 |
Facebookは四半期ごとに新しいバージョンをリリースしています。常に最新の安定版バージョンをターゲットにしてください。
はじめに: 認証設定
ステップ1: Facebook開発者アカウントの作成
APIにアクセスする前に:
- Facebook開発者ポータルにアクセスする
- Facebookアカウントでサインインする
- Facebookアプリを作成する(タイプ: ビジネス)
- InstagramグラフAPI製品を追加する
ステップ2: Instagramビジネスアカウントのリンク
InstagramをFacebookページに接続します:
- Facebookページの「設定」>「Instagram」に移動する
- 「アカウントを接続」をクリックする
- Instagramにログインして認証する
- Instagramビジネスアカウントがリンクされていることを確認する
注意: 個人用InstagramアカウントはGraph APIを使用できません。Instagramの設定でビジネスアカウントまたはクリエイターアカウントに変換してください。
ステップ3: アクセストークンの取得
ユーザーアクセストークンを生成します:
const FB_APP_ID = process.env.FB_APP_ID;
const FB_APP_SECRET = process.env.FB_APP_SECRET;
const FB_REDIRECT_URI = process.env.FB_REDIRECT_URI;
// Build authorization URL
const getAuthUrl = (state) => {
const params = new URLSearchParams({
client_id: FB_APP_ID,
redirect_uri: FB_REDIRECT_URI,
scope: 'instagram_basic,instagram_content_publish,instagram_manage_comments,instagram_manage_insights,pages_read_engagement',
state: state
});
return `https://www.facebook.com/v18.0/dialog/oauth?${params.toString()}`;
};
必要な権限
| 権限 | 説明 |
|---|---|
instagram_basic |
基本的なプロフィール情報、メディアリスト |
instagram_content_publish |
写真、動画、カルーセルの公開 |
instagram_manage_comments |
コメントの読み取り/書き込み |
instagram_manage_insights |
分析データへのアクセス |
pages_read_engagement |
公開のためのページアクセス |
pages_manage_posts |
接続されたページに公開する |
ステップ4: トークンを長期間有効なトークンに交換する
短期間有効なトークンは1時間で期限切れになります。長期間有効なトークン(60日間)に交換します:
const exchangeForLongLivedToken = async (shortLivedToken) => {
const response = await fetch(
`https://graph.facebook.com/v18.0/oauth/access_token?` +
`grant_type=fb_exchange_token&` +
`client_id=${FB_APP_ID}&` +
`client_secret=${FB_APP_SECRET}&` +
`fb_exchange_token=${shortLivedToken}`
);
const data = await response.json();
return data;
};
// Usage
const longLivedToken = await exchangeForLongLivedToken(shortLivedToken);
console.log(`Token expires: ${new Date(longLivedToken.expires_at * 1000)}`);
ステップ5: InstagramビジネスアカウントIDの取得
接続されているInstagramアカウントを取得します:
const getInstagramAccountId = async (pageId, accessToken) => {
const response = await fetch(
`https://graph.facebook.com/v18.0/${pageId}?fields=instagram_business_account&access_token=${accessToken}`
);
const data = await response.json();
return data.instagram_business_account.id;
};
// Usage
const igAccountId = await getInstagramAccountId('12345678', accessToken);
console.log(`Instagram Account ID: ${igAccountId}`);
ステップ6: 認証されたAPI呼び出しを行う
再利用可能なAPIクライアントを作成します:
const IG_BASE_URL = 'https://graph.facebook.com/v18.0';
const instagramRequest = async (endpoint, params = {}) => {
const url = new URL(`${IG_BASE_URL}${endpoint}`);
url.searchParams.append('access_token', process.env.INSTAGRAM_ACCESS_TOKEN);
Object.entries(params).forEach(([key, value]) => {
url.searchParams.append(key, value);
});
const response = await fetch(url.toString());
if (!response.ok) {
const error = await response.json();
throw new Error(`Instagram API Error: ${error.error.message}`);
}
return response.json();
};
// Usage
const account = await instagramRequest(`/me`);
console.log(`Instagram Account: ${account.username}`);
コンテンツの公開
写真の公開
Instagramに写真を投稿します:
const publishPhoto = async (igAccountId, photoData) => {
// Step 1: Create media container
const containerResponse = await instagramRequest(`/${igAccountId}/media`, {
method: 'POST',
image_url: photoData.imageUrl,
caption: photoData.caption,
location_id: photoData.locationId, // Optional
is_carousel_item: 'false'
});
const creationId = containerResponse.id;
// Step 2: Publish the media
const publishResponse = await instagramRequest(`/${igAccountId}/media_publish`, {
method: 'POST',
creation_id: creationId
});
return publishResponse;
};
// Usage
const post = await publishPhoto({
igAccountId: '17841400000000000',
imageUrl: 'https://example.com/image.jpg',
caption: 'Excited to announce our new product! 🚀 #launch #innovation',
locationId: '123456789' // Optional
});
console.log(`Published media ID: ${post.id}`);
動画の公開
Instagramに動画を投稿します:
const publishVideo = async (igAccountId, videoData) => {
// Step 1: Create media container
const containerResponse = await instagramRequest(`/${igAccountId}/media`, {
method: 'POST',
video_url: videoData.videoUrl,
cover_url: videoData.coverUrl, // Optional thumbnail
caption: videoData.caption,
media_type: 'REELS', // or 'VIDEO' for feed
share_to_feed: 'true' // For reels
});
const creationId = containerResponse.id;
// Wait for video processing (poll until status is EXPIRED or FINISHED)
await waitForVideoProcessing(creationId);
// Step 2: Publish the media
const publishResponse = await instagramRequest(`/${igAccountId}/media_publish`, {
method: 'POST',
creation_id: creationId
});
return publishResponse;
};
const waitForVideoProcessing = async (creationId, maxAttempts = 30) => {
for (let i = 0; i < maxAttempts; i++) {
const status = await instagramRequest(`/${creationId}`);
if (status.status_code === 'FINISHED') {
return true;
} else if (status.status_code === 'EXPIRED') {
throw new Error('Video processing expired');
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
throw new Error('Video processing timeout');
};
カルーセル(複数の画像/動画)の公開
1つの投稿で複数のメディアアイテムを投稿します:
const publishCarousel = async (igAccountId, carouselData) => {
const children = [];
// Step 1: Create each carousel item
for (const item of carouselData.items) {
const containerResponse = await instagramRequest(`/${igAccountId}/media`, {
method: 'POST',
[item.type === 'video' ? 'video_url' : 'image_url']: item.url,
caption: item.caption || '',
is_carousel_item: 'true'
});
children.push(containerResponse.id);
}
// Step 2: Create carousel container with children
const carouselContainerResponse = await instagramRequest(`/${igAccountId}/media`, {
method: 'POST',
media_type: 'CAROUSEL',
children: children.join(','),
caption: carouselData.caption
});
const creationId = carouselContainerResponse.id;
// Step 3: Publish the carousel
const publishResponse = await instagramRequest(`/${igAccountId}/media_publish`, {
method: 'POST',
creation_id: creationId
});
return publishResponse;
};
// Usage
const carousel = await publishCarousel('17841400000000000', {
caption: 'Product showcase 2026',
items: [
{ type: 'image', url: 'https://example.com/img1.jpg', caption: 'Product 1' },
{ type: 'image', url: 'https://example.com/img2.jpg', caption: 'Product 2' },
{ type: 'video', url: 'https://example.com/vid1.mp4', caption: 'Demo' }
]
});
メディアタイプ
| メディアタイプ | パラメータ | ユースケース |
|---|---|---|
IMAGE |
image_url, caption | 写真投稿 |
VIDEO |
video_url, cover_url, caption | 動画投稿 |
REELS |
video_url, cover_url, caption, share_to_feed | リール |
CAROUSEL |
children (配列), caption | 複数メディア |
メディアとインサイトの取得
ユーザーメディアの取得
公開されたメディアを取得します:
const getUserMedia = async (igAccountId, limit = 25) => {
const response = await instagramRequest(`/${igAccountId}/media`, {
fields: 'id,caption,media_type,media_url,permalink,timestamp,like_count,comments_count',
limit: limit.toString()
});
return response;
};
// Usage
const media = await getUserMedia('17841400000000000');
media.data.forEach(item => {
console.log(`${item.media_type}: ${item.caption}`);
console.log(`Likes: ${item.like_count}, Comments: ${item.comments_count}`);
console.log(`URL: ${item.permalink}`);
});
メディアインサイトの取得
特定のメディアの分析データを取得します:
const getMediaInsights = async (mediaId) => {
const response = await instagramRequest(`/${mediaId}/insights`, {
fields: 'impressions,reach,engagement,saved,video_views,profile_visits,follows'
});
return response;
};
// Usage
const insights = await getMediaInsights('17890000000000000');
insights.data.forEach(metric => {
console.log(`${metric.name}: ${metric.values[0].value}`);
});
利用可能なインサイト指標
| 指標 | 説明 | メディアタイプ |
|---|---|---|
impressions |
合計ビュー数 | 全て |
reach |
到達したユニークアカウント数 | 全て |
engagement |
いいね + コメント + 保存 | 全て |
saved |
保存された回数 | 全て |
video_views |
動画視聴回数(3秒以上) | 動画、リール |
plays |
合計動画再生数 | 動画、リール |
profile_visits |
投稿からのプロフィール訪問数 | 全て |
follows |
投稿からのフォロワー数 | 全て |
comments |
コメント数 | 全て |
like_count |
いいね数 | 全て |
アカウントインサイトの取得
アカウントの集計分析データを取得します:
const getAccountInsights = async (igAccountId, metricNames, since = null, until = null) => {
const params = {
metric: metricNames.join(','),
period: 'day'
};
if (since) params.since = since;
if (until) params.until = until;
const response = await instagramRequest(`/${igAccountId}/insights`, params);
return response;
};
// Usage - Get last 30 days of metrics
const accountInsights = await getAccountInsights(
'17841400000000000',
['impressions', 'reach', 'profile_views', 'email_contacts', 'website_clicks'],
'2026-02-23',
'2026-03-25'
);
accountInsights.data.forEach(metric => {
console.log(`${metric.name}:`);
metric.values.forEach(value => {
console.log(` ${value.end_time}: ${value.value}`);
});
});
アカウントレベルの指標
| 指標 | 説明 |
|---|---|
impressions |
合計プロフィール + コンテンツビュー数 |
reach |
到達したユニークアカウント数 |
profile_views |
プロフィール訪問数 |
website_clicks |
プロフィールリンクのクリック数 |
email_contacts |
メールボタンのタップ数 |
phone_call_clicks |
電話ボタンのタップ数 |
text_message_clicks |
SMSボタンのタップ数 |
get_directions_clicks |
住所クリック数 |
follower_count |
合計フォロワー数 |
audience_city |
フォロワーの都市 |
audience_country |
フォロワーの国 |
audience_gender_age |
人口統計の内訳 |
コメント管理
コメントの取得
メディア上のコメントを取得します:
const getMediaComments = async (mediaId, limit = 50) => {
const response = await instagramRequest(`/${mediaId}/comments`, {
fields: 'id,text,timestamp,username,hidden',
limit: limit.toString()
});
return response;
};
// Usage
const comments = await getMediaComments('17890000000000000');
comments.data.forEach(comment => {
console.log(`@${comment.username}: ${comment.text}`);
console.log(`Hidden: ${comment.hidden}`);
});
コメントへの返信
コメントに返信を投稿します:
const replyToComment = async (mediaId, commentId, replyText) => {
const response = await instagramRequest(`/${mediaId}/comments`, {
method: 'POST',
response_to: commentId,
message: replyText
});
return response;
};
// Usage
const reply = await replyToComment(
'17890000000000000',
'17900000000000000',
'Thank you for your interest! Check your DM for details.'
);
console.log(`Reply posted: ${reply.id}`);
コメントの非表示
不適切なコメントを非表示にします:
const hideComment = async (commentId) => {
const response = await instagramRequest(`/${commentId}`, {
method: 'POST',
hide: 'true'
});
return response;
};
// Usage
await hideComment('17900000000000000');
console.log('Comment hidden');
コメントの削除
スパムや不適切なコメントを削除します:
const deleteComment = async (commentId) => {
await instagramRequest(`/${commentId}`, {
method: 'DELETE'
});
console.log('Comment deleted');
};
Webhook
Webhookの構成
リアルタイム通知のためにWebhookを設定します:
const subscribeToWebhooks = async (appId, pageId, accessToken) => {
// Subscribe to Instagram events
const response = await fetch(
`https://graph.facebook.com/v18.0/${appId}/subscriptions`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
object: 'instagram',
callback_url: 'https://myapp.com/webhooks/instagram',
verify_token: process.env.WEBHOOK_VERIFY_TOKEN,
access_token: accessToken,
fields: ['comments', 'mentions', 'message_reactions']
})
}
);
return response.json();
};
Webhookの処理
const express = require('express');
const app = express();
// Webhook購読の検証
app.get('/webhooks/instagram', (req, res) => {
const mode = req.query['hub.mode'];
const token = req.query['hub.verify_token'];
const challenge = req.query['hub.challenge'];
if (mode === 'subscribe' && token === process.env.WEBHOOK_VERIFY_TOKEN) {
console.log('Webhook verified');
res.status(200).send(challenge);
} else {
res.status(403).send('Verification failed');
}
});
// Webhookイベントの処理
app.post('/webhooks/instagram', express.json(), async (req, res) => {
const body = req.body;
if (body.object !== 'instagram') {
return res.status(404).send('Not found');
}
for (const entry of body.entry) {
const igId = entry.id;
const changes = entry.changes;
for (const change of changes) {
switch (change.field) {
case 'comments':
await handleNewComment(change.value);
break;
case 'mentions':
await handleMention(change.value);
break;
case 'message_reactions':
await handleReaction(change.value);
break;
}
}
}
res.status(200).send('OK');
});
async function handleNewComment(data) {
console.log(`New comment on media ${data.media_id}`);
console.log(`From: ${data.from_id}`);
console.log(`Text: ${data.text}`);
// 自動返信またはモデレート
if (isSpam(data.text)) {
await hideComment(data.id);
}
}
Webhookフィールド
| フィールド | トリガー |
|---|---|
comments |
新しいコメントまたは返信 |
mentions |
ユーザーがアカウントをメンション |
message_reactions |
ストーリーへのリアクション |
story_status |
ストーリーの返信/表示 |
レート制限
レート制限の理解
InstagramグラフAPIは以下を適用します:
- アプリごとに1時間あたり200回の呼び出し(すべてのユーザーで共有)
- ビジネスディスカバリー: ユーザーごとに1時間あたり200回の呼び出し
- コンテンツ公開: アクションタイプによって制限されます
制限を超えると、エラーサブコード613を含むHTTP 400が返されます。
レート制限のベストプラクティス
- 応答のキャッシュ - 変更されていないデータを再取得しない
- バッチリクエスト - フィールド展開を使用して呼び出しを減らす
- Webhookの使用 - ポーリングではなくリアルタイム更新
- バックオフの実装 - 429エラーに対する指数関数的バックオフ
const makeRateLimitedRequest = async (endpoint, params = {}, maxRetries = 3) => {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await instagramRequest(endpoint, params);
return response;
} catch (error) {
if (error.message.includes('429') && attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 1000;
console.log(`レート制限に達しました。${delay}ms後に再試行します...`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
};
一般的な問題のトラブルシューティング
問題: OAuthトークンの期限切れ
症状: 「無効なOAuthアクセストークン」エラーが発生する。
解決策:
- 60日間の期限切れ前にトークン更新を実装する
- トークンの有効期限日を保存し、期限切れ前にアラートを出す
- トークンが期限切れの場合、ユーザーを再認証する
問題: メディア公開の失敗
症状: 公開時にエラーが返される。
解決策:
- 画像URLが公開アクセス可能であることを確認する(認証不要)
- 画像の形式(JPEG、PNG)とサイズ(8MB未満)を確認する
- 動画がMP4形式で、1GB未満、90秒未満であることを確認する
- 公開前に動画の処理が完了するのを待つ
問題: インサイトが利用できない
症状: インサイトAPIが空のデータを返す。
解決策:
- アカウントがビジネスまたはクリエイターアカウントであることを確認する(個人アカウントではない)
- インサイトが生成されるまで24〜48時間待つ
- アカウントに十分なアクティビティがあることを確認する
本番デプロイチェックリスト
本番稼働前に:
- [ ] すべてのテストアカウントをビジネス/クリエイターに変換する
- [ ] 長期間有効なトークンでOAuth 2.0を実装する
- [ ] トークンを暗号化して安全に保存する
- [ ] 自動トークン更新を実装する
- [ ] HTTPSでWebhookエンドポイントを設定する
- [ ] レート制限とリクエストキューを追加する
- [ ] 包括的なエラー処理を実装する
- [ ] すべてのAPI呼び出しのロギングを追加する
- [ ] コンテンツモデレーションワークフローを作成する
- [ ] 複数のアカウントタイプでテストする
実世界のユースケース
ソーシャルメディアスケジュールツール
マーケティングプラットフォームは投稿を自動化します:
- 課題: 50以上のクライアントアカウントでの手動投稿
- 解決策: Instagram APIを介したスケジュール公開
- 結果: 80%の時間削減、一貫した投稿スケジュール
主な実装:
- ドラッグアンドドロップによるスケジュール設定が可能なコンテンツカレンダー
- 写真、動画、カルーセルの自動公開
- コンテンツに基づいたハッシュタグの提案
カスタマーサービス自動化
Eコマースブランドはコメントへの応答を自動化します:
- 課題: 顧客からの問い合わせへの応答が遅い
- 解決策: Webhookを介したよくある質問への自動返信
- 結果: 平均応答時間5分、顧客満足度90%
主な実装:
- キーワード検出(価格、在庫、配送)
- 商品リンク付きの自動返信
- 複雑な問い合わせを人間エージェントにエスカレート
結論
InstagramグラフAPIは、Instagramビジネスアカウントおよびクリエイターアカウントの機能への包括的なアクセスを提供します。主なポイントは以下の通りです。
- 60日間有効なトークンによるFacebookログインOAuth 2.0認証
- コンテンツ公開は写真、動画、リール、カルーセルをサポート
- インサイトAPIはエンゲージメント、リーチ、人口統計データを提供
- Webhookはコメントとメンションのリアルタイム監視を可能にする
- アプリごとに1時間あたり200回の呼び出しというレート制限には慎重な管理が必要
- ApidogはAPIテストとチームコラボレーションを効率化する
FAQセクション
Instagram APIにアクセスするにはどうすればよいですか?
Facebook開発者アカウントを作成し、ビジネスアプリを作成し、InstagramグラフAPI製品を追加し、必要な権限でFacebookログインを介して認証します。
Instagramに自動的に投稿できますか?
はい、コンテンツ公開APIを使用して、写真、動画、リール、カルーセルをビジネスアカウントおよびクリエイターアカウントに公開できます。
Instagram APIをサポートするアカウントタイプは何ですか?
ビジネスアカウントとクリエイターアカウントのみが完全なAPIアクセス権を持ちます。個人アカウントはAPIアクセスが制限されているか、利用できません。
Instagramからコメントを取得するにはどうすればよいですか?
コメントエンドポイント(/{media-id}/comments)を使用して、特定のメディアのコメントを取得します。Webhookはリアルタイム通知を提供します。
Instagramのレート制限は何ですか?
InstagramグラフAPIは、アプリごとに1時間あたり200回の呼び出しを許可しています。一部のエンドポイントには、追加のユーザーごとの制限があります。
API経由でストーリーを公開できますか?
はい、ストーリーはフィード投稿と同じコンテンツ公開フローを使用して公開できます。
Instagramインサイトにアクセスするにはどうすればよいですか?
OAuth中にinstagram_manage_insights権限をリクエストします。インサイトエンドポイントを使用して、メディアとアカウントの指標を取得します。
コメントに自動返信できますか?
はい、コメントAPIを使用して返信を投稿できます。多くのブランドが自動カスタマーサービス応答のためにこれを利用しています。
