# PeerTube Scraper: Videos, Channels, Accounts & Search (`perconey/peertube-scraper`) Actor

Scrape any PeerTube instance via the official /api/v1 REST API. Videos, channels, accounts, search - cross-instance federation routing. No browser, no proxies, no auth. Pay only per result item.

- **URL**: https://apify.com/perconey/peertube-scraper.md
- **Developed by:** [Perconey](https://apify.com/perconey) (community)
- **Categories:** Social media, Developer tools, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 result items

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

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

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

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

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

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

# README

### What does PeerTube Scraper do?

**PeerTube Scraper** pulls structured data from any [PeerTube](https://joinpeertube.org/) instance via the **official `/api/v1/*` REST API**. Videos with views, likes/dislikes, duration, embed link, thumbnails. Channels with subscriber counts. Accounts with follower counts. Full-text search. The actor calls the documented public API directly: no browser, no proxies, no cookies, no anti-bot fight. One actor works with **every PeerTube-protocol server** in the Fediverse: framatube.org, video.blender.org, tilvids.com, peertube.cpy.re, makertube.net, and hundreds more.

Try it instantly: pick **getVideos**, leave instance as `https://framatube.org`, click Start. You get the 30 newest Framatube videos (title, duration, views, likes, channel) in under 3 seconds for $0.03.

### Why use PeerTube Scraper?

- **Federation researchers**: Compare video communities across instances. Same channel concept exists on lots of servers with different culture and policies.
- **Indie video creators**: Find PeerTube instances that match your niche. Use `searchChannels` to discover where your audience lives outside of YouTube / Vimeo.
- **OSS maintainers**: Track talks and demos about your project. Schedule daily `searchVideos` runs with your project name.
- **Trend analysts**: Both likes AND dislikes are exposed (unlike YouTube). Compute controversy ratios on educational / political videos.
- **Academic researchers**: PeerTube is a federated decentralized video platform on ActivityPub - rich material for network science studies.
- **YouTube alternatives advocates**: Build a discovery layer that surfaces high-quality PeerTube content to mainstream audiences.

### How to use PeerTube Scraper

1. Open the **Input** tab.
2. Pick an **action** from the dropdown. `getVideos` is the simplest starting point.
3. Set **instance** (default `https://framatube.org`). To scrape a different server, paste its URL.
4. For channel / account / video-detail / search actions, fill **queries**.
5. Tune **sort** (-publishedAt / -views / -likes / -trending) and **maxItems** (default 30).
6. Toggle **nsfw** off if you want to skip adult content.
7. Click **Start**.

#### Query format by action

Action | Query format
\--- | ---
getVideos | leave empty (uses instance + sort)
searchVideos | free-text search query
getVideoDetail | video uuid (e.g. `9845e20c-7236-4270-8b69-88530a61f616`) or numeric id
getChannels | leave empty (uses instance)
searchChannels | free-text search query
getChannelVideos | `name@host` (e.g. `blender_open_movies@video.blender.org`)
getAccountProfile | `name@host` (e.g. `framasoft@framatube.org`)
getAccountVideos | `name@host`

### Input

Field | Required | Description
\--- | --- | ---
`action` | yes | Which API call to make. Eight options.
`instance` | yes | PeerTube instance URL. Default https://framatube.org.
`queries` | sometimes | Required for search / detail / channel / account actions. Empty for the per-instance feeds.
`maxItems` | no | Max items per query. Default 30.
`sort` | no | `-publishedAt` (default), `-views`, `-likes`, `-trending`, or `publishedAt`.
`nsfw` | no | Include NSFW content. Default true (passes through with the nsfw flag for downstream filtering).

### Output

Every item carries `_type` (`video` / `channel` / `account` / `error`) plus `_action` and `_instance`.

```json
{
    "_type": "video",
    "_action": "getVideos",
    "_instance": "https://framatube.org/",
    "id": 65272,
    "uuid": "9845e20c-7236-4270-8b69-88530a61f616",
    "name": "Why Free Software Matters for Climate Justice",
    "duration": 1284,
    "views": 12450,
    "likes": 312,
    "dislikes": 4,
    "comments": 27,
    "publishedAt": "2026-05-10T14:00:00Z",
    "nsfw": false,
    "isLive": false,
    "thumbnail_url": "https://framatube.org/lazy-static/thumbnails/...",
    "embed_url": "https://framatube.org/videos/embed/9845e20c-...",
    "url": "https://framatube.org/w/9845e20c-...",
    "channel": { "name": "framasoft", "displayName": "Framasoft", "host": "framatube.org" },
    "account": { "name": "framasoft", "displayName": "Framasoft", "host": "framatube.org" }
}
```

You can download the dataset in JSON, CSV, XML, Excel, RSS or HTML format from the Output tab.

### Data fields

Type | Key fields
\--- | ---
`video` | id, uuid, name, description, duration, views, likes, dislikes, comments, publishedAt, nsfw, isLive, category, language, thumbnail\_url, embed\_url, url, channel, account
`channel` | id, name, displayName, host, description, followersCount, followingCount, url, avatar, ownerAccount
`account` | id, name, displayName, host, description, followersCount, followingCount, url, avatar

### Pricing

**Pay-per-result: $0.001 per item.** No flat monthly fee.

Cost examples:

- Daily 30 newest Framatube videos: **$0.03**
- 1,000 videos from a creator: **$1.00**
- 50 channels matching a search term: **$0.05**
- Top-100 most-viewed videos on an instance: **$0.10**

### Tips

- **Cross-instance routing is automatic.** Write `blender_open_movies@video.blender.org` and the actor talks to video.blender.org even if your `instance` field points to framatube.org. Same pattern as Mastodon / Lemmy.
- **Likes AND dislikes are exposed.** Compute `controversy = min(likes, dislikes) / max(likes, dislikes)` to find polarizing content.
- **Sort options matter.** PeerTube does NOT have a "trending" endpoint, but `-trending` as a sort parameter approximates it.
- **NSFW filtering is client-side.** The API does not let you exclude NSFW on the server; the actor passes the flag through and (optionally) filters in-process.

### FAQ, disclaimers, support

**Is this legal?** The actor calls each PeerTube instance's official public REST API with documented endpoints. Public read access is the design intent of the AGPL-licensed PeerTube software. We send a clear User-Agent identifying the actor and honor rate-limit / Retry-After headers.

**Will I get rate-limited?** PeerTube's per-IP rate limits are generous for read-only traffic and the actor backs off on 429 / Retry-After. For very heavy scraping consider donating to the instance you're hitting most.

**Why is getChannelVideos failing for a channel?** PeerTube channel records live on the channel's HOME instance. Use the `name@host` format like `blender_open_movies@video.blender.org`. The actor auto-routes.

**What about live streams?** `isLive: true` videos appear in the feed. The actor returns metadata only - it does not download the stream.

**Bug or feature request?** Open an Issue on the actor's Issues tab. I usually respond within a day.

**Need a scraper for Mastodon, Lemmy, Bluesky, Hacker News, dev.to, arxiv?** See my other actors at https://apify.com/perconey.

# Actor input Schema

## `action` (type: `string`):

Pick the action. getVideos / getChannels / searchVideos / searchChannels work without queries. The rest need a handle (name@host) or video id/uuid.

## `instance` (type: `string`):

Base URL of the instance to query. Cross-instance routing is automatic for channel/account handles in the form name@host - the actor switches to the right instance even if you pass a different one here.

## `queries` (type: `array`):

One entry per query. searchVideos / searchChannels: free text. getVideoDetail: video id or uuid (e.g. 9845e20c-7236-4270-8b69-88530a61f616). Channel / account actions: name@host (e.g. blender\_open\_movies@video.blender.org).

## `sort` (type: `string`):

PeerTube accepts a prefix - for descending: -publishedAt = newest first, -views = most-viewed, -likes = most-liked, -trending = trending. Leave on -publishedAt for the canonical feed.

## `maxItems` (type: `integer`):

Stop after this many items per query. The actor paginates in batches of 100 (PeerTube's max per request).

## `nsfw` (type: `boolean`):

PeerTube marks adult content with nsfw=true. Default is to include them with the flag passed through; toggle off to skip.

## Actor input object example

```json
{
  "action": "getVideos",
  "instance": "https://framatube.org/",
  "queries": [],
  "sort": "-publishedAt",
  "maxItems": 30,
  "nsfw": true
}
```

# Actor output Schema

## `dataset` (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 = {
    "instance": "https://framatube.org/",
    "queries": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("perconey/peertube-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 = {
    "instance": "https://framatube.org/",
    "queries": [],
}

# Run the Actor and wait for it to finish
run = client.actor("perconey/peertube-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 '{
  "instance": "https://framatube.org/",
  "queries": []
}' |
apify call perconey/peertube-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,perconey/peertube-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/D38Egkki5ZPQpJKc3/builds/M1kGWKgcsYcDwnPGF/openapi.json
