# Youtube Channel Scraper (`newbs/youtube-channel`) Actor

Scrape YouTube channels or keyword searches for video URLs, titles, metrics, transcripts, channel profiles, social links, descriptions and more. Fast, low-cost YouTube data extraction for monitoring, influencer research, SEO, and LLM workflows.

- **URL**: https://apify.com/newbs/youtube-channel.md
- **Developed by:** [Newbs](https://apify.com/newbs) (community)
- **Categories:** Social media, Videos
- **Stats:** 2,950 total users, 39 monthly users, 99.2% runs succeeded, 79 bookmarks
- **User rating**: 4.13 out of 5 stars

## Pricing

$35.00/month + usage

To use this Actor, you pay a monthly rental fee to the developer. The rent is subtracted from your prepaid usage every month after the free trial period.You also pay for the Apify platform usage, which gets cheaper the higher Apify subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#rental-actors

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## YouTube Channel Scraper

Scrape YouTube channels or YouTube search results and export clean video data from Apify. This actor collects video URLs, titles, thumbnails, descriptions, views, likes, comments, publish dates, duration, channel profile data, channel social links, and transcripts when YouTube exposes caption tracks.

It is built for teams that need reliable YouTube data without spending minutes clicking through channels manually.

### What You Can Extract

- Latest videos from one or many YouTube channels
- Videos from keyword search results
- Video metadata: title, URL, ID, thumbnail, description, publish date, duration
- Engagement metrics: views, likes, comments
- Channel metadata: handle, subscriber count, profile image, banner image, total videos, total channel views, verification status
- Channel information and clean outbound links from the About section, surfaced as `channelDescription`, `channelLinks`, and table-friendly `channelLinksText`
- Video transcripts from available YouTube captions, plus `transcriptStatus` to explain missing transcripts
- Clean JSON output ready for CSV, Excel, API, Make, Zapier, dashboards, or internal enrichment workflows

### Common Use Cases

- Monitor competitor YouTube channels
- Build influencer and creator lead lists
- Track brand channels and campaign performance
- Collect video metadata for SEO or content research
- Extract transcripts for summarization, search, classification, or LLM pipelines
- Find creator websites, social profiles, storefronts, and lead/contact pages from channel About links
- Feed YouTube data into CRMs, spreadsheets, BI tools, and automation workflows

### Why Use This Actor

- Optimized for speed: channel and video details can run in parallel.
- Balanced proxy use: `proxyMode: "auto"` keeps search/list collection and video detail scraping direct first, then uses proxy-backed HTTP only for hard failures or incomplete core metadata.
- Detail-only proxy control: `videoDetailProxyStrategy: "proxyFirst"` is available for advanced tests when direct video-detail requests are unreliable, while keeping channel/search collection direct.
- Better transcript coverage: direct caption extraction is combined with Innertube caption-track discovery, adaptive proxy recovery when batch coverage is poor, and optional aggressive residential fallback for maximum transcript attempts.
- Clear transcript diagnostics: `transcriptStatus` distinguishes recovered transcripts from no exposed caption tracks, caption fetch failures, and detail fetch failures.
- More resilient runs: incomplete detail rows are retried directly before proxy fallback, and one bad channel URL no longer stops valid sources from returning results.
- Larger-run safety: completed rows stream to the dataset during the run instead of waiting for all videos to finish.
- Cleaner channel lead data: empty social placeholders are removed, and About links are visible in priority dataset views.
- Integration ready: structured input schema, dataset schema, and output schema make results easier to use through the Apify UI, API, MCP, Make, Zapier, and scheduled runs.

Latest Apify benchmark on build `0.0.302`, using 102 normal videos from 6 YouTube channels with standard transcript mode:

- 102/102 rows succeeded.
- 62/102 transcripts were recovered.
- 102/102 rows included `publishedAt`, channel About data, and channel links.
- 0 Shorts, 0 duplicate URLs, and 0 inflated like-count issues were found.
- Runtime was about 135 seconds, about 45 results/minute.
- Apify platform usage was about $0.17 for the run, about $1.69 per 1,000 results.

Actual runtime and cost depend on number of channels, number of videos, selected proxy mode, transcript availability, and YouTube response speed.

### Input

#### Minimal Channel Input

```json
{
  "channel": ["https://www.youtube.com/@adidas/videos", "zara"],
  "keywords": false,
  "numberOfResults": 2,
  "needVideoDetails": true
}
````

#### Keyword Search Input

```json
{
  "channel": ["running shoes", "summer fashion campaign"],
  "keywords": true,
  "numberOfResults": 10,
  "uniqueChannels": true,
  "maxVideosPerChannel": 1,
  "needVideoDetails": true
}
```

#### Fast List-Only Input

Use this when you only need fast data from YouTube list/search results. This mode does not open each video page, so it is much faster. It can still return title, URL, video ID, thumbnail, channel name, channel URL, channel avatar, description snippet, relative publish text, duration, live/upcoming status, and visible view count when YouTube exposes them in the listing.

```json
{
  "channel": ["https://www.youtube.com/@adidas/videos"],
  "keywords": false,
  "numberOfResults": 25,
  "needVideoDetails": false
}
```

### Input Options

| Field | Description |
| --- | --- |
| `channel` | List of YouTube channel handles, channel URLs, `/videos` URLs, direct video URLs, or search terms. Direct video URLs may use `watch?v=`, `youtu.be`, `/embed/`, or `/live/` formats. |
| `keywords` | Set to `true` when `channel` contains search keywords instead of channel names or URLs. |
| `numberOfResults` | Number of videos to collect for each item in `channel`. With `keywords: false`, this is per channel. With `keywords: true`, this is per keyword before duplicate/channel limits are applied. |
| `uniqueChannels` | Keyword mode only. Set to `true` to keep at most one result from each YouTube channel per keyword. Useful for creator discovery and lead lists. |
| `maxVideosPerChannel` | Keyword mode only. Limits how many videos from the same channel are returned for each keyword. Set `1` for one video per creator, or leave empty for no limit. |
| `needVideoDetails` | Set to `true` for full metadata, metrics, channel info, and transcripts. Set to `false` for faster basic video collection. |
| `localeHl` | YouTube language hint, for example `en`, `fr`, or `de`. |
| `localeGl` | YouTube country hint, for example `US`, `FR`, or `DE`. |
| `acceptLanguage` | HTTP language header, for example `en-US,en;q=0.9`. |
| `maxVideoDetailConcurrency` | Number of video detail pages scraped in parallel per channel. |
| `proxyMode` | `auto` is recommended. Keyword/channel collection and video detail requests start direct, then hard failures or incomplete core metadata can retry with proxy-backed HTTP. Missing transcripts only use residential fallback when `transcriptMode` is `aggressive`. Use `always` to proxy collection too, or `never` for maximum speed and lowest cost. |
| `videoDetailProxyStrategy` | Controls only per-video detail requests. Keep `auto` for normal use. Use `proxyFirst` only as an advanced troubleshooting mode when direct video-detail requests are unreliable or caption tracks are hidden. It can increase cost and may be slower. |
| `transcriptMode` | `standard` is faster and cheaper, with adaptive proxy recovery only when batch transcript coverage is poor. `aggressive` retries missing transcripts more eagerly with residential proxy and can recover captions that are blocked from the direct path. |
| `adaptiveTranscriptProxyFallback` | Enabled by default in standard transcript mode. It retries missing transcripts with proxy only when the batch would otherwise have weak transcript coverage. Disable it only when lowest proxy cost matters more than transcript coverage. |
| `adaptiveTranscriptMaxRetries` | Optional cap for adaptive transcript retries. Leave empty for automatic behavior: all missing transcripts on small runs, and up to 80 round-robin rows across channels on larger runs. |
| `adaptiveTranscriptRetryConcurrency` | Optional parallelism for adaptive transcript retries. Leave empty for the default. Increase only when transcript-heavy runs need more speed and your proxy setup can handle the extra parallel requests. |
| `residentialFallbackForMissingTranscripts` | Older compatibility switch for saved inputs. Prefer `transcriptMode: "aggressive"` for new runs. |
| `proxyConfiguration` | Optional Apify Proxy configuration. Leave empty in `auto` mode unless you need custom proxy groups or country settings for fallback or `always` mode. |
| `streamDatasetItems` | Enabled by default. Writes rows as they finish so large runs preserve completed data if the run is interrupted. |

### Output

The actor stores results in the default Apify dataset. You can download the data as JSON, CSV, Excel, XML, RSS, or HTML from the Apify Console, or consume it through the Dataset API.

Example output item:

```json
{
  "title": "Chasing Sub 2: The Journey of Sabastian Sawe's Historic 1:59:30 Marathon",
  "transcript": "Full transcript text when captions are available...",
  "transcriptStatus": "available",
  "transcriptSource": "watch_html",
  "transcriptLanguage": "en",
  "author": "@adidas",
  "videoUrl": "https://www.youtube.com/watch?v=qRr0lmYvp5g",
  "coverImage": "https://i.ytimg.com/vi/qRr0lmYvp5g/hqdefault.jpg",
  "subscriberCount": 2330000,
  "likeCount": 5400,
  "description": "Video description text...",
  "viewCount": 103403,
  "commentCount": 201,
  "publishedAt": "2026-04-30T00:00:00.000Z",
  "duration": "00:12:30",
  "id": "qRr0lmYvp5g",
  "amountOfVideos": 972,
  "profilePicture": "https://yt3.googleusercontent.com/...",
  "profileBanner": "https://yt3.googleusercontent.com/...",
  "channelDescription": "Through sport, we have the power to change lives.",
  "channelLinks": {
    "website": "https://www.adidas.com/",
    "Instagram": "https://instagram.com/adidas"
  },
  "channelLinksText": "website: https://www.adidas.com/\nInstagram: https://instagram.com/adidas",
  "channelInfo": {
    "channelDescription": "Through sport, we have the power to change lives.",
    "link": {
      "website": "https://www.adidas.com/",
      "Instagram": "https://instagram.com/adidas"
    },
    "additionalInfo": {
      "subscribers": "2.33M subscribers",
      "videos": "972 videos",
      "views": "481,647,084 views"
    }
  },
  "channelTotalViews": 481647084,
  "isChannelVerified": true,
  "commentsTurnedOff": false,
  "scrapingStatus": "success"
}
```

### Channel About Links

When YouTube exposes channel About data, the actor returns the description and outbound links in two easy-to-use top-level fields:

- `channelDescription`: the channel About description.
- `channelLinks`: only real links found on the channel, such as websites, Instagram, Facebook, TikTok, X/Twitter, stores, courses, or custom links. Empty placeholders are omitted.
- `channelLinksText`: the same links flattened into readable `label: URL` lines so Apify Overview, CSV, and spreadsheet exports show the URLs directly.

The full nested About object is still available as `channelInfo` for backwards compatibility. The Overview view prioritizes `channelDescription` and `channelLinksText` so users can see the useful links immediately. The Channel Profile view keeps both the readable text and the structured `channelLinks` object.

### Transcript Behavior

The actor first tries direct YouTube caption sources because they are faster and cheaper than UI automation. If YouTube blocks or hides captions, the actor uses Innertube caption-track requests. In standard mode, it can run an adaptive proxy retry only when the batch would otherwise have poor transcript coverage. In aggressive mode, it retries missing transcripts more eagerly with residential proxy. If a video has no caption tracks exposed by YouTube even after the selected recovery path, `transcript` will be `null`.

Use `transcriptStatus` to understand why:

- `available`: a transcript was recovered.
- `no_caption_tracks`: YouTube did not expose caption tracks through the checked HTTP/Innertube sources.
- `caption_fetch_failed`: caption tracks were found, but YouTube did not return usable caption text.
- `detail_fetch_failed`: the video detail page itself could not be read.
- `not_requested`: full video details/transcripts were disabled.

For maximum transcript attempts, enable:

```json
{
  "proxyMode": "auto",
  "transcriptMode": "aggressive"
}
```

This retries videos that still miss transcripts with Apify residential proxy. It can improve recovery in blocked-caption cases, but it is slower and costs more than standard mode. The older `residentialFallbackForMissingTranscripts` boolean still works for saved inputs.

### Speed And Cost Tips

- Keep `proxyMode` set to `auto` for the best balance of speed and reliability.
- Keep `videoDetailProxyStrategy` set to `auto` unless hosted tests show direct video details are being throttled or hiding caption tracks. Use `proxyFirst` only when the extra proxy traffic improves metadata quality enough to justify the cost.
- Keep `adaptiveTranscriptProxyFallback` enabled if transcripts matter. Disable it for the cheapest metadata-only monitoring runs.
- Leave `adaptiveTranscriptMaxRetries` empty for normal transcript-focused runs. Lower it only when you need cheaper metadata-first monitoring.
- For several channels with transcripts enabled, the default video-detail concurrency is tuned for faster hosted runs. If YouTube starts throttling a large run, lower `maxVideoDetailConcurrency`.
- Use `needVideoDetails: false` when you only need fast listing data such as video URL, title, thumbnail, channel, duration, relative publish text, and visible views.
- For broad keyword searches, use `uniqueChannels: true` or `maxVideosPerChannel: 1` to avoid many repeated videos from the same creator.
- Start with the default detail concurrency for normal runs, then increase carefully if YouTube is not throttling.
- Increase concurrency carefully; YouTube can throttle or change responses when runs become too aggressive.
- Use schedules for recurring monitoring instead of running large backfills repeatedly.

### Integrations

This actor works with standard Apify platform features:

- Dataset export in JSON, CSV, Excel, XML, RSS, and HTML
- Apify API and API clients
- Scheduled runs for channel monitoring
- Webhooks after every run
- Make, Zapier, and other no-code automation tools
- Actor chaining and MCP/AI-agent workflows through the output schema

### FAQ

#### Can I scrape multiple channels in one run?

Yes. Add multiple handles or URLs to the `channel` array. The actor processes channels concurrently based on `maxChannelConcurrency`.

#### Can I search by keyword instead of channel?

Yes. Put search terms in `channel` and set `keywords` to `true`.

#### Why is a transcript missing?

YouTube does not expose captions for every video. Some videos have no captions, some captions are region or client restricted, and some can be hidden by YouTube. In those cases the actor returns `transcript: null` instead of fabricating data.

#### Why are comments sometimes `null`?

Some videos have comments disabled or hidden. The actor returns `commentsTurnedOff` when it can detect that state.

#### What proxy mode should I use?

Use `auto` for most runs. It keeps search, channel collection, and video details direct first, then uses proxy fallback for hard failures or incomplete core metadata. Use `videoDetailProxyStrategy: "proxyFirst"` only when Apify-hosted detail requests are slower or less reliable direct-first. Enable `transcriptMode: "aggressive"` only when transcript coverage is more important than speed and cost. Use `never` for the lowest cost, or `always` only if collection itself is consistently blocked.

### Related Actors

- [YouTube Shorts Scraper](https://apify.com/newbs/youtube-shorts)
- [YouTube Channel Latest Post Tracker](https://apify.com/newbs/Latest-Post-Time-Youtube)

### Responsible Use

This actor extracts publicly available YouTube data. You are responsible for using the data in compliance with applicable laws, YouTube terms, privacy rules, and your own internal policies. Do not use scraped data for spam, harassment, or unlawful profiling.

# Actor input Schema

## `channel` (type: `array`):

Enter YouTube handles, channel URLs, /videos URLs, or search terms. Use channel inputs when keywords is false. Use search terms when keywords is true.

## `keywords` (type: `boolean`):

Enable this when the channel field contains YouTube search keywords instead of channel handles or URLs.

## `needVideoDetails` (type: `boolean`):

Enable for descriptions, metrics, channel profile data, publish dates, durations, and transcripts. Disable for faster basic video URL collection.

## `numberOfResults` (type: `integer`):

Number of videos to collect for each item in the channel list. If keywords is false, this means per channel. If keywords is true, this means per search keyword, before optional duplicate/channel limits are applied.

## `uniqueChannels` (type: `boolean`):

Only applies when keywords is true. Keep at most one result from each YouTube channel per keyword, and deduplicate repeated video URLs across the run.

## `maxVideosPerChannel` (type: `integer`):

Only applies when keywords is true. Limits how many videos from the same YouTube channel are returned for each keyword. Leave empty for no per-channel limit. Set 1 for creator discovery use cases.

## `localeHl` (type: `string`):

YouTube hl parameter. Examples: en, fr, de, es, ja.

## `localeGl` (type: `string`):

YouTube gl parameter. Examples: US, GB, FR, DE, JP.

## `acceptLanguage` (type: `string`):

HTTP language preferences sent with each request, for example en-US,en;q=0.9. This nudges YouTube localization but does not guarantee localized results.

## `maxVideoDetailConcurrency` (type: `integer`):

How many video details to scrape in parallel per channel or keyword.

## `maxChannelConcurrency` (type: `integer`):

How many channel or keyword inputs to collect in parallel. Higher values can improve multi-input runs but can increase YouTube throttling risk.

## `fastVideoDetailConcurrency` (type: `integer`):

Parallel HTTP video-detail requests used by fast mode. Higher values increase speed but can increase throttling risk.

## `proxyMode` (type: `string`):

Auto is recommended: search, channel list collection, and video detail requests start direct, then hard failures or incomplete core metadata can retry with proxy-backed HTTP. Missing transcripts only use residential fallback when transcript mode is aggressive. Always proxies collection and details. Never disables proxy usage for maximum speed and lowest cost.

## `videoDetailProxyStrategy` (type: `string`):

Controls only per-video detail requests. Auto/direct-first starts direct and uses proxy only for blocked or incomplete core details. Proxy-first uses proxy for video detail pages while keeping channel/search collection direct. Use proxy-first only as an advanced troubleshooting mode because it can increase cost and may be slower.

## `proxyConfiguration` (type: `object`):

Optional Apify Proxy settings. Leave empty with Auto mode unless you need custom proxy groups or country settings for fallback or Always mode.

## `transcriptMode` (type: `string`):

Standard mode is faster and cheaper, with adaptive proxy recovery only when batch transcript coverage is poor. Aggressive mode retries missing transcripts with residential proxy more eagerly, improving some blocked-caption cases at higher runtime and cost.

## `adaptiveTranscriptProxyFallback` (type: `boolean`):

In standard transcript mode, automatically retry missing transcripts with proxy only when the batch comes back with poor transcript coverage. Disable for the lowest possible proxy cost.

## `adaptiveTranscriptMaxRetries` (type: `integer`):

Maximum missing-transcript rows retried by adaptive recovery in standard mode. Leave empty for automatic caps: all rows for small runs, and up to 80 round-robin rows for larger runs. Lower it when runtime and proxy cost matter more than transcript coverage.

## `adaptiveTranscriptRetryConcurrency` (type: `integer`):

How many missing-transcript rows adaptive recovery may retry in parallel. Leave empty for the default. Higher values can improve speed for transcript-heavy runs but may increase proxy pressure.

## `residentialFallbackForMissingTranscripts` (type: `boolean`):

Compatibility option. Prefer Transcript mode = Aggressive. When enabled, videos that still miss transcripts after direct caption extraction are retried with Apify residential proxy.

## `streamDatasetItems` (type: `boolean`):

Write completed rows while the run is still processing instead of waiting until the end. Keep enabled for larger runs so partial progress is preserved if a run times out.

## `resetCheckpoint` (type: `boolean`):

Accepted for compatibility with older inputs. The HTTP-first actor does not persist checkpoints.

## Actor input object example

```json
{
  "channel": [
    "https://www.youtube.com/@adidas/videos",
    "zara"
  ],
  "keywords": false,
  "needVideoDetails": true,
  "numberOfResults": 2,
  "uniqueChannels": false,
  "localeHl": "en",
  "localeGl": "US",
  "acceptLanguage": "en-US,en;q=0.9",
  "maxVideoDetailConcurrency": 20,
  "maxChannelConcurrency": 2,
  "fastVideoDetailConcurrency": 20,
  "proxyMode": "auto",
  "videoDetailProxyStrategy": "auto",
  "transcriptMode": "standard",
  "adaptiveTranscriptProxyFallback": true,
  "adaptiveTranscriptRetryConcurrency": 20,
  "residentialFallbackForMissingTranscripts": false,
  "streamDatasetItems": true,
  "resetCheckpoint": false
}
```

# Actor output Schema

## `results` (type: `string`):

Full dataset items returned by the actor.

## `overview` (type: `string`):

Dataset view optimized for checking the main video, transcript, transcript status, channel links, and metric fields.

## `channelProfile` (type: `string`):

Dataset view focused on channel About data, outbound links, profile images, and channel metrics.

## `transcripts` (type: `string`):

Dataset view focused on transcript text, transcript status, source, and language.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "channel": [
        "https://www.youtube.com/@adidas/videos",
        "zara"
    ],
    "numberOfResults": 2,
    "localeHl": "en",
    "localeGl": "US",
    "acceptLanguage": "en-US,en;q=0.9",
    "maxVideoDetailConcurrency": 20,
    "maxChannelConcurrency": 2,
    "fastVideoDetailConcurrency": 20,
    "adaptiveTranscriptRetryConcurrency": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("newbs/youtube-channel").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "channel": [
        "https://www.youtube.com/@adidas/videos",
        "zara",
    ],
    "numberOfResults": 2,
    "localeHl": "en",
    "localeGl": "US",
    "acceptLanguage": "en-US,en;q=0.9",
    "maxVideoDetailConcurrency": 20,
    "maxChannelConcurrency": 2,
    "fastVideoDetailConcurrency": 20,
    "adaptiveTranscriptRetryConcurrency": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("newbs/youtube-channel").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "channel": [
    "https://www.youtube.com/@adidas/videos",
    "zara"
  ],
  "numberOfResults": 2,
  "localeHl": "en",
  "localeGl": "US",
  "acceptLanguage": "en-US,en;q=0.9",
  "maxVideoDetailConcurrency": 20,
  "maxChannelConcurrency": 2,
  "fastVideoDetailConcurrency": 20,
  "adaptiveTranscriptRetryConcurrency": 20
}' |
apify call newbs/youtube-channel --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=newbs/youtube-channel",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Youtube Channel Scraper",
        "description": "Scrape YouTube channels or keyword searches for video URLs, titles, metrics, transcripts, channel profiles, social links, descriptions and more. Fast, low-cost YouTube data extraction for monitoring, influencer research, SEO, and LLM workflows.",
        "version": "0.0",
        "x-build-id": "GYPsHa6p71PWODDtB"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/newbs~youtube-channel/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-newbs-youtube-channel",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/newbs~youtube-channel/runs": {
            "post": {
                "operationId": "runs-sync-newbs-youtube-channel",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/newbs~youtube-channel/run-sync": {
            "post": {
                "operationId": "run-sync-newbs-youtube-channel",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "channel",
                    "numberOfResults"
                ],
                "properties": {
                    "channel": {
                        "title": "Channels, URLs, or search terms",
                        "type": "array",
                        "description": "Enter YouTube handles, channel URLs, /videos URLs, or search terms. Use channel inputs when keywords is false. Use search terms when keywords is true.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "keywords": {
                        "title": "Search by keyword",
                        "type": "boolean",
                        "description": "Enable this when the channel field contains YouTube search keywords instead of channel handles or URLs.",
                        "default": false
                    },
                    "needVideoDetails": {
                        "title": "Scrape full video details",
                        "type": "boolean",
                        "description": "Enable for descriptions, metrics, channel profile data, publish dates, durations, and transcripts. Disable for faster basic video URL collection.",
                        "default": true
                    },
                    "numberOfResults": {
                        "title": "Results per channel or keyword",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Number of videos to collect for each item in the channel list. If keywords is false, this means per channel. If keywords is true, this means per search keyword, before optional duplicate/channel limits are applied."
                    },
                    "uniqueChannels": {
                        "title": "Unique channels in keyword results",
                        "type": "boolean",
                        "description": "Only applies when keywords is true. Keep at most one result from each YouTube channel per keyword, and deduplicate repeated video URLs across the run.",
                        "default": false
                    },
                    "maxVideosPerChannel": {
                        "title": "Max videos per channel",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Only applies when keywords is true. Limits how many videos from the same YouTube channel are returned for each keyword. Leave empty for no per-channel limit. Set 1 for creator discovery use cases."
                    },
                    "localeHl": {
                        "title": "YouTube language hint",
                        "type": "string",
                        "description": "YouTube hl parameter. Examples: en, fr, de, es, ja."
                    },
                    "localeGl": {
                        "title": "YouTube country hint",
                        "type": "string",
                        "description": "YouTube gl parameter. Examples: US, GB, FR, DE, JP."
                    },
                    "acceptLanguage": {
                        "title": "Accept-Language header",
                        "type": "string",
                        "description": "HTTP language preferences sent with each request, for example en-US,en;q=0.9. This nudges YouTube localization but does not guarantee localized results."
                    },
                    "maxVideoDetailConcurrency": {
                        "title": "Parallel video details",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "How many video details to scrape in parallel per channel or keyword."
                    },
                    "maxChannelConcurrency": {
                        "title": "Parallel channels or keywords",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "How many channel or keyword inputs to collect in parallel. Higher values can improve multi-input runs but can increase YouTube throttling risk."
                    },
                    "fastVideoDetailConcurrency": {
                        "title": "Fast HTTP detail concurrency",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Parallel HTTP video-detail requests used by fast mode. Higher values increase speed but can increase throttling risk."
                    },
                    "proxyMode": {
                        "title": "Proxy mode",
                        "enum": [
                            "auto",
                            "always",
                            "never"
                        ],
                        "type": "string",
                        "description": "Auto is recommended: search, channel list collection, and video detail requests start direct, then hard failures or incomplete core metadata can retry with proxy-backed HTTP. Missing transcripts only use residential fallback when transcript mode is aggressive. Always proxies collection and details. Never disables proxy usage for maximum speed and lowest cost.",
                        "default": "auto"
                    },
                    "videoDetailProxyStrategy": {
                        "title": "Video detail proxy strategy",
                        "enum": [
                            "auto",
                            "proxyFirst"
                        ],
                        "type": "string",
                        "description": "Controls only per-video detail requests. Auto/direct-first starts direct and uses proxy only for blocked or incomplete core details. Proxy-first uses proxy for video detail pages while keeping channel/search collection direct. Use proxy-first only as an advanced troubleshooting mode because it can increase cost and may be slower.",
                        "default": "auto"
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Optional Apify Proxy settings. Leave empty with Auto mode unless you need custom proxy groups or country settings for fallback or Always mode."
                    },
                    "transcriptMode": {
                        "title": "Transcript mode",
                        "enum": [
                            "standard",
                            "aggressive"
                        ],
                        "type": "string",
                        "description": "Standard mode is faster and cheaper, with adaptive proxy recovery only when batch transcript coverage is poor. Aggressive mode retries missing transcripts with residential proxy more eagerly, improving some blocked-caption cases at higher runtime and cost.",
                        "default": "standard"
                    },
                    "adaptiveTranscriptProxyFallback": {
                        "title": "Adaptive transcript recovery",
                        "type": "boolean",
                        "description": "In standard transcript mode, automatically retry missing transcripts with proxy only when the batch comes back with poor transcript coverage. Disable for the lowest possible proxy cost.",
                        "default": true
                    },
                    "adaptiveTranscriptMaxRetries": {
                        "title": "Max adaptive transcript retries",
                        "minimum": 0,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Maximum missing-transcript rows retried by adaptive recovery in standard mode. Leave empty for automatic caps: all rows for small runs, and up to 80 round-robin rows for larger runs. Lower it when runtime and proxy cost matter more than transcript coverage."
                    },
                    "adaptiveTranscriptRetryConcurrency": {
                        "title": "Parallel adaptive transcript retries",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "How many missing-transcript rows adaptive recovery may retry in parallel. Leave empty for the default. Higher values can improve speed for transcript-heavy runs but may increase proxy pressure."
                    },
                    "residentialFallbackForMissingTranscripts": {
                        "title": "Residential fallback for missing transcripts",
                        "type": "boolean",
                        "description": "Compatibility option. Prefer Transcript mode = Aggressive. When enabled, videos that still miss transcripts after direct caption extraction are retried with Apify residential proxy.",
                        "default": false
                    },
                    "streamDatasetItems": {
                        "title": "Stream dataset rows",
                        "type": "boolean",
                        "description": "Write completed rows while the run is still processing instead of waiting until the end. Keep enabled for larger runs so partial progress is preserved if a run times out.",
                        "default": true
                    },
                    "resetCheckpoint": {
                        "title": "Reset saved progress",
                        "type": "boolean",
                        "description": "Accepted for compatibility with older inputs. The HTTP-first actor does not persist checkpoints.",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
