# YouTube Community Tab Post & Poll Scraper (`dataspryva/youtube-community-tab-post-and-poll-scraper`) Actor

Read a YouTube channel's Community tab and get structured records for every text post, image, poll, and shared video, with vote counts and optional comment threads.

- **URL**: https://apify.com/dataspryva/youtube-community-tab-post-and-poll-scraper.md
- **Developed by:** [Dataspryva](https://apify.com/dataspryva) (community)
- **Categories:** Social media, Videos, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

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

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 Community Posts, Polls & Comments Scraper

Read a YouTube channel's Posts (Community) tab — or a single post URL — and get clean records for text posts, image carousels, shared videos, polls, quizzes, playlists and reposts. Exact publish dates and like counts, comment counts and comment threads are available without logging in.

### What this actor does

- **Three modes:** `channelPosts` reads a channel feed, `postDetails` enriches one post per URL or ID, and `postComments` returns one row per comment.
- **Every public post type:** text, single image, image carousel, shared video, text poll, image poll, quiz, shared playlist and repost with the original post's content and attachments.
- **Exact engagement:** exact ISO publish date, exact like count and exact comment count when details are enabled; the text YouTube displays is kept too.
- **Comments that work:** up to 1,000 top-level comments per post, Top or Newest order, and optional replies.
- **Filters (in `channelPosts` mode):** post type, keyword and exact publish-date range.
- **Clean output:** one best-resolution URL per image, resolved external links, hashtags and normalized UTC dates. Empty fields are omitted.

### Output per post

- `recordType` — `community_post` for a post, `comment` in postComments mode, or `status` for an explanatory row
- `postId`, `postUrl` — YouTube's post ID and canonical link
- `postType` — `text`, `image`, `video`, `poll`, `quiz`, `playlist` or `shared`
- `channelId`, `channelName`, `channelHandle`, `channelUrl` — the channel whose tab was read
- `channelSubscriberCountText` — subscriber label shown on the channel page
- `authorName` — the post or repost author
- `contentText` — post text as YouTube displays it; a long URL may be shortened here, with the full target in `links[]`
- `links[]` — full external URLs found in the post text
- `hashtags[]` — hashtags found in the post text
- `publishedTimeText`, `isEdited` — relative label and edited marker
- `publishedAt` — exact ISO 8601 UTC publish date (details on)
- `voteCountText`, `likeCount` — displayed likes and exact likes
- `commentCountText`, `commentCount` — displayed and exact comment counts
- `commentsDisabled` — present when the creator turned comments off
- `images[]`, `imageDetails[]` — one best-resolution URL per image, with dimensions
- `videoAttachments[]` — shared video ID, title, URL, thumbnail, description, views, length, owner and badges
- `poll` — `pollChoices`, optional `pollOptions` with images, total votes text and parsed approximate total
- `quiz` — choices with `isCorrect` and `explanation`, plus total answers
- `playlist` — playlist ID, title, video count, URL and thumbnail
- `sharedPost` — a repost's original post: author, text, date label, likes label and attachments
- `isMembership` — present only when YouTube exposes a members-only badge
- `commentPreview[]` — first three comments when details are on but full comments are not requested
- `comments[]` — comment rows with author, text, time, likes, reply count and optional `replies[]`
- `scrapedAt` — ISO 8601 scrape timestamp

### Output per comment (`postComments` mode)

One row per top-level comment and, when enabled, one row per reply:

- `recordType` — `comment`
- `postId`, `postUrl`, `channelId`, `channelName`, `channelHandle`, `channelUrl`
- `commentId`, `parentCommentId`, `replyLevel`
- `authorName`, `authorChannelId`, `authorChannelUrl`, `authorHandle`
- `text`, `publishedTimeText`, `likeCountText`, `replyCount`
- `isCreator`, `isVerified`, `isPinned`, `isHearted`
- `scrapedAt`

Status rows use `recordType: "status"` with a `status` value such as `channel_not_found`, `no_community_tab`, `post_not_found` or `comments_disabled`.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `channelPosts` | `channelPosts`, `postDetails` or `postComments` |
| `urls` | array | – | Channel URLs/handles/IDs, or post URLs/IDs for the post modes |
| `maxPosts` | integer | `100` | Maximum posts per channel in `channelPosts` mode, or per run in the post modes (1–200). |
| `postTypes` | array | `[]` | `channelPosts` only: keep text/image/video/poll/quiz/playlist/shared posts |
| `keyword` | string | – | `channelPosts` only: keep posts whose text contains this phrase |
| `publishedAfter` | string | – | `channelPosts` only: keep posts published on or after this date |
| `publishedBefore` | string | – | `channelPosts` only: keep posts published on or before this date |
| `includeDetails` | boolean | `true` | `channelPosts` only: fetch exact date, likes, comment count and a 3-comment preview. `postDetails` always returns details. |
| `includeComments` | boolean | `false` | Include comment threads in `channelPosts` and `postDetails`; `postComments` always returns comments |
| `maxComments` | integer | `100` | Maximum top-level comments per post (1–1,000) |
| `includeReplies` | boolean | `false` | Include replies under comments |
| `maxRepliesPerComment` | integer | `10` | Maximum replies per comment (1–100) |
| `commentSort` | string | `top` | `top` or `newest` when comments are requested |
| `market` | string | `US` | Country used for YouTube's localized labels |
| `language` | string | `en` | Interface language for relative times and labels |

#### Example: recent posts from two channels

```json
{
  "mode": "channelPosts",
  "urls": ["https://www.youtube.com/@MrBeast", "@GoodMythicalMorning"],
  "maxPosts": 20
}
```

#### Example: polls and quizzes only

```json
{
  "mode": "channelPosts",
  "urls": ["@veritasium", "@watchmojo"],
  "postTypes": ["poll", "quiz"],
  "maxPosts": 50
}
```

#### Example: exact date range with comments

```json
{
  "mode": "channelPosts",
  "urls": ["@MrBeast"],
  "publishedAfter": "2026-08-01",
  "publishedBefore": "2026-10-01",
  "includeComments": true,
  "maxComments": 100,
  "commentSort": "newest"
}
```

#### Example: one post by URL, with replies

```json
{
  "mode": "postDetails",
  "urls": ["https://www.youtube.com/post/UgkxZusu9I1Z-VuU5PGZNA2gclHi8V9CJVZk"],
  "includeComments": true,
  "maxComments": 200,
  "includeReplies": true,
  "maxRepliesPerComment": 20
}
```

#### Example: comments as one row per comment

```json
{
  "mode": "postComments",
  "urls": ["UgkxZusu9I1Z-VuU5PGZNA2gclHi8V9CJVZk"],
  "maxComments": 500,
  "commentSort": "newest"
}
```

### Use cases

- **Creator agencies** — track announcements, product drops and audience polls across a roster of channels
- **Social listening** — export poll choices, post text and comment sentiment for brand monitoring
- **Competitive research** — compare engagement and posting cadence across creators
- **Content archiving** — save time-limited Community posts with images, links and comments
- **AI datasets** — collect clean creator text, quizzes and threaded comments
- **Community management** — monitor new comments on a post without opening YouTube

### FAQ

**What is a Community post?**
Any text update, image, image carousel, shared video, poll, quiz, playlist or repost a channel publishes to its Posts tab — the feed that sits beside Videos and Shorts.

**Do I need to log in or provide cookies?**
No. The actor reads the same public pages a logged-out visitor sees. Posts that a creator restricted to channel members are not visible without a membership, so they are not returned.

**Why does a channel stop at 200 posts?**
YouTube's Posts tab only serves the newest 200 posts. There is no public way to page further back. If you already have an older post URL or ID, the `postDetails` and `postComments` modes can still read it.

**Why are poll percentages missing?**
YouTube only reveals per-choice votes and percentages to signed-in viewers who voted in that poll. Logged out, the page carries the choices and a rounded total vote count, which the actor returns.

**Are like and comment counts exact?**
Yes when `includeDetails` is on: the actor reads YouTube's exact counters. Counts are a point-in-time snapshot and can change after the scrape. When details are off, only the display text such as `147K` is available. Reposts do not have their own like or comment counters.

**Can I get every comment on a post?**
Up to `maxComments` top-level comments. YouTube's featured-comment feed is finite; for deeper requests the actor continues with the newest-comment feed and removes duplicates. `includeReplies` adds reply threads.

**Why does a post have no comment count?**
The creator turned comments off. The record then carries `commentsDisabled: true` instead of inventing zero.

**Does the market or language field translate post text?**
No. It changes YouTube's own labels and relative times, never the creator's text.

**Can I filter by date, type or keyword?**
Yes, in `channelPosts` mode. `publishedAfter` and `publishedBefore` use the exact publish date, `postTypes` filters attachments, and `keyword` matches the post text case-insensitively. The post modes process the URLs/IDs you give them directly.

**Is this affiliated with YouTube?**
No. This is an independent third-party actor that reads public YouTube pages and is not operated by or affiliated with YouTube or Google.

# Actor input Schema

## `mode` (type: `string`):

Choose channel posts, one post per URL/ID, or comments from post URLs/IDs.

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

Channel URLs, @handles or channel IDs when mode=channelPosts. Post URLs or post IDs when mode=postDetails/postComments.

## `maxPosts` (type: `integer`):

Maximum posts per channel, or per run in the post modes. The run also accepts at most this many channel/post inputs. YouTube exposes at most 200 posts per channel.

## `postTypes` (type: `array`):

In channelPosts mode, only return these post types. Leave empty to include every type. The post modes return the post URLs/IDs you give them.

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

In channelPosts mode, only keep posts whose text contains this phrase. Case-insensitive. Leave empty for all posts.

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

In channelPosts mode, keep posts published on or after this date. Uses YouTube's exact publish date, so details are fetched when set.

## `publishedBefore` (type: `string`):

In channelPosts mode, keep posts published on or before this date. Uses YouTube's exact publish date, so details are fetched when set.

## `includeDetails` (type: `boolean`):

In channelPosts mode, fill the exact publish date, exact like count, comment count and a 3-comment preview. Adds one detail and one comment request per post. postDetails always returns details.

## `includeComments` (type: `boolean`):

Return comment threads on each post (up to Maximum comments) in channelPosts and postDetails modes. postComments always returns comments.

## `maxComments` (type: `integer`):

Maximum top-level comments to keep per post when comments are included. Replies are counted separately.

## `includeReplies` (type: `boolean`):

Also fetch replies under each comment when comments are included.

## `maxRepliesPerComment` (type: `integer`):

Maximum replies to keep per comment when replies are included.

## `commentSort` (type: `string`):

Show YouTube's featured comments first, or the newest comments first, when comments are returned.

## `market` (type: `string`):

Country used to render YouTube's localized labels and relative times.

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

Language used for YouTube's relative times and display labels. Post text is never translated.

## Actor input object example

```json
{
  "mode": "channelPosts",
  "urls": [
    "https://www.youtube.com/@MrBeast"
  ],
  "maxPosts": 3,
  "postTypes": [],
  "includeDetails": true,
  "includeComments": false,
  "maxComments": 100,
  "includeReplies": false,
  "maxRepliesPerComment": 10,
  "commentSort": "top",
  "market": "US",
  "language": "en"
}
```

# Actor output Schema

## `posts` (type: `string`):

Dataset containing community post rows, comment rows from postComments mode, and explanatory status rows.

# 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 = {
    "mode": "channelPosts",
    "urls": [
        "https://www.youtube.com/@MrBeast"
    ],
    "maxPosts": 3,
    "postTypes": [],
    "includeDetails": false,
    "includeComments": false,
    "includeReplies": false,
    "commentSort": "top",
    "market": "US",
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataspryva/youtube-community-tab-post-and-poll-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 = {
    "mode": "channelPosts",
    "urls": ["https://www.youtube.com/@MrBeast"],
    "maxPosts": 3,
    "postTypes": [],
    "includeDetails": False,
    "includeComments": False,
    "includeReplies": False,
    "commentSort": "top",
    "market": "US",
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("dataspryva/youtube-community-tab-post-and-poll-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 '{
  "mode": "channelPosts",
  "urls": [
    "https://www.youtube.com/@MrBeast"
  ],
  "maxPosts": 3,
  "postTypes": [],
  "includeDetails": false,
  "includeComments": false,
  "includeReplies": false,
  "commentSort": "top",
  "market": "US",
  "language": "en"
}' |
apify call dataspryva/youtube-community-tab-post-and-poll-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataspryva/youtube-community-tab-post-and-poll-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/TgWj38cfCgu54papJ/builds/YmiJOaB3acz5T3dIO/openapi.json
