# YouTube Subtitle Search Scraper (`maximedupre/youtube-subtitle-search-crawler`) Actor

Search public YouTube captions for words or phrases and find matching videos. Get each video's URL, title, channel, view count, duration, publication time, thumbnail, full captions, timed segments, language, and first matching phrase.

- **URL**: https://apify.com/maximedupre/youtube-subtitle-search-crawler.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Videos, Social media, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.80 / 1,000 caption matches

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

### 🔎 Search YouTube captions by phrase

Search publicly reachable YouTube captions for words or phrases and find the videos where they appear. Researchers, educators, content teams, and developers can review caption text with video and channel details, timing, language, and the first submitted phrase that found each saved video. The result is a structured dataset that helps you locate spoken topics without checking videos one by one.

- Discover videos whose subtitles contain your phrase with **[Search YouTube Videos by Subtitles](https://apify.com/maximedupre/youtube-subtitle-search-crawler/examples/search-youtube-videos-by-subtitles)**.
- Look up a term in video transcripts with **[YouTube Transcript Search](https://apify.com/maximedupre/youtube-subtitle-search-crawler/examples/youtube-transcript-search)**.
- Find matching spoken words with **[Search YouTube Captions](https://apify.com/maximedupre/youtube-subtitle-search-crawler/examples/search-youtube-captions)**.
- Scan subtitles for a phrase with **[Search YouTube Subtitles](https://apify.com/maximedupre/youtube-subtitle-search-crawler/examples/search-youtube-subtitles)**.
- Check where a phrase appears in captions with **[YouTube Caption Search](https://apify.com/maximedupre/youtube-subtitle-search-crawler/examples/youtube-caption-search)**.
- Build a list of videos that mention a term with **[YouTube Subtitle Search](https://apify.com/maximedupre/youtube-subtitle-search-crawler/examples/youtube-subtitle-search)**.

#### 📺 Find videos through caption text

Each saved row represents one matching public YouTube video. It can include the video URL, title, channel, public view count, duration, publication time, thumbnail, caption language, full caption text, and timed caption segments. The selected search phrase is also saved.

If the same source video appears again for another submitted phrase, the Actor keeps the first saved match and ignores later copies. The `searchPhrase` value shows the first submitted phrase that found that row.

#### ▶️ Search captions in a few steps

1. Add one or more words or phrases in **Search phrases**.
2. Choose a caption language preference and either readable text or SRT subtitles.
3. Add view, date, order, or result-count settings when needed.
4. Leave **Maximum results** empty to return all available results until the source is exhausted, or set a limit for a smaller run.
5. Start the run and open **Matching videos** in the default dataset.

The Actor searches public caption tracks. You do not need a YouTube API key or account login for this public data. It does not download YouTube video or audio files.

#### ⚙️ Input

Add at least one search phrase. The optional settings help you choose caption language, format, filters, and order.

**Input fields**

| Field | Type | What it does |
| --- | --- | --- |
| `searchPhrases` | string array (required) | Words or phrases to find in YouTube captions. Add one or more unique values. |
| `preferredLanguages` | string array | Tries caption language codes in the order you list them, such as `en` or `es`. If a preferred track is not available, another available track is used. Leave it empty to use any available caption language. |
| `subtitleFormat` | string | Choose `text` for readable caption text or `srt` for subtitles with timestamps. |
| `minimumViews` | integer | Keeps videos with at least this many public views. Leave it empty to allow any view count. |
| `publishedAfter` | string | Keeps videos published on or after a calendar date or a relative value such as `30 days ago`. Leave it empty for any publication date. |
| `resultOrder` | string | Choose `relevance` for caption-match relevance or `views` for most public views. |
| `maxResults` | integer | Stops after this many matching videos. Leave it empty to return all available results until the source is exhausted. |

**Example input**

This is the public input from the successful default-input run:

```json
{
  "searchPhrases": [
    "machine learning"
  ],
  "subtitleFormat": "text",
  "resultOrder": "relevance",
  "maxResults": 20
}
```

#### 🧾 Output

The output panel provides a **Matching videos** link to the default dataset. Each saved dataset row has the same shape.

**Matching video fields**

| Field | Type | What it does |
| --- | --- | --- |
| `videoUrl` | URL | URL of the matching YouTube video. |
| `title` | string | Title of the matching video. |
| `channel` | object | Public channel that published the video. |
| `channel.name` | string | Name of the channel that published the video. |
| `channel.url` | URL | Public channel URL, when available. |
| `viewCount` | integer | Public view count, when available. |
| `durationSeconds` | integer | Video duration in seconds, when available. |
| `publishedAt` | date-time | Date and time when the video was published, when available. |
| `thumbnailUrl` | URL | Video thumbnail URL, when available. |
| `searchPhrase` | string | First submitted phrase that found this video. |
| `captionLanguage` | string | Language code of the caption track used for this result. |
| `captionText` | string | All available captions in the format chosen for the run. This is readable text or SRT subtitles. |
| `captionSegments` | object array | Caption segments with source timing for finding matching text in the video. |
| `captionSegments.startSeconds` | number | Start time of the caption segment in seconds. |
| `captionSegments.durationSeconds` | number | Duration of the caption segment in seconds. |
| `captionSegments.text` | string | Text shown in the caption segment. |

**Example matching video**

This is a shortened real row from the successful beta run for the default input. The full caption text and later caption segments are replaced with the string `"..."` so the example stays small.

```json
{
  "videoUrl": "https://www.youtube.com/watch?v=PeMlggyqz0Y",
  "title": "Machine Learning Explained in 100 Seconds",
  "channel": {
    "name": "Fireship",
    "url": "http://www.youtube.com/@Fireship"
  },
  "viewCount": 1107634,
  "durationSeconds": 154,
  "publishedAt": "2021-09-09T17:31:56.000Z",
  "thumbnailUrl": "https://i.ytimg.com/vi/PeMlggyqz0Y/sddefault.jpg",
  "searchPhrase": "machine learning",
  "captionLanguage": "en",
  "captionText": "...",
  "captionSegments": [
    {
      "startSeconds": 0.12,
      "durationSeconds": 4.32,
      "text": "machine learning teach a computer how to"
    },
    {
      "startSeconds": 2.48,
      "durationSeconds": 4.2,
      "text": "perform a task without explicitly"
    },
    {
      "startSeconds": 4.44,
      "durationSeconds": 4.76,
      "text": "programming it to perform said task"
    },
    {
      "startSeconds": 6.68,
      "durationSeconds": 4.12,
      "text": "instead feed data into an algorithm to"
    },
    {
      "startSeconds": 9.2,
      "durationSeconds": 3.88,
      "text": "gradually improve outcomes with"
    },
    {
      "startSeconds": 10.8,
      "durationSeconds": 4.879,
      "text": "experience similar to how organic life"
    },
    {
      "startSeconds": 13.08,
      "durationSeconds": 5.119,
      "text": "learns the term was coined in 1959 by"
    },
    {
      "startSeconds": 15.679,
      "durationSeconds": 4.241,
      "text": "Arthur Samuel at IBM who is developing"
    },
    "..."
  ]
}
```

#### 💳 Pricing

This Actor uses pay-per-event pricing. You pay $0.0018 for each saved video whose available captions match a submitted phrase. A run that saves no matching video does not create a caption-match charge. If the same video matches another phrase later, that copy is ignored and the saved row is charged once.

#### 🔌 Integrations

Read saved rows from the default dataset through the Apify API or export them from Apify in common data formats.

**Video guide**

https://www.youtube.com/watch?v=bNACk1\_S\_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

#### ❓ FAQ

##### What happens when a video has no readable captions?

The Actor can use only publicly reachable caption tracks that it can read. Private, login-required, unavailable, or unreadable captions cannot be searched, so they may not produce a matching row.

##### Does it search the title or video description?

No. It checks caption text for the submitted words or phrases. The title, channel, and other video details are returned as context for a match.

##### Can I choose a caption language?

Yes. Add language codes such as `en` or `es` in your preferred order. If a preferred track is not available, the Actor uses another available track. The `captionLanguage` field shows the track used.

##### Should I choose text or SRT subtitles?

Choose readable text when you want a simple caption body. Choose SRT when you want a standard subtitle format that keeps timestamps.

##### How are duplicate videos handled across phrases?

The Actor saves the first eligible match for a source video. If that video appears again from another phrase, the later match is ignored, and `searchPhrase` stays set to the first submitted phrase that found it.

##### Can I filter and order the matching videos?

Yes. Set a minimum view count or publication date, then choose caption-match relevance or most public views. You can also set a maximum result count. Leave that limit empty to collect all available results until the source is exhausted.

##### Can I get only a short clip around the match?

No. Each row includes full available caption text and timed segments. Use the segment times to find the words in the video. The Actor does not download a video or audio clip.

##### Do I need a YouTube API key or account login?

No. The Actor uses publicly reachable YouTube caption data and does not ask you for a customer API key or account login.

### 📝 Changelog

**v0.0** (02-09-2026)

- Initial release.

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~youtube-subtitle-search-crawler/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- [YouTube Transcript to PDF](https://apify.com/maximedupre/youtube-to-pdf) - Turn known public YouTube videos with captions into readable PDF transcripts and timed transcript rows.
- [YouTube Transcript Scraper](https://apify.com/igview-owner/youtube-transcript-scraper) - Get a full timestamped transcript from a known public YouTube video.
- [YouTube Scraper - Videos, Search, Subtitles & Comments](https://apify.com/gganbukim/youtube-scraper) - Collect broader YouTube video or search data when you need more than caption matches.
- [YouTube Transcript Search](https://apify.com/lead_maker/youtube-transcript-keyword-search) - Search transcript or caption text by keyword and review timestamped matches.
- [YouTube Video Transcript](https://apify.com/starvibe/youtube-video-transcript) - Get full transcripts, timestamps, and metadata from known public YouTube videos.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `searchPhrases` (type: `array`):

Words or phrases to find in YouTube captions. Add one or more phrases.

## `preferredLanguages` (type: `array`):

Try these caption languages in this order. Use language codes such as `en` or `es`. If a preferred track is not available, the Actor uses another available track. Leave this empty to use any available caption language.

## `subtitleFormat` (type: `string`):

Choose readable caption text or SRT subtitles with timestamps.

## `minimumViews` (type: `integer`):

Only include videos with at least this many public views. Leave this empty to allow any view count.

## `publishedAfter` (type: `string`):

Only include videos published on or after this date. Leave this empty for any publication date. You can use a calendar date or a relative value such as `30 days ago`.

## `resultOrder` (type: `string`):

Choose caption-match relevance or public popularity.

## `maxResults` (type: `integer`):

Stop after this many matching videos. Leave this empty to return all available results until the source is exhausted.

## Actor input object example

```json
{
  "searchPhrases": [
    "machine learning"
  ],
  "subtitleFormat": "text",
  "resultOrder": "relevance",
  "maxResults": 20
}
```

# Actor output Schema

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

Open the matching videos in the default dataset.

# 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 = {
    "searchPhrases": [
        "machine learning"
    ],
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/youtube-subtitle-search-crawler").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 = {
    "searchPhrases": ["machine learning"],
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/youtube-subtitle-search-crawler").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "searchPhrases": [
    "machine learning"
  ],
  "maxResults": 20
}' |
apify call maximedupre/youtube-subtitle-search-crawler --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maximedupre/youtube-subtitle-search-crawler"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/7s3HYPYG3h6ARknof/builds/wpJANfT3h38l6JOK1/openapi.json
