{
  "schema": "https://github.com/wild-card-ai/agents-json/blob/main/schemas/agents.json",
  "info": {
    "name": "CommentShark",
    "description": "AI-powered YouTube comment automation: auto-reply, AI moderation, smart rules, and a suite of free public tools for analyzing any YouTube video's comments.",
    "url": "https://www.commentshark.com",
    "openapi": "https://www.commentshark.com/openapi.json"
  },
  "authentication": {
    "type": "none",
    "notes": "All endpoints below are public and unauthenticated. IP-based rate limiting applies."
  },
  "transport": {
    "protocol": "https",
    "method": "POST",
    "url": "https://www.commentshark.com/api/",
    "contentType": "application/json",
    "notes": "All operations share one URL. Discriminate by the `id` field in the request body (see operations[].rpc)."
  },
  "operations": [
    {
      "rpc": "get-public-comments-request",
      "title": "Fetch a public YouTube video's comments",
      "intent": "Return top-level comments (and optionally inline replies) for any public YouTube video, with server-side sort/filter/limit. Use when an agent needs to read or sample comments without authenticating.",
      "rateLimit": "10 requests / 30 seconds (burst), 60 / hour, 200 / day, per IP",
      "input": {
        "type": "object",
        "required": [
          "id",
          "videoId"
        ],
        "properties": {
          "id": {
            "const": "get-public-comments-request"
          },
          "videoId": {
            "type": "string",
            "description": "YouTube video ID (the 11-char string after v= in the watch URL)."
          },
          "maxComments": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5000,
            "default": 2000,
            "description": "Hard cap on top-level threads fetched from YouTube."
          },
          "sort": {
            "type": "string",
            "enum": [
              "oldest",
              "newest",
              "random"
            ],
            "description": "Order of the returned comments. `random` shuffles via Fisher-Yates."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "description": "Optional cap on returned comments after sort/filter."
          },
          "text": {
            "type": "string",
            "description": "Case-insensitive substring filter against textOriginal."
          },
          "dateBefore": {
            "type": "string",
            "format": "date-time",
            "description": "ISO date — only comments published strictly before this."
          },
          "dateAfter": {
            "type": "string",
            "format": "date-time",
            "description": "ISO date — only comments published strictly after this."
          },
          "uniqueAuthors": {
            "type": "boolean",
            "description": "Dedup so each author appears at most once."
          },
          "includeReplies": {
            "type": "boolean",
            "description": "Include inline replies (up to 5 per thread)."
          }
        }
      },
      "output": {
        "type": "object",
        "required": [
          "id",
          "videoId",
          "totalCommentsScanned",
          "reachedCap",
          "comments"
        ],
        "properties": {
          "id": {
            "const": "get-public-comments-response"
          },
          "videoId": {
            "type": "string"
          },
          "totalCommentsScanned": {
            "type": "integer"
          },
          "reachedCap": {
            "type": "boolean",
            "description": "True if the scan stopped because it hit maxComments before exhausting YouTube."
          },
          "comments": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "commentId": {
                  "type": "string"
                },
                "parentCommentId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Populated for inline replies, null for top-level."
                },
                "authorName": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "authorChannelId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "authorProfileImageUrl": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "textOriginal": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "textDisplay": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "publishedAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "likeCount": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "replyCount": {
                  "type": [
                    "integer",
                    "null"
                  ]
                }
              }
            }
          },
          "error": {
            "type": "object",
            "description": "Populated when YouTube refused to return comments for a terminal reason (comments disabled, video not found).",
            "properties": {
              "code": {
                "type": "string"
              },
              "reason": {
                "type": "string"
              }
            }
          }
        }
      },
      "examples": [
        {
          "description": "Fetch up to 200 random comments on Rick Astley's 'Never Gonna Give You Up'.",
          "request": {
            "method": "POST",
            "url": "https://www.commentshark.com/api/",
            "headers": {
              "Content-Type": "application/json"
            },
            "body": {
              "id": "get-public-comments-request",
              "videoId": "dQw4w9WgXcQ",
              "sort": "random",
              "limit": 200
            }
          },
          "response": {
            "status": 200,
            "body": {
              "id": "get-public-comments-response",
              "videoId": "dQw4w9WgXcQ",
              "totalCommentsScanned": 2000,
              "reachedCap": true,
              "comments": [
                "… 200 comment objects …"
              ]
            }
          }
        }
      ]
    },
    {
      "rpc": "get-video-comment-heatmap-request",
      "title": "Per-video comment timing heatmap",
      "intent": "Return per-hour and per-day-of-week comment counts for a YouTube video, timezone-aware. Use when an agent needs to know *when* people commented (engagement timing, best time to post, launch curve).",
      "rateLimit": "10 requests / 30 seconds (burst), 60 / hour, 200 / day, per IP",
      "input": {
        "type": "object",
        "required": [
          "id",
          "videoId",
          "timezone"
        ],
        "properties": {
          "id": {
            "const": "get-video-comment-heatmap-request"
          },
          "videoId": {
            "type": "string",
            "description": "YouTube video ID."
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone, e.g. 'America/Los_Angeles'."
          },
          "maxComments": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5000,
            "default": 2000
          }
        }
      },
      "output": {
        "type": "object",
        "required": [
          "id",
          "videoId",
          "totalCommentsScanned",
          "reachedCap",
          "timezone",
          "dailyBuckets",
          "hourByDayOfWeek",
          "hourByDate"
        ],
        "properties": {
          "id": {
            "const": "get-video-comment-heatmap-response"
          },
          "videoId": {
            "type": "string"
          },
          "totalCommentsScanned": {
            "type": "integer"
          },
          "reachedCap": {
            "type": "boolean"
          },
          "timezone": {
            "type": "string"
          },
          "dailyBuckets": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "date": {
                  "type": "string",
                  "description": "YYYY-MM-DD in the requested timezone."
                },
                "count": {
                  "type": "integer"
                }
              }
            }
          },
          "hourByDayOfWeek": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "dayOfWeek": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 6,
                  "description": "0 = Sunday."
                },
                "hour": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 23
                },
                "count": {
                  "type": "integer"
                }
              }
            }
          },
          "hourByDate": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "date": {
                  "type": "string"
                },
                "hour": {
                  "type": "integer"
                },
                "count": {
                  "type": "integer"
                }
              }
            }
          },
          "earliestAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "latestAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "reason": {
                "type": "string"
              }
            }
          }
        }
      },
      "examples": [
        {
          "description": "Heatmap for a video, in Los Angeles time.",
          "request": {
            "method": "POST",
            "url": "https://www.commentshark.com/api/",
            "headers": {
              "Content-Type": "application/json"
            },
            "body": {
              "id": "get-video-comment-heatmap-request",
              "videoId": "dQw4w9WgXcQ",
              "timezone": "America/Los_Angeles"
            }
          },
          "response": {
            "status": 200,
            "body": {
              "id": "get-video-comment-heatmap-response",
              "videoId": "dQw4w9WgXcQ",
              "totalCommentsScanned": 2000,
              "reachedCap": true,
              "timezone": "America/Los_Angeles",
              "dailyBuckets": [
                "… { date, count } …"
              ],
              "hourByDayOfWeek": [
                "… { dayOfWeek, hour, count } …"
              ],
              "hourByDate": [
                "… { date, hour, count } …"
              ],
              "earliestAt": "2009-10-25T06:57:33Z",
              "latestAt": "2026-05-17T10:14:02Z"
            }
          }
        }
      ]
    },
    {
      "rpc": "get-video-comment-heatmap-bucket-detail-request",
      "title": "Drill-down for a specific heatmap bucket",
      "intent": "Given a heatmap bucket (a specific day, or a day-of-week × hour cell), return the top videos, top commenters, top liked comments, and engagement stats inside that bucket across the supplied videos. Use as a follow-up after `get-video-comment-heatmap-request`.",
      "rateLimit": "10 requests / 30 seconds (burst), 60 / hour, 200 / day, plus 50 / day specifically for this endpoint (YouTube quota protection), per IP",
      "input": {
        "type": "object",
        "required": [
          "id",
          "videoIds",
          "bucket",
          "timezone"
        ],
        "properties": {
          "id": {
            "const": "get-video-comment-heatmap-bucket-detail-request"
          },
          "videoIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Up to a small number of videos; each costs ~20 YouTube quota units."
          },
          "bucket": {
            "oneOf": [
              {
                "type": "object",
                "required": [
                  "kind",
                  "date"
                ],
                "properties": {
                  "kind": {
                    "const": "day"
                  },
                  "date": {
                    "type": "string",
                    "description": "YYYY-MM-DD in the requested timezone."
                  }
                }
              },
              {
                "type": "object",
                "required": [
                  "kind",
                  "dayOfWeek",
                  "hour"
                ],
                "properties": {
                  "kind": {
                    "const": "weekHour"
                  },
                  "dayOfWeek": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 6
                  },
                  "hour": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 23
                  }
                }
              }
            ]
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone."
          },
          "maxComments": {
            "type": "integer"
          }
        }
      },
      "output": {
        "type": "object",
        "required": [
          "id",
          "totalComments",
          "peakHour",
          "topVideos",
          "topCommenters",
          "topLikedComments",
          "averageLikes",
          "averageReplyDepth"
        ],
        "properties": {
          "id": {
            "const": "get-video-comment-heatmap-bucket-detail-response"
          },
          "totalComments": {
            "type": "integer"
          },
          "peakHour": {
            "type": [
              "integer",
              "null"
            ]
          },
          "topVideos": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "videoId": {
                  "type": "string"
                },
                "count": {
                  "type": "integer"
                }
              }
            }
          },
          "topCommenters": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "authorChannelId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "authorName": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "profileImageUrl": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "count": {
                  "type": "integer"
                }
              }
            }
          },
          "topLikedComments": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "commentId": {
                  "type": "string"
                },
                "videoId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "text": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "likeCount": {
                  "type": "integer"
                },
                "authorName": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "publishedAt": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "averageLikes": {
            "type": "number"
          },
          "averageReplyDepth": {
            "type": "number"
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "reason": {
                "type": "string"
              }
            }
          }
        }
      },
      "examples": [
        {
          "description": "Detail for a specific day across two videos.",
          "request": {
            "method": "POST",
            "url": "https://www.commentshark.com/api/",
            "headers": {
              "Content-Type": "application/json"
            },
            "body": {
              "id": "get-video-comment-heatmap-bucket-detail-request",
              "videoIds": [
                "dQw4w9WgXcQ",
                "9bZkp7q19f0"
              ],
              "bucket": {
                "kind": "day",
                "date": "2024-11-15"
              },
              "timezone": "America/Los_Angeles"
            }
          },
          "response": {
            "status": 200,
            "body": {
              "id": "get-video-comment-heatmap-bucket-detail-response",
              "totalComments": 124,
              "peakHour": 19,
              "topVideos": [
                {
                  "videoId": "dQw4w9WgXcQ",
                  "count": 87
                }
              ],
              "topCommenters": [
                "…"
              ],
              "topLikedComments": [
                "…"
              ],
              "averageLikes": 4.2,
              "averageReplyDepth": 0.3
            }
          }
        }
      ]
    },
    {
      "rpc": "get-video-comment-wordcloud-request",
      "title": "Per-video comment wordcloud",
      "intent": "Return the top-N most frequent terms across a YouTube video's comments, weighted by occurrence. Use to summarize what viewers are talking about.",
      "rateLimit": "10 requests / 30 seconds (burst), 60 / hour, 200 / day, per IP",
      "input": {
        "type": "object",
        "required": [
          "id",
          "videoId"
        ],
        "properties": {
          "id": {
            "const": "get-video-comment-wordcloud-request"
          },
          "videoId": {
            "type": "string"
          },
          "maxComments": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5000,
            "default": 2000
          },
          "maxWords": {
            "type": "integer",
            "default": 150,
            "description": "How many top-N words to return."
          }
        }
      },
      "output": {
        "type": "object",
        "required": [
          "id",
          "videoId",
          "totalCommentsScanned",
          "reachedCap",
          "words"
        ],
        "properties": {
          "id": {
            "const": "get-video-comment-wordcloud-response"
          },
          "videoId": {
            "type": "string"
          },
          "totalCommentsScanned": {
            "type": "integer"
          },
          "reachedCap": {
            "type": "boolean"
          },
          "words": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "text": {
                  "type": "string"
                },
                "weight": {
                  "type": "number"
                }
              }
            }
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "reason": {
                "type": "string"
              }
            }
          }
        }
      },
      "examples": [
        {
          "description": "Top 50 wordcloud terms.",
          "request": {
            "method": "POST",
            "url": "https://www.commentshark.com/api/",
            "headers": {
              "Content-Type": "application/json"
            },
            "body": {
              "id": "get-video-comment-wordcloud-request",
              "videoId": "dQw4w9WgXcQ",
              "maxWords": 50
            }
          },
          "response": {
            "status": 200,
            "body": {
              "id": "get-video-comment-wordcloud-response",
              "videoId": "dQw4w9WgXcQ",
              "totalCommentsScanned": 2000,
              "reachedCap": true,
              "words": [
                {
                  "text": "never",
                  "weight": 8123
                },
                {
                  "text": "rick",
                  "weight": 7041
                }
              ]
            }
          }
        }
      ]
    }
  ]
}