# YouTube SEO Keyword Research Pro — Search, Tags, Trends (`sian.agency/youtube-seo-keyword-research-pro`) Actor

Complete YouTube SEO keyword research toolkit. From one keyword get top search results, autocomplete suggestions, related videos, and trending hashtags. Built for creators, SEO agencies, and content strategists planning videos that win YouTube search.

- **URL**: https://apify.com/sian.agency/youtube-seo-keyword-research-pro.md
- **Developed by:** [SIÁN OÜ](https://apify.com/sian.agency) (community)
- **Categories:** Videos, Social media, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $15.00 / 1,000 keyword snapshots

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## 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 SEO Keyword Research Pro 🔎

[![Store-SIÁN Agency](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![Store-YouTube Autocomplete](https://img.shields.io/badge/Store-YouTube%20Autocomplete-FF0000)](https://apify.com/sian.agency/youtube-auto-complete-and-query-suggestion?fpr=sian) [![Store-Cheapest YouTube Comments](https://img.shields.io/badge/Store-Cheapest%20YouTube%20Comments-FF0000)](https://apify.com/sian.agency/cheapest-youtube-comments-scraper?fpr=sian) [![Store-YouTube AI Comments + Questions](https://img.shields.io/badge/Store-YouTube%20AI%20Comments%20%2B%20Questions-FF0000)](https://apify.com/sian.agency/youtube-ai-comments-scraper-and-questions-extractor?fpr=sian)

**The complete YouTube SEO keyword research toolkit.** From one seed keyword, get top search results, autocomplete suggestions, related videos, and trending hashtags — all in one workflow. Built for creators, SEO agencies, and content strategists who need to win YouTube search.

> 💡 **Only need autocomplete suggestions?** Save with our cheaper single-purpose sibling: [YouTube Autocomplete & Query Suggestion](https://apify.com/sian.agency/youtube-auto-complete-and-query-suggestion?fpr=sian) — pure autocomplete at $0.0005 / suggestion. Use this Pro bundle when you need the FULL keyword research package (search + suggest + related + hashtag).

---

### Why this actor

Most YouTube research actors on Apify ship one endpoint. To build a complete keyword brief you'd have to glue together a search scraper, an autocomplete scraper, a related-videos scraper, and a hashtag scraper — and then JOIN the results in your warehouse.

This actor delivers **four YouTube discovery endpoints per keyword in one workflow, one bill, one dataset**:

| | This actor (Pro bundle) | Our autocomplete-only sibling | Top per-endpoint commodity scrapers |
|---|---|---|---|
| Search results (videos, channels, playlists) | ✅ | — | ✅ (separate actor) |
| Autocomplete suggestions | ✅ | ✅ | partial |
| Related-video graph (algorithm signal) | ✅ | — | rare |
| Trending hashtag adjacency | ✅ | — | rare |
| Parallel fetch (one wall-clock latency) | ✅ | n/a | sequential |
| Unified tidy-long row schema with `rowType` | ✅ | ✅ | flat blob — flatten yourself |
| Bulk + seed-video discovery modes | ✅ | partial | — |
| Predictable per-keyword headline price | ✅ | — | — |

Drop the result into Pandas, DuckDB, or BigQuery and filter by `rowType` to slice the bundle.

> **Want only autocomplete?** Use our [autocomplete-only sibling](https://apify.com/sian.agency/youtube-auto-complete-and-query-suggestion?fpr=sian) — it's cheaper and built for that single task. This Pro bundle is for when you need the full SEO research package.

---

### What you get back

A single dataset where every row carries a `rowType` discriminator:

| `rowType` | What it is | Charged event |
|---|---|---|
| `keyword_snapshot` ⭐ | The per-keyword anchor row — counts of each signal kind, top search videoId, matched hashtag + YouTube's hashtag volume signal. Exactly 1 per keyword. | `keyword-snapshot-result` |
| `search_result` | One row per YouTube search result. For `resultType: video` you get title, views, channel, length, publishedAt. For `channel` and `playlist` you get the relevant columns. | `search-result-row` |
| `suggestion` | One row per autocomplete suggestion. `suggestion` + `suggestionRank`. | `suggestion-row` |
| `related_video` | One row per related/recommended video chained off the keyword's top search result. The YouTube algorithm's own adjacency signal. | `related-video-row` |
| `hashtag_trend` | One row per trending video under the closest matching hashtag for the keyword (e.g. `rust programming` → `#rustprogramming`). | `hashtag-trend-row` |
| `error` | Status row (`status: no_results | endpoint_unavailable | error`) — never charged. | — |

Every row carries `_sourceKeyword`, `_sourceMode`, `_sourceEndpoint`, `_sourceRegion`, `_sourceLanguage`, `_fetchedAt`, and `_page` so you can group, dedupe, and trace lineage even in bulk mode.

---

### Input

Three research modes:

#### 1. Single keyword (`keywordResearch`, default)

```json
{
  "operation": "keywordResearch",
  "keyword": "rust programming",
  "region": "US",
  "language": "en",
  "includeEndpoints": ["search", "suggest", "hashtag", "related"]
}
````

#### 2. Bulk keywords (`bulkKeywords`)

```json
{
  "operation": "bulkKeywords",
  "keywords": "rust programming\ngolang vs rust\nlearn rust 2026",
  "region": "US",
  "language": "en",
  "includeEndpoints": ["search", "suggest", "hashtag"]
}
```

#### 3. Seed video discovery (`seedVideoResearch`)

Paste a competitor's video URL — the actor extracts its top keywords and runs keyword research around them.

```json
{
  "operation": "seedVideoResearch",
  "seedVideoUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
```

#### Input fields

| Field | Type | Default | Description |
|---|---|---|---|
| `operation` | string | `keywordResearch` | One of `keywordResearch`, `bulkKeywords`, `seedVideoResearch`. |
| `keyword` | string | — | Seed keyword for `keywordResearch` mode. |
| `keywords` | string | — | Comma/newline-separated keyword list for `bulkKeywords` mode. Max 50 per run. |
| `seedVideoUrl` | string | — | YouTube video URL or 11-char ID for `seedVideoResearch` mode. |
| `includeEndpoints` | array | All 4 | Pick which endpoints to fetch: `search`, `suggest`, `hashtag`, `related`. |
| `searchType` | string | `video` | One of `video`, `channel`, `playlist`, `all`. |
| `region` | string | — | Two-letter country code (`US`, `GB`, `IN`, `DE`, `BR`). |
| `language` | string | — | Two-letter language code (`en`, `es`, `pt`, `ja`). |
| `maxSearchPages` | integer | 1 | Pages of `/search` results (1–5). |
| `maxRelatedPages` | integer | 1 | Pages of `/related` results (1–5). |

***

### How endpoint-level gating works

For each keyword, the actor fires search + suggest + hashtag in parallel (`Promise.allSettled`) for one wall-clock latency. The `related` endpoint is then chained off the top search result. If an endpoint returns empty/error for a specific keyword — e.g. an obscure long-tail with no hashtag matches — the actor:

1. **Detects the empty/body-level error** (yt-api wraps endpoint errors at the body level, not HTTP).
2. **Does not charge you** for that endpoint.
3. **Pushes one status row** (`status: no_results` or `endpoint_unavailable`) for auditing.

This means you only pay for endpoints that actually returned data — and the `keyword_snapshot` anchor row tells you exactly which signals were available at a glance.

***

### Pricing

**Pay-per-event.** Bronze tier shown — higher tiers auto-ladder via Apify's tier system. FREE-tier is deliberately higher to deter abuse (per Apify pricing model).

| Event | BRONZE | What it covers |
|---|---|---|
| `apify-actor-start` (once) | $0.005 | Actor lifecycle |
| `keyword-snapshot-result` ⭐ | $0.020 | Per keyword — the anchor snapshot row (1 per keyword) |
| `search-result-row` | $0.003 | Per YouTube search result row |
| `suggestion-row` | $0.001 | Per autocomplete suggestion row |
| `related-video-row` | $0.003 | Per related-video row |
| `hashtag-trend-row` | $0.003 | Per hashtag-trending video row |

⭐ = primary / headline event (snapshot anchor; exactly 1 per successful keyword).

**Estimated full-bundle cost (1 keyword, all 4 endpoints, BRONZE tier):**
$0.005 (start) + $0.020 (snapshot) + ~20 × $0.003 (search) + ~10 × $0.001 (suggest) + ~20 × $0.003 (related) + ~25 × $0.003 (hashtag) = **~$0.22 / keyword** for the full discovery surface.

**Cheap snapshot (`includeEndpoints: ["suggest"]` only):**
$0.005 (start) + $0.020 (snapshot) + ~10 × $0.001 (suggest) = **~$0.035 / keyword** — but you should use the [autocomplete-only sibling actor](https://apify.com/sian.agency/youtube-auto-complete-and-query-suggestion?fpr=sian) for ~10× cheaper at $0.0005 / suggestion.

Skip endpoints you don't need — never pay for data you didn't request.

***

### Use cases

1. **YouTube Creators — Plan Videos That Win Search.** Creators planning their next upload need to know what real people search for on YouTube, what the autocomplete completes, what the algorithm associates, and which hashtags are trending. One run per keyword gives a complete brief for title, description, and tag selection — far more reliable than guessing.

2. **SEO Agencies — Sell YouTube SEO Services to Clients.** Agencies offering YouTube SEO need bulk keyword research workflows. Feed a list of seed keywords, get back search competitiveness, related-video graphs, autocomplete trees, and hashtag adjacency for each — packaged as one tidy-long dataset per run, ready to drop into client deliverables.

3. **Content Strategists — Topic Discovery + Gap Analysis.** Content teams building YouTube editorial calendars need to know which adjacent topics the algorithm surfaces, which autocomplete tails imply unmet intent, and which hashtags carry trending volume. The bundle gives you all four signals per topic in one workflow.

4. **Brand Marketing — Organic YouTube Discovery Research.** Brand teams running organic YouTube channels need to research category-defining keywords without buying agency tools. Bulk mode takes a list of brand-relevant terms and returns the full discovery surface at predictable per-keyword pricing.

5. **Educators + Course Creators — Position Content for Search.** Online educators and course creators competing for educational search traffic need to identify long-tail keywords with high intent but low competition. Autocomplete + related-video signals reveal exactly what learners type, watch, and search next.

***

### Output schema (unified rows)

Every row carries:

- **Tracing fields**: `_sourceKeyword`, `_sourceMode`, `_sourceEndpoint`, `_sourceRegion`, `_sourceLanguage`, `_fetchedAt`, `_page`
- **Discriminator**: `rowType` (one of `keyword_snapshot | search_result | suggestion | related_video | hashtag_trend | error`)
- **Status**: `status` (`success` / `no_results` / `endpoint_unavailable` / `error`)

Plus per-`rowType` fields:

**`keyword_snapshot`** — `snapshotKeyword`, `snapshotSuggestionCount`, `snapshotSearchResultCount`, `snapshotRelatedVideoCount`, `snapshotHashtagTrendCount`, `snapshotHashtag` (matched), `snapshotHashtagInfoText` (YouTube's volume signal e.g. `3.2K videos • 803 channels`), `snapshotTopVideoId`, `snapshotTopVideoTitle`. The full list of autocomplete suggestions is in `extra.allSuggestions`; the upstream's `estimatedResults` lives in `extra.estimatedSearchResults`.

**`search_result`** — `resultType` (`video | channel | playlist | shorts_listing`), `resultRank`, plus the video/channel/playlist columns relevant to the type: `videoId`, `videoTitle`, `viewCount`, `channelId`, `channelUrl`, `channelSubscriberCountText`, `playlistId`, `playlistTitle`, `playlistVideoCount`, etc.

**`suggestion`** — `suggestion` (the string), `suggestionRank`.

**`related_video`** — `videoId`, `videoTitle`, `viewCount`, `lengthText`, `publishedAt`, `channelId`, `channelTitle`, `channelHandle`, `thumbnailUrl`.

**`hashtag_trend`** — `hashtagName` (`#rustprogramming`), plus the trending video's `videoId`, `videoTitle`, `viewCount`, `channelTitle`, etc.

Anything endpoint-specific that doesn't fit the unified schema is captured in `extra` (object) so you never lose upstream data.

***

### FAQ

**Q: I only need autocomplete. Should I use this?**
Probably not. Our cheaper [autocomplete-only sibling actor](https://apify.com/sian.agency/youtube-auto-complete-and-query-suggestion?fpr=sian) charges ~$0.0005 / suggestion vs. this actor's $0.020 snapshot fee + $0.001 / suggestion. Use this Pro bundle when you also want search, related, or hashtag signals — that's where the parallel-bundle value lives.

**Q: Can I run keyword research on a competitor's video?**
Yes — set `operation: "seedVideoResearch"` and paste the video URL. The actor calls `/video/info` (absorbed in the snapshot fee — no extra charge) to extract the video's tags + title, then runs full keyword research on the top extracted keyword.

**Q: How are hashtags matched from keywords?**
We normalize the keyword to a YouTube-style tag — lowercase, alphanumerics only, no spaces. So `rust programming` becomes `rustprogramming`. If the resulting tag has no trending videos, the row is emitted as `no_results` and not charged.

**Q: What region / language should I use?**
For most use cases, leave them empty (upstream defaults to US / English). Set `region: "GB"` for UK-focused research, `region: "IN"` for India-focused, `region: "DE"` for Germany. Pair with `language: "en"`, `"de"`, etc. when researching non-English content.

**Q: How many search results can I get?**
Default is 1 page (~20 results). Set `maxSearchPages` up to 5 to broaden the funnel. Same for related videos via `maxRelatedPages`.

**Q: How fast is bulk mode?**
3 keywords concurrent per batch. Local smoke test: 3 keywords × 3 endpoints = **136 rows in 3.3 seconds**.

**Q: What if I pass a brand-new keyword YouTube has zero data on?**
The actor pushes per-endpoint `status: no_results` rows for the empty endpoints (no charges) and still emits the `keyword_snapshot` anchor row showing the zeroes — useful for negative-signal mining.

**Q: Can I get the full video metadata for the top search result?**
Use our [YouTube Video 360 Intelligence Bundle](https://apify.com/sian.agency/youtube-video-360-intelligence?fpr=sian) (when available) — it takes the videoId from this actor's output and returns full metadata + transcript + related + subtitles for the video.

**Q: Why is `related` chained off the top search result?**
`/related` is a per-video endpoint, not a per-keyword endpoint. The algorithm's own related-video graph for the keyword's top-ranked video is the closest proxy to "what does YouTube think this keyword is about?" — and it's a far richer signal than running `/related` on an arbitrary seed.

***

### ⚠️ Trademark Disclaimer

YouTube® is a trademark of Google LLC. This actor is an independent data-discovery tool. It is not affiliated with, endorsed by, sponsored by, or supported by Google LLC or YouTube. All trademarks, registered trademarks, and brand names are the property of their respective owners.

***

### Legal & data privacy

This actor scrapes publicly accessible YouTube search and discovery data. Users are responsible for ensuring compliance with YouTube's Terms of Service and applicable data-protection laws (GDPR, CCPA, etc.) when using the data downstream. Don't scrape PII or use scraped data to harass / discriminate. See [Apify's blog on legal scraping](https://blog.apify.com/is-web-scraping-legal/).

***

### Support

- Email: apify@sian-agency.online
- Issues: use the Apify Console Issues tab for this actor
- More actors: [apify.com/sian.agency](https://apify.com/sian.agency?fpr=sian)

***

# Actor input Schema

## `operation` (type: `string`):

Pick the keyword research workflow.

- **`keywordResearch`** (default) — one seed keyword + region/lang → full bundle (search + suggest + related + hashtag).
- **`bulkKeywords`** — list of keywords sharing the same region/lang/endpoints; one snapshot per keyword.
- **`seedVideoResearch`** — paste a YouTube video URL/ID; we extract its top keywords and run keyword research around them.

## `keyword` (type: `string`):

Seed keyword for `keywordResearch` mode. Examples: `rust programming`, `home espresso 2026`, `productivity for designers`.

The actor runs `search`, `suggest_queries`, `hashtag`, and `related` (chained off the top search result) on this keyword and returns a tidy-long dataset with all four signal types tagged by `rowType`.

## `keywords` (type: `string`):

List of keywords for `bulkKeywords` mode (one snapshot per keyword). Comma-separated OR newline-separated. Max 50 keywords per run. Shares the same `region`, `language`, and `includeEndpoints` settings.

Example (one per line):

```
rust programming
golang vs rust
learn rust 2026
```

## `seedVideoUrl` (type: `string`):

For `seedVideoResearch` mode. Accepts any YouTube video URL or 11-char video ID. The actor calls `/video/info` to extract the top keywords from the video's tags + title, then runs full keyword research on the first extracted keyword.

The `/video/info` call is absorbed into the snapshot fee — you pay one `keyword-snapshot-result` event per seed video, not two.

## `includeEndpoints` (type: `array`):

Pick which endpoints to fetch per keyword snapshot. **Defaults to all 4** — leave empty for the full bundle. Endpoints that return empty/error responses are silently skipped — you are NEVER charged for unavailable endpoint pulls.

- `search` — top YouTube search results for the keyword (videos, channels, playlists)
- `suggest` — autocomplete suggestions (what people actually type)
- `hashtag` — trending videos under the closest matching hashtag
- `related` — related-video graph chained off the top search result (algorithm signal)

## `searchType` (type: `string`):

What kind of content `/search` should return. Default `video` is the SEO research norm (you're researching what videos rank for the keyword).

- `video` — only videos (default, best for keyword research)
- `channel` — only channels (for influencer/competitor discovery)
- `playlist` — only playlists
- `all` — mixed (videos, channels, playlists, shorts)

## `region` (type: `string`):

Two-letter country code that biases search/suggest results to a specific geography (e.g. `US`, `GB`, `IN`, `DE`, `BR`). Defaults to upstream's default (typically US). Useful when researching regional content trends.

## `language` (type: `string`):

Two-letter language code (e.g. `en`, `es`, `pt`, `ja`) that biases autocomplete + search to a specific language. Defaults to upstream's default. Useful for non-English content research.

## `maxSearchPages` (type: `integer`):

Pages of `/search` results to fetch per keyword (each page returns ~20 results). `1` is the snapshot default; bump to `2-3` for broader research; max `5`. Only applies when `search` is in `includeEndpoints`.

## `maxRelatedPages` (type: `integer`):

Pages of `/related` results to fetch per keyword (each page returns ~20 related videos). Default `1`. Only applies when `related` is in `includeEndpoints`.

## Actor input object example

```json
{
  "operation": "keywordResearch",
  "keyword": "rust programming",
  "keywords": "rust programming\ngolang vs rust\nlearn rust 2026",
  "seedVideoUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "includeEndpoints": [
    "search",
    "suggest",
    "hashtag",
    "related"
  ],
  "searchType": "video",
  "region": "US",
  "language": "en",
  "maxSearchPages": 1,
  "maxRelatedPages": 1
}
```

# Actor output Schema

## `output` (type: `string`):

Tidy-long rows. Filter by `rowType` (`keyword_snapshot`, `search_result`, `suggestion`, `related_video`, `hashtag_trend`, `error`) and `_sourceEndpoint` to slice the bundle. Every row tagged with `_sourceKeyword`, `_sourceMode`, and `_fetchedAt`.

## `report` (type: `string`):

HTML report with run status, success/error counts, per-endpoint and per-keyword breakdowns, pages fetched, duration, and inputs — written even on fatal crash.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("sian.agency/youtube-seo-keyword-research-pro").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("sian.agency/youtube-seo-keyword-research-pro").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 '{}' |
apify call sian.agency/youtube-seo-keyword-research-pro --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=sian.agency/youtube-seo-keyword-research-pro",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

````json
{
    "openapi": "3.0.1",
    "info": {
        "title": "YouTube SEO Keyword Research Pro — Search, Tags, Trends",
        "description": "Complete YouTube SEO keyword research toolkit. From one keyword get top search results, autocomplete suggestions, related videos, and trending hashtags. Built for creators, SEO agencies, and content strategists planning videos that win YouTube search.",
        "version": "1.0",
        "x-build-id": "qGwWDfnijt30U9jPu"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/sian.agency~youtube-seo-keyword-research-pro/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-sian.agency-youtube-seo-keyword-research-pro",
                "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/sian.agency~youtube-seo-keyword-research-pro/runs": {
            "post": {
                "operationId": "runs-sync-sian.agency-youtube-seo-keyword-research-pro",
                "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/sian.agency~youtube-seo-keyword-research-pro/run-sync": {
            "post": {
                "operationId": "run-sync-sian.agency-youtube-seo-keyword-research-pro",
                "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",
                "properties": {
                    "operation": {
                        "title": "🎯 Research mode",
                        "enum": [
                            "keywordResearch",
                            "bulkKeywords",
                            "seedVideoResearch"
                        ],
                        "type": "string",
                        "description": "Pick the keyword research workflow.\n\n- **`keywordResearch`** (default) — one seed keyword + region/lang → full bundle (search + suggest + related + hashtag).\n- **`bulkKeywords`** — list of keywords sharing the same region/lang/endpoints; one snapshot per keyword.\n- **`seedVideoResearch`** — paste a YouTube video URL/ID; we extract its top keywords and run keyword research around them.",
                        "default": "keywordResearch"
                    },
                    "keyword": {
                        "title": "🔍 Keyword (single)",
                        "type": "string",
                        "description": "Seed keyword for `keywordResearch` mode. Examples: `rust programming`, `home espresso 2026`, `productivity for designers`.\n\nThe actor runs `search`, `suggest_queries`, `hashtag`, and `related` (chained off the top search result) on this keyword and returns a tidy-long dataset with all four signal types tagged by `rowType`."
                    },
                    "keywords": {
                        "title": "🔍 Keywords (batch — comma or newline separated)",
                        "type": "string",
                        "description": "List of keywords for `bulkKeywords` mode (one snapshot per keyword). Comma-separated OR newline-separated. Max 50 keywords per run. Shares the same `region`, `language`, and `includeEndpoints` settings.\n\nExample (one per line):\n```\nrust programming\ngolang vs rust\nlearn rust 2026\n```"
                    },
                    "seedVideoUrl": {
                        "title": "🎬 Seed video URL / ID (for seedVideoResearch)",
                        "type": "string",
                        "description": "For `seedVideoResearch` mode. Accepts any YouTube video URL or 11-char video ID. The actor calls `/video/info` to extract the top keywords from the video's tags + title, then runs full keyword research on the first extracted keyword.\n\nThe `/video/info` call is absorbed into the snapshot fee — you pay one `keyword-snapshot-result` event per seed video, not two."
                    },
                    "includeEndpoints": {
                        "title": "🎯 Endpoints to include",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Pick which endpoints to fetch per keyword snapshot. **Defaults to all 4** — leave empty for the full bundle. Endpoints that return empty/error responses are silently skipped — you are NEVER charged for unavailable endpoint pulls.\n\n- `search` — top YouTube search results for the keyword (videos, channels, playlists)\n- `suggest` — autocomplete suggestions (what people actually type)\n- `hashtag` — trending videos under the closest matching hashtag\n- `related` — related-video graph chained off the top search result (algorithm signal)",
                        "items": {
                            "type": "string",
                            "enum": [
                                "search",
                                "suggest",
                                "hashtag",
                                "related"
                            ]
                        },
                        "default": [
                            "search",
                            "suggest",
                            "hashtag",
                            "related"
                        ]
                    },
                    "searchType": {
                        "title": "🔎 Search content type",
                        "enum": [
                            "video",
                            "channel",
                            "playlist",
                            "all"
                        ],
                        "type": "string",
                        "description": "What kind of content `/search` should return. Default `video` is the SEO research norm (you're researching what videos rank for the keyword).\n\n- `video` — only videos (default, best for keyword research)\n- `channel` — only channels (for influencer/competitor discovery)\n- `playlist` — only playlists\n- `all` — mixed (videos, channels, playlists, shorts)",
                        "default": "video"
                    },
                    "region": {
                        "title": "🌍 Region code (geo, optional)",
                        "type": "string",
                        "description": "Two-letter country code that biases search/suggest results to a specific geography (e.g. `US`, `GB`, `IN`, `DE`, `BR`). Defaults to upstream's default (typically US). Useful when researching regional content trends."
                    },
                    "language": {
                        "title": "🌐 Language code (lang, optional)",
                        "type": "string",
                        "description": "Two-letter language code (e.g. `en`, `es`, `pt`, `ja`) that biases autocomplete + search to a specific language. Defaults to upstream's default. Useful for non-English content research."
                    },
                    "maxSearchPages": {
                        "title": "📄 Max search pages",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Pages of `/search` results to fetch per keyword (each page returns ~20 results). `1` is the snapshot default; bump to `2-3` for broader research; max `5`. Only applies when `search` is in `includeEndpoints`.",
                        "default": 1
                    },
                    "maxRelatedPages": {
                        "title": "📄 Max related pages",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Pages of `/related` results to fetch per keyword (each page returns ~20 related videos). Default `1`. Only applies when `related` is in `includeEndpoints`.",
                        "default": 1
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
````
