Blog

API de Moderação de Comentários do Instagram: Automatize Seus Comentários

Aprenda a automatizar comentários do Instagram usando a Graph API. Construa sistemas de moderação, responda programaticamente e gerencie comentários em escala com TypeScript.

Por

+8

Poste em tudo. Uma API.

Try Free

Gerenciar comentários em múltiplas publicações do Instagram se torna avassalador à medida que sua audiência cresce. A moderação de comentários do Instagram através da Graph API permite que você construa sistemas automatizados que buscam, filtram, respondem e moderam comentários programaticamente. Este guia orienta você na implementação de uma solução completa de gerenciamento de comentários usando TypeScript.

Seja você construindo um painel de mídias sociais, uma ferramenta de suporte ao cliente ou um sistema de engajamento automatizado, entender a API de comentários do Instagram é essencial. Cobriremos tudo, desde autenticação básica até fluxos de moderação avançados com análise de sentimento.

Requisitos de Acesso à API

Antes de poder automatizar comentários do Instagram, você precisa ter o acesso adequado à API configurado. A Instagram Graph API requer uma conta de Desenvolvedor do Facebook e um aplicativo aprovado com permissões específicas.

Permissões Necessárias

Seu aplicativo precisa destes escopos OAuth para trabalhar com comentários:

const INSTAGRAM_SCOPES = [
  'instagram_business_basic',           // Acesso básico à conta
  'instagram_business_content_publish', // Publicar conteúdo
  'instagram_business_manage_comments', // Ler e gerenciar comentários
  'instagram_business_manage_messages', // Necessário para respostas privadas
];

Configuração do Ambiente

Crie um arquivo .env com suas credenciais:

INSTAGRAM_CLIENT_ID=your_client_id
INSTAGRAM_CLIENT_SECRET=your_client_secret
INSTAGRAM_ACCESS_TOKEN=your_long_lived_token
INSTAGRAM_USER_ID=your_business_account_id

Implementação da Troca de Token

Os tokens do Instagram começam como de curta duração (1 hora) e devem ser trocados por tokens de longa duração (60 dias):

interface TokenResponse {
  access_token: string;
  token_type: string;
  expires_in: number;
}

async function exchangeForLongLivedToken(
  shortLivedToken: string,
  clientSecret: string
): Promise<TokenResponse> {
  const baseUrl = 'https://graph.instagram.com';
  
  const response = await fetch(
    `${baseUrl}/access_token?` +
    `grant_type=ig_exchange_token&` +
    `client_secret=${clientSecret}&` +
    `access_token=${shortLivedToken}`,
    { method: 'GET' }
  );

  if (!response.ok) {
    const errorText = await response.text();
    throw new Error(`Token exchange failed: ${response.status} - ${errorText}`);
  }

  return response.json();
}

async function refreshLongLivedToken(
  currentToken: string
): Promise<TokenResponse> {
  const baseUrl = 'https://graph.instagram.com';
  
  const response = await fetch(
    `${baseUrl}/refresh_access_token?` +
    `grant_type=ig_refresh_token&` +
    `access_token=${currentToken}`,
    { method: 'GET' }
  );

  if (!response.ok) {
    const errorText = await response.text();
    throw new Error(`Token refresh failed: ${response.status} - ${errorText}`);
  }

  return response.json();
}

Nota: Tokens de longa duração devem ser atualizados antes de expirarem. Configure um cron job para atualizar tokens pelo menos 7 dias antes da expiração.

Buscando Comentários em Publicações

A base de qualquer sistema de moderação de comentários do Instagram é recuperar comentários de forma eficiente. A API suporta paginação para lidar com publicações com milhares de comentários.

Recuperação Básica de Comentários

interface InstagramUser {
  id: string;
  username: string;
}

interface InstagramComment {
  commentId: string;
  comment: string;
  created: string;
  from: InstagramUser;
  likeCount: number;
  replyCount: number;
  hidden: boolean;
  platform: 'instagram';
  replies: InstagramComment[];
}

interface CommentResponse {
  comments: InstagramComment[];
  pagination: {
    hasMore: boolean;
    cursor?: string;
  };
}

async function getMediaComments(
  accessToken: string,
  mediaId: string,
  options?: { limit?: number; cursor?: string }
): Promise<CommentResponse> {
  const baseUrl = 'https://graph.instagram.com';
  const limit = Math.min(options?.limit || 25, 50);
  
  let url = `${baseUrl}/${mediaId}/comments?` +
    `fields=id,text,timestamp,username,hidden,` +
    `from{id,username},like_count,` +
    `replies{id,text,timestamp,username,hidden,from{id,username},like_count}&` +
    `limit=${limit}&access_token=${accessToken}`;

  if (options?.cursor) {
    url += `&after=${options.cursor}`;
  }

  const response = await fetch(url);
  
  if (!response.ok) {
    const errorText = await response.text();
    throw new Error(`Failed to fetch comments: ${response.status} - ${errorText}`);
  }

  const data = await response.json();

  // Construir mapa de lookup para dados completos do comentário
  const commentDataById = new Map<string, any>();
  (data.data || []).forEach((comment: any) => {
    commentDataById.set(comment.id, comment);
  });

  // Identificar IDs de respostas para filtrar do nível superior
  const allReplyIds = new Set<string>();
  (data.data || []).forEach((comment: any) => {
    (comment.replies?.data || []).forEach((reply: any) => {
      allReplyIds.add(reply.id);
    });
  });

  // Filtrar apenas comentários de nível superior
  const topLevelComments = (data.data || [])
    .filter((comment: any) => !allReplyIds.has(comment.id));

  const comments: InstagramComment[] = topLevelComments.map((comment: any) => ({
    commentId: comment.id,
    comment: comment.text,
    created: comment.timestamp,
    from: {
      id: comment.from?.id,
      username: comment.from?.username || comment.username,
    },
    likeCount: comment.like_count || 0,
    replyCount: comment.replies?.data?.length || 0,
    hidden: comment.hidden || false,
    platform: 'instagram',
    replies: (comment.replies?.data || []).map((reply: any) => {
      const fullReplyData = commentDataById.get(reply.id) || reply;
      return {
        commentId: reply.id,
        comment: fullReplyData.text || reply.text,
        created: fullReplyData.timestamp || reply.timestamp,
        from: {
          id: fullReplyData.from?.id || reply.from?.id,
          username: fullReplyData.from?.username || reply.from?.username,
        },
        likeCount: fullReplyData.like_count || reply.like_count || 0,
        hidden: fullReplyData.hidden || false,
        platform: 'instagram',
        replies: [],
        replyCount: 0,
      };
    }),
  }));

  return {
    comments,
    pagination: {
      hasMore: !!data.paging?.next,
      cursor: data.paging?.cursors?.after,
    },
  };
}

Buscando Todos os Comentários com Paginação

Para publicações com muitos comentários, implemente paginação para recuperar tudo:

async function getAllComments(
  accessToken: string,
  mediaId: string,
  maxComments: number = 1000
): Promise<InstagramComment[]> {
  const allComments: InstagramComment[] = [];
  let cursor: string | undefined;
  
  while (allComments.length < maxComments) {
    const response = await getMediaComments(accessToken, mediaId, {
      limit: 50,
      cursor,
    });
    
    allComments.push(...response.comments);
    
    if (!response.pagination.hasMore || !response.pagination.cursor) {
      break;
    }
    
    cursor = response.pagination.cursor;
    
    // Rate limiting: aguardar entre requisições
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  return allComments.slice(0, maxComments);
}

Build faster with Late

One API call to post everywhere. No OAuth headaches. No platform-specific code.

Free tier • No credit card • 99.97% uptime

Respondendo a Comentários Programaticamente

A capacidade de responder a comentários do Instagram via API programaticamente permite engajamento automatizado, bots de suporte ao cliente e gerenciamento de comunidade em escala.

Implementação de Resposta Pública

interface ReplyResult {
  replyId: string;
  success: boolean;
  error?: string;
}

async function replyToComment(
  accessToken: string,
  commentId: string,
  message: string
): Promise<ReplyResult> {
  const baseUrl = 'https://graph.instagram.com';
  
  try {
    const response = await fetch(
      `${baseUrl}/${commentId}/replies`,
      {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          message,
          access_token: accessToken,
        }),
      }
    );

    if (!response.ok) {
      const errorText = await response.text();
      return {
        replyId: '',
        success: false,
        error: `Reply failed: ${response.status} - ${errorText}`,
      };
    }

    const data = await response.json();
    return {
      replyId: data.id,
      success: true,
    };
  } catch (error) {
    return {
      replyId: '',
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error',
    };
  }
}

Resposta Privada (Mensagem Direta)

O Instagram permite enviar uma DM privada para autores de comentários. Isso é útil para cenários de suporte ao cliente:

interface PrivateReplyResult {
  messageId: string;
  success: boolean;
  error?: string;
}

async function sendPrivateReply(
  accessToken: string,
  igUserId: string,
  commentId: string,
  message: string
): Promise<PrivateReplyResult> {
  const baseUrl = 'https://graph.instagram.com';
  
  try {
    const response = await fetch(
      `${baseUrl}/${igUserId}/messages`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${accessToken}`,
        },
        body: JSON.stringify({
          recipient: {
            comment_id: commentId,
          },
          message: {
            text: message,
          },
        }),
      }
    );

    if (!response.ok) {
      const errorText = await response.text();
      
      // Tratar casos de erro específicos
      if (errorText.includes('551') || errorText.toLowerCase().includes('already')) {
        return {
          messageId: '',
          success: false,
          error: 'Uma resposta privada já foi enviada para este comentário. O Instagram permite apenas uma resposta privada por comentário.',
        };
      }
      
      if (errorText.includes('10903')) {
        return {
          messageId: '',
          success: false,
          error: 'Comentário tem mais de 7 dias. Respostas privadas devem ser enviadas dentro de 7 dias.',
        };
      }
      
      return {
        messageId: '',
        success: false,
        error: `Private reply failed: ${response.status} - ${errorText}`,
      };
    }

    const data = await response.json();
    return {
      messageId: data.message_id || data.id,
      success: true,
    };
  } catch (error) {
    return {
      messageId: '',
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error',
    };
  }
}

Nota: O Instagram permite apenas UMA resposta privada por comentário, e ela deve ser enviada dentro de 7 dias após o comentário ser postado. Planeje sua automação de acordo.

Ocultando e Excluindo Comentários

Uma moderação de comentários do Instagram eficaz requer a capacidade de ocultar comentários inapropriados ou excluir suas próprias respostas.

Ocultar e Desocultar Comentários

async function hideComment(
  accessToken: string,
  commentId: string
): Promise<{ success: boolean; error?: string }> {
  const baseUrl = 'https://graph.instagram.com';
  
  try {
    const response = await fetch(
      `${baseUrl}/${commentId}?hide=true&access_token=${accessToken}`,
      { method: 'POST' }
    );

    if (!response.ok) {
      const errorText = await response.text();
      return {
        success: false,
        error: `Hide failed: ${response.status} - ${errorText}`,
      };
    }

    return { success: true };
  } catch (error) {
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error',
    };
  }
}

async function unhideComment(
  accessToken: string,
  commentId: string
): Promise<{ success: boolean; error?: string }> {
  const baseUrl = 'https://graph.instagram.com';
  
  try {
    const response = await fetch(
      `${baseUrl}/${commentId}?hide=false&access_token=${accessToken}`,
      { method: 'POST' }
    );

    if (!response.ok) {
      const errorText = await response.text();
      return {
        success: false,
        error: `Unhide failed: ${response.status} - ${errorText}`,
      };
    }

    return { success: true };
  } catch (error) {
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error',
    };
  }
}

Excluir Comentários

Você só pode excluir comentários que você fez (suas próprias respostas):

async function deleteComment(
  accessToken: string,
  commentId: string
): Promise<{ success: boolean; error?: string }> {
  const baseUrl = 'https://graph.instagram.com';
  
  try {
    const response = await fetch(
      `${baseUrl}/${commentId}?access_token=${accessToken}`,
      { method: 'DELETE' }
    );

    if (!response.ok) {
      const errorText = await response.text();
      return {
        success: false,
        error: `Delete failed: ${response.status} - ${errorText}`,
      };
    }

    return { success: true };
  } catch (error) {
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error',
    };
  }
}

Filtragem de Comentários e Regras de Moderação

Construir um sistema de moderação automatizado requer definir regras para qual conteúdo sinalizar, ocultar ou responder.

Motor de Regras de Moderação

interface ModerationRule {
  id: string;
  name: string;
  type: 'keyword' | 'regex' | 'sentiment' | 'spam';
  pattern?: string;
  keywords?: string[];
  action: 'hide' | 'flag' | 'delete' | 'reply';
  replyTemplate?: string;
  enabled: boolean;
}

interface ModerationResult {
  commentId: string;
  triggered: boolean;
  matchedRules: string[];
  action: 'hide' | 'flag' | 'delete' | 'reply' | 'none';
  replyMessage?: string;
}

class CommentModerator {
  private rules: ModerationRule[];

  constructor(rules: ModerationRule[]) {
    this.rules = rules.filter(r => r.enabled);
  }

  evaluate(comment: InstagramComment): ModerationResult {
    const matchedRules: string[]

Uma API. 13+ plataformas.

Integre redes sociais em minutos, não semanas.

Criado para desenvolvedores. Adorado por agências. Confiado por 6.325 usuários.