# Skool Video Scraper (`hgservices/skool-video-scraper`) Actor

Download videos from Skool classroom lessons, or resolve a lesson URL to its underlying playable video URL. Handles both third-party embeds (Loom/YouTube/Vimeo) and self-hosted Mux streams.

- **URL**: https://apify.com/hgservices/skool-video-scraper.md
- **Developed by:** [Harish Garg](https://apify.com/hgservices) (community)
- **Categories:** Videos, AI, MCP servers
- **Stats:** 1 total users, 1 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

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

## Skool Video Downloader

**Download videos from [Skool](https://www.skool.com) classroom lessons** — or just **resolve a lesson URL to its underlying playable video URL** without downloading. Give it a public Skool lesson page link and it figures out where the video actually lives, whether that's a **third-party embed (Loom, YouTube, Vimeo, Wistia)** or a **self-hosted Mux stream**, then hands you the file or the link.

This Actor runs on the [Apify platform](https://apify.com), so you get **API access, scheduling, proxy rotation, and run monitoring** out of the box.

### What does Skool Video Downloader do?

Skool has no download button, and the way it serves video makes saving a lesson surprisingly hard:

- **Embedded lessons** point to another platform (Loom, YouTube, Vimeo, Wistia). The real video URL is buried in the page data.
- **Self-hosted lessons** stream from Mux as a **signed, short-lived, referrer-gated HLS playlist** (`.m3u8?token=<JWT>`). A stream URL copied from devtools stops working the moment you leave the page or the token expires.

This Actor reads the public Skool lesson page, resolves the lesson to its true video source, and then either **downloads the full video file** (saved to the key-value store as an MP4) or **returns the playable URL** — no manual devtools digging, no expired-token guesswork.

### Why use Skool Video Downloader?

- **Archive course content** you have access to, in a stable MP4 you actually own a copy of.
- **Feed videos into a pipeline** — transcription, clipping, summarization, re-encoding.
- **Get a fetchable URL** instead of a one-shot tokenized stream that dies when you navigate away.
- **Automate it** — schedule runs, trigger via API/webhooks, and integrate with the rest of your stack on Apify.

### How to download videos from Skool

1. Open the Skool lesson in your browser and copy its page URL — it usually contains `?md=<lessonId>`.
2. Paste it into the **Skool Lesson URL** field.
3. Choose **What to do**: *Download the video file* or *Resolve the video URL only*.
4. (Optional) Set **Max Video Minutes** to skip anything longer than your cap.
5. Click **Start**. When the run finishes, the result is in the **Output** tab, and for download mode the MP4 is in **Storage → Key-value store**.

> ℹ️ The Actor loads Skool pages **anonymously** — it can't sign in, so the lesson must be on a publicly accessible (free/open) community page.

### Input

| Field | Description |
|---|---|
| `skoolUrl` | **Required.** The Skool classroom lesson page URL (contains `?md=<lessonId>`). |
| `outputMode` | `downloadVideo` (default) — download the file; or `resolveUrl` — just return the video URL. |
| `maxVideoMinutes` | Optional. Skip videos longer than this, in minutes (download mode only). |
| `proxyConfiguration` | Optional Apify Proxy. Off by default; enable RESIDENTIAL only if Skool blocks the server IP. |

#### Input example

```json
{
    "skoolUrl": "https://www.skool.com/my-community/classroom/abc123?md=def456",
    "outputMode": "downloadVideo"
}
````

### Output

Each run pushes **one item** to the dataset. In **download mode**, the video file itself is saved to the **key-value store** and linked from the item via `videoFile`. You can download the dataset in various formats such as **JSON, CSV, Excel, or HTML**.

#### Download mode

```json
{
    "skoolUrl": "https://www.skool.com/my-community/classroom/abc123?md=def456",
    "title": "Glenn Marcus - $60K in 5 Days",
    "status": "downloaded",
    "isSelfHosted": true,
    "videoFile": "https://api.apify.com/v2/key-value-stores/<storeId>/records/Glenn-Marcus---60K-in-5-Days.mp4",
    "fileName": "Glenn-Marcus---60K-in-5-Days.mp4",
    "fileSizeBytes": 53018337,
    "ext": "mp4",
    "durationSeconds": 562,
    "width": 1280,
    "height": 720,
    "resolvedVideoUrl": "https://stream.video.skool.com/<playbackId>.m3u8?token=..."
}
```

#### Resolve-only mode

```json
{
    "skoolUrl": "https://www.skool.com/my-community/classroom/abc123?md=def456",
    "title": "Glenn Marcus - $60K in 5 Days",
    "status": "resolved",
    "isSelfHosted": true,
    "resolvedVideoUrl": "https://stream.video.skool.com/<playbackId>.m3u8?token=...",
    "referer": "https://www.skool.com/"
}
```

> ⚠️ **Self-hosted (Mux) URLs are signed, short-lived, and referrer-bound.** If you resolve one and fetch it yourself, you must send the `Referer: https://www.skool.com/` header and use it promptly before the token expires. Download mode handles this for you.

#### Data fields

| Field | Description |
|---|---|
| `title` | Lesson title (for self-hosted) or extractor title (for embeds). |
| `status` | `downloaded`, `resolved`, or `failed`. |
| `isSelfHosted` | `true` for self-hosted Mux streams, `false` for third-party embeds. |
| `resolvedVideoUrl` | The underlying playable video URL. |
| `referer` | Required Referer header for self-hosted streams (else `null`). |
| `videoFile` | Key-value store URL of the downloaded file (download mode). |
| `fileName` | File name used for the stored video. |
| `fileSizeBytes`, `ext`, `durationSeconds`, `width`, `height` | Downloaded file metadata. |
| `statusMessage` | Human-readable result or error explanation. |

### Tips and advanced options

- **Pick the exact lesson.** If your URL points at a classroom with several lessons rather than one, open the specific lesson so the URL includes `?md=...`. Otherwise the Actor can't tell which video you want.
- **Resolve before you download.** Run `resolveUrl` first to confirm the lesson has a playable video and see whether it's an embed or self-hosted, then download.
- **Leave the proxy off.** Skool pages and most embeds load fine — and faster — without a proxy. Only enable Apify Proxy (e.g. the RESIDENTIAL group) if Skool starts blocking the datacenter IP.
- **Cap long videos.** `maxVideoMinutes` skips anything over your limit and reports it cleanly, so a stray multi-hour recording doesn't blow up a run.
- **Automate it.** Schedule recurring runs or call the Actor from the Apify API / webhooks to pull new lessons into your own workflow automatically.

### FAQ, limitations, and support

**Can it download members-only or paid lessons?**
No. The Actor downloads anonymously and can't authenticate, so private/paywalled lessons return a `failed` item explaining this. Use it for publicly accessible lessons you have the rights to.

**Can I submit a raw `stream.video.skool.com/...m3u8` link?**
No — those are tokenized streams tied to your session and IP, and they expire. Submit the lesson **page** URL (the one containing `?md=...`) instead.

**Why did my run say there's no video?**
The lesson may be text-only, members-only, or still processing on Skool's side. Open it in a browser to confirm it plays, then re-submit.

**Is this legal?**
Only download content you have the rights to access and use. **You are responsible for complying with [Skool's Terms of Service](https://www.skool.com)** and the content owner's rights. This Actor does not bypass authentication or paywalls.

**Found a bug or need a tweak?** Use the **Issues** tab on the Actor's page — feedback and feature requests are welcome.

# Actor input Schema

## `skoolUrl` (type: `string`):

URL of a Skool classroom lesson page (e.g. https://www.skool.com/<community>/classroom/<id>?md=<lessonId>). The Actor reads the lesson's video from the public page — it can't sign in, so the lesson must be publicly accessible.

## `outputMode` (type: `string`):

Download the full video file into the key-value store, or just resolve the lesson to its underlying playable video URL without downloading.

## `maxVideoMinutes` (type: `integer`):

Skip videos longer than this many minutes (download mode only). Leave empty for no limit.

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

Optional Apify Proxy. Off by default — Skool pages and most embeds load fine and faster without a proxy. Enable (e.g. RESIDENTIAL group) only if Skool blocks the server IP.

## Actor input object example

```json
{
  "skoolUrl": "https://www.skool.com/ai-automation-society/classroom/7f8b31ca?md=f44c0d98e63c4d3ead7aa6c3996676fc",
  "outputMode": "downloadVideo",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `videoFiles` (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 = {
    "skoolUrl": "https://www.skool.com/ai-automation-society/classroom/7f8b31ca?md=f44c0d98e63c4d3ead7aa6c3996676fc",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("hgservices/skool-video-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 = {
    "skoolUrl": "https://www.skool.com/ai-automation-society/classroom/7f8b31ca?md=f44c0d98e63c4d3ead7aa6c3996676fc",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("hgservices/skool-video-scraper").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 '{
  "skoolUrl": "https://www.skool.com/ai-automation-society/classroom/7f8b31ca?md=f44c0d98e63c4d3ead7aa6c3996676fc",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call hgservices/skool-video-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Skool Video Scraper",
        "description": "Download videos from Skool classroom lessons, or resolve a lesson URL to its underlying playable video URL. Handles both third-party embeds (Loom/YouTube/Vimeo) and self-hosted Mux streams.",
        "version": "0.1",
        "x-build-id": "HCcZTIFTwLCgNyK5q"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/hgservices~skool-video-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-hgservices-skool-video-scraper",
                "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/hgservices~skool-video-scraper/runs": {
            "post": {
                "operationId": "runs-sync-hgservices-skool-video-scraper",
                "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/hgservices~skool-video-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-hgservices-skool-video-scraper",
                "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": [
                    "skoolUrl"
                ],
                "properties": {
                    "skoolUrl": {
                        "title": "Skool Lesson URL",
                        "type": "string",
                        "description": "URL of a Skool classroom lesson page (e.g. https://www.skool.com/<community>/classroom/<id>?md=<lessonId>). The Actor reads the lesson's video from the public page — it can't sign in, so the lesson must be publicly accessible."
                    },
                    "outputMode": {
                        "title": "What to do",
                        "enum": [
                            "downloadVideo",
                            "resolveUrl"
                        ],
                        "type": "string",
                        "description": "Download the full video file into the key-value store, or just resolve the lesson to its underlying playable video URL without downloading.",
                        "default": "downloadVideo"
                    },
                    "maxVideoMinutes": {
                        "title": "Max Video Minutes",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Skip videos longer than this many minutes (download mode only). Leave empty for no limit."
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "Optional Apify Proxy. Off by default — Skool pages and most embeds load fine and faster without a proxy. Enable (e.g. RESIDENTIAL group) only if Skool blocks the server IP.",
                        "default": {
                            "useApifyProxy": 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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
