2026年版:Instagram Graph API 使い方ガイド

Ashley Innocent

Ashley Innocent

25 3月 2026

2026年版:Instagram Graph API 使い方ガイド

要するに

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統合が完了しているでしょう。

💡
ApidogはAPI統合テストを簡素化します。Instagramのエンドポイントをテストし、OAuthフローを検証し、API応答を検査し、公開の問題を1つのワークスペースでデバッグできます。API仕様をインポートし、応答をモックし、テストシナリオをチームと共有できます。
ボタン

InstagramグラフAPIとは?

InstagramグラフAPIは、FacebookグラフAPIを介してInstagramビジネスアカウントおよびクリエイターアカウントへのプログラムによるアクセスを提供します。このAPIは以下を処理します。

主な機能

機能 説明
グラフベース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にアクセスする前に:

  1. Facebook開発者ポータルにアクセスする
  2. Facebookアカウントでサインインする
  3. Facebookアプリを作成する(タイプ: ビジネス)
  4. InstagramグラフAPI製品を追加する

ステップ2: Instagramビジネスアカウントのリンク

InstagramをFacebookページに接続します:

  1. Facebookページの「設定」>「Instagram」に移動する
  2. アカウントを接続」をクリックする
  3. Instagramにログインして認証する
  4. 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は以下を適用します:

制限を超えると、エラーサブコード613を含むHTTP 400が返されます。

レート制限のベストプラクティス

  1. 応答のキャッシュ - 変更されていないデータを再取得しない
  2. バッチリクエスト - フィールド展開を使用して呼び出しを減らす
  3. Webhookの使用 - ポーリングではなくリアルタイム更新
  4. バックオフの実装 - 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アクセストークン」エラーが発生する。

解決策:

  1. 60日間の期限切れ前にトークン更新を実装する
  2. トークンの有効期限日を保存し、期限切れ前にアラートを出す
  3. トークンが期限切れの場合、ユーザーを再認証する

問題: メディア公開の失敗

症状: 公開時にエラーが返される。

解決策:

  1. 画像URLが公開アクセス可能であることを確認する(認証不要)
  2. 画像の形式(JPEG、PNG)とサイズ(8MB未満)を確認する
  3. 動画がMP4形式で、1GB未満、90秒未満であることを確認する
  4. 公開前に動画の処理が完了するのを待つ

問題: インサイトが利用できない

症状: インサイトAPIが空のデータを返す。

解決策:

  1. アカウントがビジネスまたはクリエイターアカウントであることを確認する(個人アカウントではない)
  2. インサイトが生成されるまで24〜48時間待つ
  3. アカウントに十分なアクティビティがあることを確認する

本番デプロイチェックリスト

本番稼働前に:


実世界のユースケース

ソーシャルメディアスケジュールツール

マーケティングプラットフォームは投稿を自動化します:

主な実装:

カスタマーサービス自動化

Eコマースブランドはコメントへの応答を自動化します:

主な実装:

結論

InstagramグラフAPIは、Instagramビジネスアカウントおよびクリエイターアカウントの機能への包括的なアクセスを提供します。主なポイントは以下の通りです。

ボタン

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を使用して返信を投稿できます。多くのブランドが自動カスタマーサービス応答のためにこれを利用しています。

ApidogでAPIデザイン中心のアプローチを取る

APIの開発と利用をよりシンプルなことにする方法を発見できる