> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go-fetch.io/llms.txt
> Use this file to discover all available pages before exploring further.

# YouTube

> Videos, Shorts and streams from YouTube channels and playlists. scraper_type youtube.

`youtube` collects the videos, Shorts and live streams of YouTube channels, or the videos of a playlist. One result
is one row; most rows are videos.

## Run it

```python Python theme={null}
import os

from gofetch import GoFetchClient

client = GoFetchClient(api_key=os.environ["GOFETCH_API_KEY"])

run = client.actor("youtube").call(run_input={
    "channelUrls": ["https://www.youtube.com/@NobelPrize"],
    "limit": 50,
})

for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row.get("type") in ("video", "shorts", "stream"):
        print(row["date"], row["type"], row["title"], row["viewCount"])
```

```bash cURL theme={null}
curl https://go-fetch.io/api/v1/jobs/create/ \
  -H "X-API-Key: $GOFETCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"scraper_type": "youtube", "config": {"channelUrls": ["https://www.youtube.com/@NobelPrize"], "limit": 50}}'
```

## Inputs

Send channel or playlist links in `channelUrls`. `channelHandles`, `directUrls`, `startUrls` and `urls` are accepted
too, and everything you send is merged.

| Field | Type | Default | What it does |
| - | - | - | - |
| `channelUrls` | list of URLs | | Channels (`https://www.youtube.com/@NobelPrize`, `/channel/UC...`, `/user/...`, `/c/...`) or playlists (`https://www.youtube.com/playlist?list=...`). Send full `https://` links. A handle such as `@NobelPrize` also works. |
| `limit` | integer | 10,000 per channel without a date filter, no cap with one | Rows per channel, from 0 to 1,000,000, across the Videos, Shorts and Live tabs, spent in that order. |
| `maxResultsShorts` | integer | as `limit` | Keeps this many of the channel's rows for Shorts. `0` skips the Shorts tab. |
| `maxResultStreams` | integer | as `limit` | Keeps this many of the channel's rows for live streams. `0` skips the Live tab. |
| `oldestPostDate` | date or date-time | | Only items published on or after this date. `onlyPostsNewerThan` is accepted as another name. Not in the future. |
| `maxTotalChargeUsd` | number | | A spending cap, enforced while the job runs; the job's log notes it. See [Billing](https://docs.go-fetch.io/billing.md#cap-a-job-with-maxtotalchargeusd). |

> [!NOTE]
>
> `limit: 50` on a channel with 50 or more long-form videos returns no Shorts and no streams: set
> `maxResultsShorts` and `maxResultStreams` to keep room for them. `limit: 0` skips the Videos tab, so
> `{"limit": 0, "maxResultsShorts": 100}` collects Shorts only. On a job with a date filter within the last 29 days,
> `maxResultsShorts` and `maxResultStreams` are capped at 200.

A link to one video (`watch?v=`, `/shorts/<id>`, `/live/` or `youtu.be/`) is refused with `400` naming the field:
send its channel instead. Search isn't supported either: a job with only `searchQueries` is refused with `400`.
`downloadSubtitles`, `subtitlesFormat` and `subtitlesLanguage` are accepted and have no effect: subtitles are not
collected. `downloadSubtitles: true`, or a format other than `srt` or a language other than `en`, adds a warning to
the job's log.

A date filter within the last 29 days makes the job a recent crawl, which is billed at its own rate; see
[Billing](https://docs.go-fetch.io/billing.md#rates).

## Output

A real row from a job for @NobelPrize:

```json theme={null}
[
  {
    "id": "QyQPe3TSqUI",
    "title": "“I don’t believe it until I hear it from you!” | Navi Pillay | 2026 Nobel Peace Prize call",
    "url": "https://www.youtube.com/watch?v=QyQPe3TSqUI",
    "type": "video",
    "duration": "4:39",
    "date": "2026-10-09T12:50:00.000Z",
    "dateIsApproximate": false,
    "dateText": null,
    "viewCount": 20000,
    "likes": 415,
    "commentsCount": 33,
    "text": "The Norwegian Nobel Committee were unable to reach new laureate Navi Pillay before they announced her award of the 2026 Nobel Peace Prize.\n \nKristian Berg Harpviken, Director of the Norwegian Nobel Institute, was later able to share the news with her personally after it was announced to the world.\n \nThe 2026 Nobel Peace Prize was awarded to Navanethem “Navi” Pillay for her efforts to promote peace and international law.",
    "thumbnailUrl": "https://i.ytimg.com/vi/QyQPe3TSqUI/maxresdefault.jpg",
    "descriptionLinks": [],
    "hashtags": [],
    "isMonetized": null,
    "isAgeRestricted": false,
    "subtitles": null,
    "input": "https://www.youtube.com/@NobelPrize",
    "inputChannelUrl": "https://www.youtube.com/@NobelPrize",
    "channelName": "Nobel Prize",
    "channelUrl": "https://www.youtube.com/@NobelPrize",
    "channelId": "UC-V6odR7HzLCuqjYeowPjLA",
    "channelDescription": "Welcome to the Nobel Prize’s official YouTube channel, which showcases videos about Nobel Prize-awarded achievements and Nobel Prize laureates.\n\nSince 1901, the Nobel Prize has been awarded in the fields of physics, chemistry, physiology or medicine, literature and peace, while a memorial prize in economic sciences was added in 1968.\n\nPlease note that our YouTube comments are moderated. Abusive, promotional and otherwise inappropriate comments will not be posted.",
    "channelJoinedDate": "Sep 4, 2007",
    "channelLocation": "Sweden",
    "channelAvatarUrl": "https://yt3.googleusercontent.com/ytc/AIdro_l8zejI_q_cg4sBiy7adPG4MQKHz7wyW6IGrcI2wV66jII=s900-c-k-c0x00ffffff-no-rj",
    "channelBannerUrl": null,
    "channelTotalVideos": 2555,
    "channelTotalViews": 101632207,
    "numberOfSubscribers": 835000,
    "isChannelVerified": true,
    "channelDescriptionLinks": [],
    "mediaUrls": [],
    "error": null,
    "note": null
  }
]
```

| Field | Type | What it holds |
| - | - | - |
| `id` | text | The video's id. |
| `type` | text | `video`, `shorts` or `stream` (live, upcoming or premiere). |
| `title`, `text` | text | Title and description. |
| `url` | URL | Link to the video (Shorts link to `/shorts/`). |
| `date` | date-time or null | When it was published (ISO 8601, UTC). |
| `dateIsApproximate`, `dateText` | true / false, text | `true` when `date` was worked out from text such as "1 month ago", which can be about two weeks off; `dateText` is that text. |
| `duration` | text or null | Length as `M:SS` or `H:MM:SS`. |
| `viewCount` | integer or null | Views as YouTube shows them, usually rounded (27K is 27000). |
| `likes`, `commentsCount` | integer or null | Likes and comments; `null` when YouTube did not show them. |
| `thumbnailUrl` | URL | The largest thumbnail. |
| `hashtags` | list of text | Hashtags from the title and description, without `#`. |
| `descriptionLinks` | list | Links in the description, each `{"url", "text"}`. |
| `channelName`, `channelUrl`, `channelId` | text | The channel. |
| `channelDescription`, `channelLocation`, `channelJoinedDate` | text | As the channel's About panel shows them; `channelJoinedDate` is display text such as `Sep 4, 2007`. |
| `numberOfSubscribers`, `channelTotalVideos`, `channelTotalViews` | integer or null | Channel counts; subscribers are rounded as YouTube shows them. |
| `isChannelVerified` | true / false / null | The channel's verified badge. |
| `channelAvatarUrl`, `channelBannerUrl` | URL or null | Channel images. |
| `channelDescriptionLinks` | list of URLs | Links in the channel description. |
| `input`, `inputChannelUrl` | text | The link you sent. A playlist's rows say which playlist only here. |
| `isMonetized`, `subtitles` | null | Always `null`. |
| `isAgeRestricted` | true / false | Not reliable: usually `false`. |
| `mediaUrls` | list | Always empty: videos are not downloaded. |
| `error`, `note` | null | Always `null` on a video row. |

### Other rows

These rows stay in the results but cost nothing: `items_scraped` counts video rows only, so it can be lower than
the `total` of `/results/`.

| Row | When | Looks like |
| - | - | - |
| Channel with nothing to return | One per channel or playlist that yielded no video rows | `error: "DATE_FILTER_TOO_STRICT"` (videos exist, none in your date range) or `"NO_VIDEOS"`, with `aboutChannelInfo` (the channel fields), `url`, `input` and `note` |
| Unsupported link | One per link the API accepted that turns out not to be a channel or playlist (video links are refused at creation) | `type: "unsupported_url"`, `error: "INVALID_CHANNEL_URL"`, `url`, `input`, `note` |

On a daily job over many channels, every channel with nothing new returns one `DATE_FILTER_TOO_STRICT` row, free. A
daily job where nothing new was posted reports `items_scraped: 0` and costs \$0.

## What logged-out means here

**You get:** public videos, Shorts and streams with their titles, descriptions, counts and channel fields.

**Not available:**

* An exact publish date for every video. YouTube withholds it from signed-out visitors for some videos. On a job with
  a date filter within the last 29 days, such videos are left out unless their listing date places them in the range;
  on other jobs they come back with `date: null` or `dateIsApproximate: true`.
* Subtitles, monetisation and dislike counts.
* Private and deleted videos in a playlist; they are skipped.

## Completeness

`scraper_metadata` is `null` unless something you sent failed. Then it holds `targets_failed`: one entry per channel,
playlist or link, with `target`, `reason` (`not_found`, `extraction_failed` or `unknown`), `detail` (for reading, not
parsing) and `retriable`. A channel whose videos were found but none could be read is listed with
`reason: "extraction_failed"` and `retriable: true`. A job where some channels fail and others deliver still
completes.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.