Blog

API YouTube Comments : Guide Complet de Gestion

Maîtrisez l'API YouTube Comments avec des exemples TypeScript pour récupérer, publier et modérer les commentaires. Inclut des conseils d'optimisation de quota.

Par

+8

Publiez partout. Une API.

Try Free

L'API YouTube Comments permet aux développeurs de créer des outils d'engagement puissants qui récupèrent, publient et modèrent les commentaires de manière programmatique. Que vous construisiez un tableau de bord de médias sociaux, un outil de gestion de communauté ou un système de réponse automatisé, comprendre les ressources de commentaires de l'API YouTube Data est essentiel pour créer des intégrations efficaces.

Ce guide couvre tout ce dont vous avez besoin pour implémenter une gestion robuste des commentaires YouTube dans vos applications, de la configuration de l'authentification aux stratégies d'optimisation de quota qui maintiennent votre intégration en bon fonctionnement.

Architecture de l'API YouTube Comments

Introduction à l'API YouTube Data v3

L'API YouTube Data v3 fournit un accès programmatique aux fonctionnalités principales de YouTube, y compris les téléchargements de vidéos, la gestion des playlists et les opérations sur les commentaires. Pour la gestion des commentaires spécifiquement, l'API expose deux ressources principales :

  • CommentThreads : Commentaires de premier niveau sur les vidéos, incluant les métadonnées sur le nombre de réponses
  • Comments : Commentaires individuels, incluant les réponses aux commentaires de premier niveau

L'API suit les conventions RESTful et retourne des réponses JSON. Toutes les opérations sur les commentaires nécessitent une authentification OAuth 2.0 car elles impliquent des données et actions spécifiques à l'utilisateur.

// Base configuration for YouTube API requests
const YOUTUBE_API_BASE = 'https://www.googleapis.com/youtube/v3';

interface YouTubeApiConfig {
  accessToken: string;
  baseUrl: string;
}

const config: YouTubeApiConfig = {
  accessToken: process.env.YOUTUBE_ACCESS_TOKEN || '',
  baseUrl: YOUTUBE_API_BASE,
};

API Key vs Authentification OAuth 2.0

Les opérations sur les commentaires YouTube nécessitent différents niveaux d'authentification selon l'action :

OpérationAPI KeyOAuth 2.0
Lire les commentaires publics
Lire les commentaires sur ses propres vidéos
Publier des commentaires
Répondre aux commentaires
Supprimer des commentaires
Modérer les commentaires

Pour toute opération d'écriture ou accès aux données privées, vous devez utiliser OAuth 2.0. Voici comment configurer le flux OAuth :

interface OAuthConfig {
  clientId: string;
  clientSecret: string;
  redirectUri: string;
  scopes: string[];
}

const oauthConfig: OAuthConfig = {
  clientId: process.env.YOUTUBE_CLIENT_ID || '',
  clientSecret: process.env.YOUTUBE_CLIENT_SECRET || '',
  redirectUri: 'https://yourapp.com/auth/youtube/callback',
  scopes: [
    'https://www.googleapis.com/auth/youtube.force-ssl',
    'https://www.googleapis.com/auth/youtube',
  ],
};

function getAuthUrl(state?: string): string {
  const params = new URLSearchParams({
    client_id: oauthConfig.clientId,
    redirect_uri: oauthConfig.redirectUri,
    scope: oauthConfig.scopes.join(' '),
    response_type: 'code',
    access_type: 'offline',
    prompt: 'consent',
  });

  if (state) {
    params.append('state', state);
  }

  return `https://accounts.google.com/o/oauth2/auth?${params.toString()}`;
}

async function exchangeCodeForToken(code: string): Promise<{
  access_token: string;
  refresh_token: string;
  expires_in: number;
}> {
  const response = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      code,
      client_id: oauthConfig.clientId,
      client_secret: oauthConfig.clientSecret,
      redirect_uri: oauthConfig.redirectUri,
      grant_type: 'authorization_code',
    }),
  });

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

  return response.json();
}

Note : Le scope youtube.force-ssl est requis pour les opérations sur les commentaires. Sans lui, les requêtes d'écriture échoueront avec une erreur 403.

Comprendre le Quota de l'API YouTube (10 000 Unités/Jour)

Le système de quota de l'API YouTube est l'un des concepts les plus importants à comprendre avant de construire toute intégration. Chaque requête API consomme des unités de quota, et vous êtes limité à 10 000 unités par jour par défaut.

Voici la répartition des coûts de quota pour les opérations liées aux commentaires :

OpérationCoût en Quota
commentThreads.list1 unité
comments.list1 unité
commentThreads.insert50 unités
comments.insert (réponse)50 unités
comments.delete50 unités
comments.update50 unités
comments.setModerationStatus50 unités

Avec 10 000 unités par jour, vous pouvez effectuer approximativement :

  • 10 000 opérations de lecture, OU
  • 200 opérations d'écriture, OU
  • Une combinaison des deux
// Quota tracking utility
interface QuotaTracker {
  used: number;
  limit: number;
  operations: Map;
}

const quotaCosts: Record = {
  'commentThreads.list': 1,
  'comments.list': 1,
  'commentThreads.insert': 50,
  'comments.insert': 50,
  'comments.delete': 50,
  'comments.update': 50,
  'comments.setModerationStatus': 50,
};

function createQuotaTracker(dailyLimit: number = 10000): QuotaTracker {
  return {
    used: 0,
    limit: dailyLimit,
    operations: new Map(),
  };
}

function trackQuotaUsage(
  tracker: QuotaTracker,
  operation: string
): { allowed: boolean; remaining: number } {
  const cost = quotaCosts[operation] || 1;
  
  if (tracker.used + cost > tracker.limit) {
    return { allowed: false, remaining: tracker.limit - tracker.used };
  }
  
  tracker.used += cost;
  const currentCount = tracker.operations.get(operation) || 0;
  tracker.operations.set(operation, currentCount + 1);
  
  return { allowed: true, remaining: tracker.limit - tracker.used };
}

Note : Le quota se réinitialise à minuit, heure du Pacifique (PT). Si vous atteignez les limites de quota, vos requêtes échoueront jusqu'à la réinitialisation. Planifiez vos opérations en conséquence.

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

Ressources CommentThreads vs Comments

Comprendre la différence entre ces deux ressources est crucial pour une gestion efficace des commentaires YouTube.

CommentThreads représentent les commentaires de premier niveau sur une vidéo. Chaque thread contient :

  • Le commentaire original (topLevelComment)
  • Le nombre de réponses
  • Optionnellement, un sous-ensemble de réponses

Comments représentent les commentaires individuels, qui peuvent être soit :

  • Des commentaires de premier niveau (accessibles via CommentThreads)
  • Des réponses aux commentaires de premier niveau

Utilisez CommentThreads lorsque vous voulez :

  • Récupérer tous les commentaires de premier niveau sur une vidéo
  • Obtenir le nombre de commentaires et les informations de base sur les réponses
  • Publier un nouveau commentaire de premier niveau

Utilisez Comments lorsque vous voulez :

  • Récupérer toutes les réponses à un commentaire spécifique
  • Publier une réponse à un commentaire existant
  • Mettre à jour ou supprimer un commentaire spécifique
// Type definitions for YouTube comment structures
interface YouTubeCommentSnippet {
  authorDisplayName: string;
  authorProfileImageUrl: string;
  authorChannelId: { value: string };
  textDisplay: string;
  textOriginal: string;
  likeCount: number;
  publishedAt: string;
  updatedAt: string;
}

interface YouTubeComment {
  id: string;
  snippet: YouTubeCommentSnippet;
}

interface YouTubeCommentThread {
  id: string;
  snippet: {
    videoId: string;
    topLevelComment: YouTubeComment;
    totalReplyCount: number;
    isPublic: boolean;
  };
  replies?: {
    comments: YouTubeComment[];
  };
}

Récupérer les Commentaires Vidéo avec l'API YouTube Comments

La récupération des commentaires est l'opération la plus courante. Voici une implémentation complète qui gère la pagination et le décodage des entités HTML :

// Helper to decode HTML entities from YouTube API responses
function decodeHtmlEntities(text: string): string {
  if (!text) return text;
  return text
    .replace(/'/g, "'")
    .replace(/"/g, '"')
    .replace(/&/g, '&')
    .replace(/</g, '<')
    .replace(/>/g, '>')
    .replace(/'/g, "'")
    .replace(///g, '/')
    .replace(/ /g, ' ');
}

interface CommentData {
  commentId: string;
  comment: string;
  created: string;
  from: {
    id: string;
    name: string;
    picture: string;
  };
  likeCount: number;
  replyCount: number;
  platform: 'youtube';
  platformPostId: string;
  replies: CommentData[];
}

interface GetCommentsOptions {
  limit?: number;
  pageToken?: string;
}

interface GetCommentsResult {
  comments: CommentData[];
  pagination: {
    hasMore: boolean;
    pageToken?: string;
  };
}

async function getVideoComments(
  accessToken: string,
  videoId: string,
  options: GetCommentsOptions = {}
): Promise {
  const maxResults = Math.min(options.limit || 25, 100);
  
  const params = new URLSearchParams({
    part: 'snippet,replies',
    videoId: videoId,
    maxResults: maxResults.toString(),
  });

  if (options.pageToken) {
    params.append('pageToken', options.pageToken);
  }

  const response = await fetch(
    `${YOUTUBE_API_BASE}/commentThreads?${params.toString()}`,
    {
      headers: {
        Authorization: `Bearer ${accessToken}`,
      },
    }
  );

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

  const data = await response.json();

  const comments: CommentData[] = (data.items || []).map(
    (thread: YouTubeCommentThread) => {
      const topComment = thread.snippet.topLevelComment.snippet;
      
      const replies: CommentData[] = (thread.replies?.comments || []).map(
        (reply: YouTubeComment) => ({
          commentId: reply.id,
          comment: decodeHtmlEntities(reply.snippet.textDisplay),
          created: reply.snippet.publishedAt,
          from: {
            id: reply.snippet.authorChannelId?.value || '',
            name: reply.snippet.authorDisplayName,
            picture: reply.snippet.authorProfileImageUrl,
          },
          likeCount: reply.snippet.likeCount || 0,
          replyCount: 0,
          platform: 'youtube' as const,
          platformPostId: thread.snippet.videoId,
          replies: [],
        })
      );

      return {
        commentId: thread.snippet.topLevelComment.id,
        comment: decodeHtmlEntities(topComment.textDisplay),
        created: topComment.publishedAt,
        from: {
          id: topComment.authorChannelId?.value || '',
          name: topComment.authorDisplayName,
          picture: topComment.authorProfileImageUrl,
        },
        likeCount: topComment.likeCount || 0,
        replyCount: thread.snippet.totalReplyCount || 0,
        platform: 'youtube' as const,
        platformPostId: thread.snippet.videoId,
        replies,
      };
    }
  );

  return {
    comments,
    pagination: {
      hasMore: !!data.nextPageToken,
      pageToken: data.nextPageToken,
    },
  };
}

Publier des Réponses aux Commentaires

Répondre aux commentaires nécessite l'endpoint comments.insert avec l'ID du commentaire parent :

interface ReplyResult {
  replyId: string;
  text: string;
  publishedAt: string;
}

async function replyToComment(
  accessToken: string,
  parentCommentId: string,
  text: string
): Promise {
  const response = await fetch(
    `${YOUTUBE_API_BASE}/comments?part=snippet`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${accessToken}`,
      },
      body: JSON.stringify({
        snippet: {
          parentId: parentCommentId,
          textOriginal: text,
        },
      }),
    }
  );

  if (!response.ok) {
    const errorBody = await response.text();
    
    // Handle specific error cases
    if (response.status === 403) {
      if (errorBody.includes('commentsDisabled')) {
        throw new Error('Comments are disabled on this video');
      }
      if (errorBody.includes('forbidden')) {
        throw new Error('You do not have permission to comment on this video');
      }
    }
    
    if (response.status === 400) {
      if (errorBody.includes('processingFailure')) {
        throw new Error('Comment processing failed. The comment may contain prohibited content.');
      }
    }
    
    throw new Error(`Failed to post reply: ${response.status} ${errorBody}`);
  }

  const data = await response.json();
  
  return {
    replyId: data.id,
    text: data.snippet.textDisplay,
    publishedAt: data.snippet.publishedAt,
  };
}

// Post a new top-level comment on a video
async function postComment(
  accessToken: string,
  videoId: string,
  text: string
): Promise<{ commentId: string }> {
  const response = await fetch(
    `${YOUTUBE_API_BASE}/commentThreads?part=snippet`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${accessToken}`,
      },
      body: JSON.stringify({
        snippet: {
          videoId,
          topLevelComment: {
            snippet: {
              textOriginal: text,
            },
          },
        },
      }),
    }
  );

  if (!response.ok) {
    const errorBody = await response.text();
    throw new Error(`Failed to post comment: ${response.status} ${errorBody}`);
  }

  const data = await response.json();
  return { commentId: data.id };
}

Opérations de Modération des Commentaires

YouTube fournit des capacités de modération pour les propriétaires de chaînes afin de gérer les commentaires sur leurs vidéos :

type ModerationStatus = 'heldForReview' | 'published' | 'rejected';

interface ModerationResult {
  succes

Une API. 13+ plateformes.

Intégrez les réseaux sociaux en minutes, pas en semaines.

Conçu pour les développeurs. Apprécié par les agences. Fiable pour 6 325 utilisateurs.