# How do I get all videos from a YouTube channel with an API?

YouTube. Checked October 2026.

Call `GET /v1/youtube/profiles/@{handle}/videos` and pass `meta.cursors.next` back as `cursor` until it is null. Each page lists the channel’s videos with title, length, views, and upload date. Sort with `sort=newest`, `popular`, or `oldest`. Pass `since` to stop at a date.

YouTube keeps Shorts and livestreams on their own tabs, and so does the API. Call `/shorts` and `/livestreams` on the same channel to get those too.

With the YouTube Data API you first look up the channel’s uploads playlist. Then you page through playlistItems.list, up to 50 videos for 1 quota unit. That list mixes videos and Shorts, and nothing marks which is which.

## GET /v1/youtube/profiles/@{handle}/videos

```bash
curl "https://api.openhandle.dev/v1/youtube/profiles/@synthetic_youtube/videos?sort=newest" \
  -H "Authorization: Bearer $OPENHANDLE_API_KEY"
```

```ts
import { OpenHandle } from '@openhandle/sdk';

const openhandle = new OpenHandle({ apiKey: process.env.OPENHANDLE_API_KEY! });
let page = await openhandle.youtube.profile('synthetic_youtube').videos.list({ sort: 'newest' });

while (true) {
    for (const video of page.data) console.log(video.id, video.title);
    const next = await page.next();
    if (!next) break;
    page = next;
}
```

200 OK:

```json
{
  "platform": "youtube",
  "resource": "post",
  "capturedAt": "2026-10-26T18:33:16Z",
  "source": "live",
  "data": [
    {
      "id": "synthvid001",
      "type": "video",
      "title": "Synthetic video 1",
      "url": "https://www.youtube.com/watch?v=synthvid001",
      "approximateCreatedAt": "2026-10-25",
      "createdAtLabel": "1 days ago",
      "duration": 240,
      "author": { "id": "UCsyntheticyoutube000001", "handle": "synthetic_youtube" },
      "metrics": { "views": 1200000, "isApproximate": true }
    }
  ],
  "meta": { "cursors": { "next": "b3BhcXVlLWN1cnNvcg" } }
}
```

Trimmed to one video and the fields this question needs. The channel is in the Test dataset, so you can run it on a free Test key.

## Rounded counts and dates

A channel’s video list on YouTube shows labels like "1.2M views" and "1 day ago". We keep what YouTube shows: the rounded count with `isApproximate: true`, the label in `createdAtLabel`, and an estimated day in `approximateCreatedAt`. For the exact count and time, read the video with `GET /v1/youtube/posts/{videoId}`.

## Every tab of a channel

| Tab | Openhandle call |
|---|---|
| Channel details | GET /v1/youtube/profiles/@handle |
| Videos | GET /v1/youtube/profiles/@handle/videos |
| Shorts | GET /v1/youtube/profiles/@handle/shorts |
| Live | GET /v1/youtube/profiles/@handle/livestreams |
| Playlists | GET /v1/youtube/profiles/@handle/playlists |
| Posts | GET /v1/youtube/profiles/@handle/community-posts |
| Search inside the channel | GET /v1/youtube/profiles/@handle/search?q=term |

Channels take an @handle or a channel ID that starts with UC. Start from a channel URL? `POST /v1/urls/fetch` accepts it.

## When this does not work

These answers are definitive. Store them, do not retry them.

| Situation | Status | Code |
|---|---|---|
| The channel does not exist | 404 | `PROFILE_NOT_FOUND` |
| The cursor came from another channel or sort | 400 | `CURSOR_MISMATCH` |

```json
{
  "error": {
    "code": "PROFILE_NOT_FOUND",
    "message": "This profile was not found.",
    "requestId": "req_01m5…",
    "retryable": false
  }
}
```

Every new workspace starts with 100 free live requests, no card needed.

## Related

- [YouTube API](https://openhandle.dev/apis/youtube): Every YouTube endpoint with examples.
- [Pagination](https://openhandle.dev/docs/concepts/pagination): How cursors work across every list.
- [YouTube Data API alternative](https://openhandle.dev/compare/youtube-data-api-alternative): Quota, transcripts, and how to move your calls.
