# YouTube API for agents

> API for Agents · https://apiforagents.dev/platforms/youtube · HTML twin: https://apiforagents.dev/platforms/youtube

Channels, videos and comments from YouTube.

Endpoint: `POST https://apiforagents.dev/v1/youtube`. One op per call. Quote first with `"estimateOnly": true`.

## Prices (USD per record, pay as you go)

| Record | Per record |
|---|---|
| channels | $0.00045 |
| comments | $0.00045 |
| videos | $0.00045 |

## Operations

### channels

Channel cards for up to ten channels, by @handle, UC… id or pasted channel URL. `include.videos` adds each channel's recent videos to the same answer.

| Field | Required | Type | Meaning |
|---|---|---|---|
| subjects | yes | list of string (1-10 items) | @handles, UC… ids or channel URLs. |
| include | no | object |  |
| include.videos | no | object |  |
| include.videos.limit | no | integer (1-50) | Recent videos to fetch per channel, newest first; 1-50. |
| include.videos.since | no | string (YYYY-MM-DD) | Only videos published on or after this day (YYYY-MM-DD). |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| handle | string |
| channelId | string |
| name | string |
| description | string |
| avatarUrl | string |
| bannerUrl | string |
| country | string |
| isVerified | boolean |
| joinedOn | string |
| links | list of string |
| subscribers | integer |
| totalVideos | integer |
| totalViews | integer |
| channelUrl | string |
| canonicalHandle | string |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/youtube \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"channels","subjects":["@mkbhd"]}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "handle": "@mirapilates",
    "name": "Mira Pilates",
    "description": "Short pilates classes you can do at home.",
    "country": "IN",
    "isVerified": true,
    "joinedOn": "2019-03-11",
    "subscribers": 412000,
    "totalVideos": 318,
    "totalViews": 52100000,
    "channelId": "495749829",
    "avatarUrl": "https://img.youtube.com/mira-pilates.jpg",
    "bannerUrl": "https://img.youtube.com/mira-pilates.jpg",
    "details": {}
  },
  {
    "handle": "@northfoldhq",
    "name": "Northfold",
    "description": "Finance, made calmer.",
    "country": "GB",
    "isVerified": false,
    "joinedOn": "2020-07-02",
    "subscribers": 18400,
    "totalVideos": 96,
    "totalViews": 1240000,
    "channelId": "3181161809",
    "avatarUrl": "https://img.youtube.com/northfold.jpg",
    "bannerUrl": "https://img.youtube.com/northfold.jpg",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=youtube&op=channels (sign in first).

### videos

One channel's recent videos with views, likes and comments. Includes the channel card when held. A date floor always fetches fresh.

| Field | Required | Type | Meaning |
|---|---|---|---|
| subject | yes | string (≤400 chars) | One @handle, UC… id or channel URL. |
| limit | no | integer (1-50) |  |
| since | no | string (YYYY-MM-DD) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| videoId | string |
| title | string |
| description | string |
| kind | string |
| publishedAt | string |
| durationS | integer |
| category | string |
| keywords | list of string |
| isLive | boolean |
| thumbnailUrl | string |
| permalink | string |
| views | integer |
| likes | integer |
| comments | integer |
| channelHandle | string |
| channelNativeId | string |
| channelName | string |
| channelUrl | string |
| channelSubscribers | string |
| channelBadges | list of string |
| captions | list of object |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/youtube \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"videos","subject":"@mkbhd","limit":10}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "channelHandle": "@cookwithkai",
    "title": "One-pan laksa in 25 minutes",
    "kind": "video",
    "publishedAt": "2026-10-09",
    "durationS": 902,
    "category": "Howto & Style",
    "views": 1210000,
    "likes": 41200,
    "comments": 1830,
    "keywords": [
      "laksa",
      "one pan",
      "weeknight"
    ],
    "videoId": "2831094151",
    "isLive": false,
    "thumbnailUrl": "https://img.youtube.com/one-pan-laksa-in-25-minutes.jpg",
    "permalink": "https://www.youtube.com/one-pan-laksa-in-25-minutes-1000",
    "channelNativeId": "247899388",
    "details": {}
  },
  {
    "channelHandle": "@cookwithkai",
    "title": "Crispy rice, 3 ways",
    "kind": "short",
    "publishedAt": "2026-10-06",
    "durationS": 48,
    "category": "Howto & Style",
    "views": 2830000,
    "likes": 120400,
    "comments": 2210,
    "keywords": [
      "rice",
      "shorts"
    ],
    "videoId": "2788502292",
    "isLive": false,
    "thumbnailUrl": "https://img.youtube.com/crispy-rice-3-ways.jpg",
    "permalink": "https://www.youtube.com/crispy-rice-3-ways-1001",
    "channelNativeId": "3627234726",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=youtube&op=videos (sign in first).

### comments

Top comments on up to ten VIDEOS, by watch/shorts URL or bare video id. Commenters are free text. Not corpus members.

| Field | Required | Type | Meaning |
|---|---|---|---|
| subjects | yes | list of string (1-10 items) | Watch/shorts URLs or bare video ids. |
| limit | no | integer (1-100) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| commentId | string |
| author | string |
| authorChannelId | string |
| body | string |
| likes | integer |
| replies | integer |
| postedAt | string |
| isOwner | boolean |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/youtube \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"comments","subjects":["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],"limit":50}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "author": "@ravi_k",
    "body": "Made this last night, the whole family loved it.",
    "likes": 812,
    "replies": 14,
    "postedAt": "2026-10-10",
    "isOwner": false,
    "commentId": "2563345527",
    "authorChannelId": "2543720091",
    "details": {}
  },
  {
    "author": "@lena.m",
    "body": "Can I use coconut cream instead of milk?",
    "likes": 236,
    "replies": 3,
    "postedAt": "2026-10-10",
    "isOwner": false,
    "commentId": "1328958082",
    "authorChannelId": "1219906403",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=youtube&op=comments (sign in first).

### history (free)

The stored time series. Free, reads only what captures already wrote.

| Field | Required | Type | Meaning |
|---|---|---|---|
| subjects | yes | list of string (1-10 items) | @handles, UC… ids or channel URLs. |
| metric | no | enum |  Values: subscribers, total_videos, total_views. |
| days | no | integer (1-730) |  |

Request shape:

```json
{
  "op": "history",
  "subjects": [
    "example"
  ]
}
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=youtube&op=history (sign in first).

## Notes for the agent

Measured YouTube data, one operation per call. Channels come from evidence (a pasted channel URL, an @handle you SAW, a UC… id). Never typed from a person's name. ops: channels (subjects = @handles, UC ids or channel URLs; add include.videos to get each channel's recent videos IN THE SAME CALL), videos (one channel, deep. Includes the channel card when held; views, likes, comments, duration and absolute publish dates per video), comments (top comments on videos by watch/shorts URL or id), history (stored subscriber/video/view series, free). Ops are independent. Issue several as PARALLEL tool calls. Fresh fetches are charged per record; your own answer is free while fresh.
