# YouTube Most Replayed Scraper - Heatmap Peaks & Clips (`steadyscrape/youtube-most-replayed-scraper`) Actor

YouTube's Most replayed heatmap for videos, playlists, channels and searches: the replay curve, YouTube's labelled moments and the top peaks with start/end seconds, intensity, chapter and a timestamped link; optional caption text per peak. No login.

- **URL**: https://apify.com/steadyscrape/youtube-most-replayed-scraper.md
- **Developed by:** [Steady Scrape](https://apify.com/steadyscrape) (community)
- **Categories:** Videos, Social media, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 videos

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## YouTube Most Replayed Scraper

The **Most replayed** heatmap of any YouTube video, Short, playlist, channel or search: YouTube's own labelled "Most replayed" moments, the **top peaks of the replay curve** with start and end seconds, intensity, the chapter they fall in and a timestamped `&t=` link, and on request the full 100-point curve and the **words spoken inside each peak**. Title, channel, exact views, likes, publish date and duration on every row.

Built for clip makers, Shorts editors and AI clipping tools: find the 30 seconds people rewatch, jump straight to them, and cut. **Every video comes back as a row**: when YouTube draws no graph for it, one free row says why. You pay only for videos with a heatmap.

No browser, no login, no API key, no YouTube Data API quota, **no video or audio is downloaded**: it reads the same watch data the site shows above the progress bar.

### What you get

One row per video:

| field | what it holds |
|---|---|
| `status`, `reason` | `ok`, or a free row: `no_heatmap` (YouTube draws no graph for this video), `filtered` (below your `minViews`), `unavailable` (deleted, private or a wrong id), `blocked` (YouTube refused every IP route; try again later). `reason` says why; it is null on `ok`. |
| `mostReplayed` | The ranges YouTube itself labels "Most replayed" on the graph (often one to three), each with `startSeconds`, `endSeconds`, `peakSeconds` (the middle of the most replayed slice inside), `intensity` (0–1, 1 = the most replayed slice of the video), `chapter`, `url` (the video opened at that second) and `transcript`. |
| `peaks` | The top peaks of the curve, most replayed first (`maxPeaks`, default 5), with the same fields plus `rank`, `prominence` (how far the peak rises above the valleys around it) and `isOpening`. The stretch of a peak runs down each side while the curve keeps falling, so two neighbouring peaks never overlap. |
| `heatmap` | With `includeHeatmap`: YouTube's 100 slices, each `startSeconds`, `durationSeconds`, `intensity`; null otherwise. |
| `chapters` | The video's chapters (`title`, `startSeconds`), empty when it has none. |
| `videoId`, `url`, `title`, `thumbnailUrl` | The video. |
| `channelName`, `channelId`, `channelUrl`, `channelSubscribers` | The channel; subscribers as the page abbreviates them ("8.71M" → 8710000). |
| `viewCount`, `likeCount` | Exact counts; `viewCount` is null on a stream on air, which shows viewers watching now instead. |
| `publishDate`, `publishDateText` | `YYYY-MM-DD`, and the date as the page writes it ("Premiered Jul 22, 2023"). |
| `durationSeconds` | The end of the curve, within a second of the player's length (null on free rows). |
| `transcriptStatus`, `transcriptLanguage`, `transcriptIsAutoGenerated` | With `includeTranscript`: `ok`, `no_captions`, `age_restricted`, `login_required`, `unavailable` or `blocked`, and which caption track was read. Each moment's `transcript` holds the caption lines heard between its start and end. |
| `source`, `scrapedAt` | The video, playlist, channel or search term the row came from (`type`, `id`), and when it was read (UTC). |

### Input

| field | what it does |
|---|---|
| `urls` | One per line: a video link in any shape (`watch?v=`, `youtu.be`, Shorts, live, embed) or a bare id; a playlist link or id; a channel (`@handle`, `/channel/UC…`, `/c/`, `/user/`). A channel gives its newest uploads. |
| `searchTerms` | Search YouTube (videos only) and read the top results. |
| `searchSort`, `searchUploadedWithin` | Relevance or view count; any time, last hour, today, this week, this month, this year. |
| `maxVideosPerSource` | Videos per playlist, channel or search term (default 10, up to 1,000). |
| `maxPeaks` | Peaks per video (default 5; 0 = only YouTube's labelled moments). |
| `minIntensity` | Leave out peaks below this share of the top (default 0.15; 0 keeps every bump). |
| `includeOpening` | Keep the opening seconds among the peaks (off by default: every viewer starts there, so it is the top of most curves). Turn on for Shorts. |
| `includeHeatmap` | Add the 100-point curve. Same price. |
| `minViews` | Skip smaller videos as free `filtered` rows. |
| `includeTranscript`, `transcriptLanguage` | Add the words spoken inside each moment, from the captions in that language (or the default track). |
| `onlyNew` | For schedules: skip videos an earlier run with the same sources already delivered. Videos without a graph yet are asked again next time. |
| `residentialFallback` | Retry through residential proxies when YouTube refuses Apify's own IP and a datacenter proxy (default on; captions usually need it). |

```json
{
    "urls": ["https://www.youtube.com/watch?v=aircAruvnKk", "@MrBeast"],
    "searchTerms": ["podcast clips"],
    "searchSort": "views",
    "searchUploadedWithin": "month",
    "maxVideosPerSource": 10,
    "maxPeaks": 3,
    "includeTranscript": true
}
```

### Output example

```json
{
    "videoId": "aircAruvnKk",
    "url": "https://www.youtube.com/watch?v=aircAruvnKk",
    "status": "ok",
    "reason": null,
    "title": "But what is a neural network? | Deep learning chapter 1",
    "channelName": "3Blue1Brown",
    "channelId": "UCYO_jab_esuFRV4b17AJtAw",
    "channelUrl": "https://www.youtube.com/@3blue1brown",
    "channelSubscribers": 8710000,
    "viewCount": 24927606,
    "likeCount": 567354,
    "publishDate": "2017-10-05",
    "publishDateText": "Oct 5, 2017",
    "thumbnailUrl": "https://i.ytimg.com/vi/aircAruvnKk/hqdefault.jpg",
    "durationSeconds": 1120,
    "mostReplayed": [
        { "startSeconds": 504, "endSeconds": 582.4, "peakSeconds": 554.4, "intensity": 1, "url": "https://www.youtube.com/watch?v=aircAruvnKk&t=504s", "chapter": "Edge detection example", "transcript": "picture yourself right now designing how exactly the activations in one layer might determine the activations in the next…" },
        { "startSeconds": 616, "endSeconds": 660.8, "peakSeconds": 632.8, "intensity": 0.825, "url": "https://www.youtube.com/watch?v=aircAruvnKk&t=616s", "chapter": "Edge detection example", "transcript": "When you compute a weighted sum like this, you might come out with any number…" }
    ],
    "peaks": [
        { "rank": 1, "startSeconds": 504, "endSeconds": 616, "peakSeconds": 554.4, "intensity": 1, "prominence": 0.895, "isOpening": false, "url": "https://www.youtube.com/watch?v=aircAruvnKk&t=504s", "chapter": "Edge detection example", "transcript": "picture yourself right now…" },
        { "rank": 2, "startSeconds": 627.2, "endSeconds": 660.8, "peakSeconds": 632.8, "intensity": 0.825, "prominence": 0.076, "isOpening": false, "url": "https://www.youtube.com/watch?v=aircAruvnKk&t=627s", "chapter": "Edge detection example", "transcript": "…" },
        { "rank": 3, "startSeconds": 694.4, "endSeconds": 705.6, "peakSeconds": 700, "intensity": 0.712, "prominence": 0.095, "isOpening": false, "url": "https://www.youtube.com/watch?v=aircAruvnKk&t=694s", "chapter": "Counting weights and biases", "transcript": "…" }
    ],
    "chapters": [{ "title": "Introduction example", "startSeconds": 0 }, { "title": "Series preview", "startSeconds": 67 }, { "title": "What are neurons?", "startSeconds": 162 }],
    "heatmap": null,
    "transcriptStatus": "ok",
    "transcriptLanguage": "en",
    "transcriptIsAutoGenerated": false,
    "source": { "type": "channel", "id": "UCYO_jab_esuFRV4b17AJtAw" },
    "scrapedAt": "2026-10-22T12:00:00.000Z"
}
```

The dataset has a second view, **Peaks**, with one row per peak: video, rank, start, end, intensity, chapter, words and link, ready for a clipping queue.

### Use cases

- **Clipping and Shorts**: the top 3 peaks of every new upload of the channels you clip, on a schedule with `onlyNew`, each with its start, end and link.
- **AI clipping tools**: feed `peaks` and their `transcript` to your editor or an LLM to title and cut the moments viewers rewatch.
- **Creators**: see which minute of a competitor's video people replay, and what was said there, before you script your hook.
- **Research**: replay curves of a whole search (top videos of the month about a topic) or a playlist, as 100 numbers per video.

### Limits and honesty

- **YouTube draws the graph only once a video has enough views**, and never for live streams, most age-restricted videos and many Shorts. Fresh uploads often have none yet (22 of the 36 most viewed uploads of one month had none on 2026-10-22). Those rows are free; with `onlyNew` they are asked again on the next run.
- The curve is normalised by YouTube: `intensity` 1 is the video's most replayed slice, not a view count. A slice is 1/100 of the video (11 s on an 18-minute video, 0.2 s on a 20-second Short).
- Peaks are computed from YouTube's curve with a fixed rule (local high points, their prominence, and the stretch where the curve stays above half that rise); `mostReplayed` is YouTube's own labelling, returned as is. On the videos measured the two agree: YouTube's labelled ranges past the opening held a peak in 33 of 34 cases.
- `channelSubscribers` is abbreviated by YouTube ("8.71M"); views and likes are exact. A few Shorts leave the channel out of their page: those fields are null.
- Transcripts come from the video's captions (manual first, else auto-generated). YouTube refuses captions to many datacenter IPs, so they are read through residential proxies when needed; a video whose captions could not be read is delivered at the plain price with `transcriptStatus` saying why.
- When YouTube refuses Apify's own IP the Actor moves to a datacenter, then a residential proxy, and never asks a refused IP again in that run; it never solves a CAPTCHA or a bot check. If every route is refused, the remaining videos are free `blocked` rows and the run still succeeds.

### Pricing

Pay per event, and only for videos with a heatmap:

- `video` — **US$0.0015**: one video's labelled moments, top peaks, chapters, metadata, and the curve if asked.
- `video-with-transcript` — **US$0.003**: the same plus the words spoken inside every moment, charged only when the captions were read.

`no_heatmap`, `filtered`, `unavailable` and `blocked` rows are free, and so is every video skipped by `onlyNew`. Set a spending limit on the run and the Actor stops at it.

### Legal

This Actor is unofficial and is not affiliated with, endorsed by or sponsored by YouTube or Google. It reads public data YouTube shows to anyone without logging in (the replay graph, titles and counts) and downloads no video or audio. Use the data in line with YouTube's terms and the laws that apply to you.

# Actor input Schema

## `urls` (type: `array`):

One per line: a video link in any shape (<code>watch?v=</code>, <code>youtu.be</code>, Shorts, live, embed) or a bare video id; a playlist link or id; a channel link (<code>@handle</code>, <code>/channel/UC…</code>, <code>/c/</code>, <code>/user/</code>) or a bare <code>@handle</code>. A playlist gives its first videos, a channel its newest uploads.

## `searchTerms` (type: `array`):

Optional. Each term is searched on YouTube (videos only) and its top results are read, in the order and upload window chosen below.

## `searchSort` (type: `string`):

YouTube's own orders for a search: relevance, or most viewed first.

## `searchUploadedWithin` (type: `string`):

Only videos uploaded within this window. Fresh uploads often have no Most replayed graph yet (YouTube draws it once a video has enough views): those come back as free <code>no_heatmap</code> rows.

## `maxVideosPerSource` (type: `integer`):

How many videos to read from each playlist, channel (newest first) or search term. Videos given directly are not counted.

## `maxPeaks` (type: `integer`):

How many peaks of the replay curve to return, most replayed first, each with start and end seconds, intensity and a timestamped link. 0 returns only YouTube's own labelled moments (and the curve if asked).

## `minIntensity` (type: `number`):

Leave out peaks whose top is below this share of the video's most replayed slice (0 to 1). The default drops bumps on the floor of the curve; 0 keeps every peak.

## `includeOpening` (type: `boolean`):

The first seconds are the most replayed part of most videos because every viewer starts there, so they are left out of the peaks. Turn on for Shorts or to keep them (they are marked <code>isOpening</code>).

## `includeHeatmap` (type: `boolean`):

Add the 100 points of YouTube's replay curve to each video: start and length in seconds and intensity 0–1. Same price.

## `minViews` (type: `integer`):

Videos with fewer views are returned as free <code>filtered</code> rows and not charged. 0: no minimum.

## `includeTranscript` (type: `boolean`):

Read the video's captions and add the text spoken inside every peak and labelled moment. Charged as <code>video-with-transcript</code> only when captions were read; otherwise the video is the plain price and <code>transcriptStatus</code> says why.

## `transcriptLanguage` (type: `string`):

Language code of the captions to read (<code>en</code>, <code>es</code>, <code>pt-BR</code>…). Empty, or missing on the video: its default caption track.

## `onlyNew` (type: `boolean`):

Skip videos an earlier run with the same sources already delivered, so a schedule on a channel returns only its new uploads. Videos without a graph yet are asked again next time.

## `residentialFallback` (type: `boolean`):

When YouTube refuses Apify's own IP and a datacenter proxy, retry through Apify's residential proxy (a few KB per video, included in the price). Captions usually need it. Off: such videos end as free <code>blocked</code> rows.

## Actor input object example

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=aircAruvnKk",
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "searchSort": "relevance",
  "searchUploadedWithin": "any",
  "maxVideosPerSource": 10,
  "maxPeaks": 5,
  "minIntensity": 0.15,
  "includeOpening": false,
  "includeHeatmap": false,
  "minViews": 0,
  "includeTranscript": false,
  "onlyNew": false,
  "residentialFallback": true
}
```

# Actor output Schema

## `videos` (type: `string`):

No description

## `summary` (type: `string`):

No description

# 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 = {
    "urls": [
        "https://www.youtube.com/watch?v=aircAruvnKk",
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/youtube-most-replayed-scraper").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 = { "urls": [
        "https://www.youtube.com/watch?v=aircAruvnKk",
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("steadyscrape/youtube-most-replayed-scraper").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 '{
  "urls": [
    "https://www.youtube.com/watch?v=aircAruvnKk",
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ]
}' |
apify call steadyscrape/youtube-most-replayed-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyscrape/youtube-most-replayed-scraper"
        }
    }
}
```

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/PTCn4W43Znd5KWN18/builds/SQQx7kM7YaHvDhKge/openapi.json
