# Reddit Scraper – Posts, Comment Threads & User History (`aster_data/reddit-mcp-actor`) Actor

Export archived Reddit posts, comment threads, scoped keyword matches and user history with standard keys, parent context, UTC dates and shared result limits. No Reddit credentials or proxy setup. Arctic Shift coverage may lag. $1 per 1,000 saved results.

- **URL**: https://apify.com/aster_data/reddit-mcp-actor.md
- **Developed by:** [Falak Fatma](https://apify.com/aster_data) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

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

## Reddit Scraper — Posts, Comment Threads & User History

Export archived Reddit posts, comment threads, scoped keyword matches and public user activity as JSON, CSV, Excel or other Apify dataset formats. No Reddit API key, login or proxy setup is required.

**The source is Arctic Shift, not a live Reddit session.** Recent records can lag, deleted material may be absent, and engagement/profile values describe archived snapshots. An exhausted query does not establish complete Reddit coverage.

Version 0.3 adds familiar input and output names used by `harshmaur/reddit-scraper`, with shared result caps, verified comment ancestry, field selection, provenance and interrupted-write recovery. These names ease migration; supported capabilities and differences are documented below.

### Price

**$1 per 1,000 saved results: $0.001 per row, plus a small memory-based start charge.** A post and three comments are four results ($0.004 in result charges). Requested community and user metadata rows count at the same rate. Parent records fetched only to enrich a comment do not create extra result rows.

Monetization is active. The `apify-actor-start` event costs $0.00005 per GB of allocated memory, with at least one event. At the default 512 MB, that is $0.00005 per run. Empty exports and dry runs can still incur the start charge. The Actor remains private until its owner requests publication.

Apify automatically charges the `apify-default-dataset-item` event; the Actor does not manually charge those rows again. Filtered candidates and duplicate candidates within a matching request are not stored. Separate runs or intentionally new requests can return the same records again.

`maxTotalItems` is a hard shared row ceiling. `maxTotalChargeUsd` adds a result ceiling rounded down at $0.001 per row: `$0.019` permits at most 19 results. A zero shared row or result-charge budget performs no source requests. Apify's platform spending limit is a separate run setting. Private owner development runs can incur platform usage. Consult Console for actual billing and the effective pricing record.

### Quick start

The Console's prefilled sample exports three known historical posts using direct ID lookups. It is also the input used for Apify's daily automated Store test. The sample has a three-row cap, three logical source requests, a 10-second HTTP timeout and one retry per request. If one record is unavailable, it continues to the other real records. Change the example URLs and limits for your own exports.

The sample is defined in [.actor/default_input.json](.actor/default_input.json). Its values are schema `prefill` entries, so they do not inject demonstration targets into API requests for your own subreddit, keyword or profile. The saved Actor example input uses the same sample. Empty API requests, including requests containing only unchanged schema defaults, resolve to this bounded sample and report `defaultSampleApplied: true`. Explicit targets, filters, custom controls and invalid inputs keep their usual behavior. Archive/provider outages can still prevent a non-empty result; successful tests cannot guarantee future uptime.

Export up to 20 archived posts from a known historical date:

```json
{
  "subredditUrls": ["Python"],
  "postedAfter": "2024-01-01",
  "postedBefore": "2024-01-01",
  "maxPostsCount": 20,
  "maxTotalItems": 20,
  "outputProfile": "compact"
}
```

Date-only upper bounds include the whole UTC day; this example ends at January 2, 00:00 UTC. Listings without an explicit lower bound scan the last 30 days. Availability still depends on the archive.

After running, open **Results** and export your preferred format. The output tab links to the JSON summary, HTML coverage report and discovery provenance.

#### A post and its archived thread

```json
{
  "startUrls": [{"url": "https://www.reddit.com/r/Python/comments/18vkgtu/"}],
  "crawlCommentsPerPost": true,
  "maxPostsCount": 1,
  "maxCommentsPerPost": 20,
  "maxTotalItems": 21,
  "includeParentData": true
}
```

Threads are chronological. Comments have joinable `postId` and `parentId` fields. `depth` and `rootCommentId` are populated only when ancestry is verified; gaps, cycles or lookup bounds yield `missingParent: true` and `depth: null`. Available replies can differ from the post's archived `commentsCount`.

A direct comment URL (`/r/community/comments/POST/title/COMMENT/`) saves that comment alone. Parent posts and ancestors can enrich it without becoming additional results. Direct URLs have no implicit 30-day lower bound; explicit date filters still apply. `maxPostsCount: 0` can suppress a direct post row while allowing its thread.

#### Scoped keyword matching

```json
{
  "searchTerms": ["python automation", "\"data pipeline\""],
  "withinCommunity": "Python",
  "postedAfter": "2024-01-01",
  "postedBefore": "2024-01-07",
  "searchPosts": true,
  "searchComments": true,
  "maxPostsCount": 10,
  "maxCommentsCount": 10,
  "maxTotalItems": 20
}
```

Every token in one search phrase must occur case-insensitively in the post title/body or comment body. Quoted phrases stay together. This is literal matching, without Reddit Boolean operators. Each term gets its own scoped search. `withinCommunity` or a subreddit/user target is required; global Reddit discovery is unavailable.

If upstream rejects scoped text filtering, the Actor scans the same target/date range and verifies matches locally within `maxRequests`. Coverage can be partial. Explicit URL/listing sources and keyword sources are additive and share a deduplicated allowance; a broad listing can consume it first. Use only `searchTerms` with `withinCommunity` for a pure keyword request.

#### User activity

```json
{
  "startUrls": ["https://www.reddit.com/user/spez/"],
  "postedAfter": "2024-01-01",
  "postedBefore": "2024-01-31",
  "commentedAfter": "2024-01-01",
  "commentedBefore": "2024-01-31",
  "includeUserComments": true,
  "maxPostsCount": 10,
  "maxCommentsCount": 10,
  "maxTotalItems": 20
}
```

`/user/NAME/comments/` restricts activity to comments; `/user/NAME/submitted/` restricts it to posts. General user targets include comment history by default. `includeUserProfiles` adds a separate archived user metadata row when available.

### Inputs

The [input schema](.actor/input_schema.json) defines Console controls. `startUrls` accepts strings or `{ "url": "…" }` objects with GET URLs. `subredditUrls` accepts names, `r/NAME`, or subreddit URLs. Short `redd.it` links, canonical posts/comments and chronological scoped search URLs are supported. Other hosts, credentials in URLs and unsupported listing paths fail validation.

| Input | Default | Meaning |
| --- | --- | --- |
| `startUrls`, `subredditUrls` | empty | Direct records, community listings or user activity; 100 entries each |
| `searchTerms`, `withinCommunity` | empty | Scoped literal keyword matching |
| `searchPosts` | `true` | Collect listing/search posts |
| `searchComments` | `false` | Collect comments independently from scopes |
| `crawlCommentsPerPost` | `false` | Collect threads for selected posts |
| `includeCommunity`, `includeUserProfiles` | `false` | Save available archived metadata rows |
| `includeUserComments` | `true` | Comment activity for general user targets |
| `postedAfter`, `postedBefore` | last 30 days / run start for listings | Post date bounds |
| `commentedAfter`, `commentedBefore` | last 30 days / run start for listings | Comment bounds; threads default to parent post creation |
| `searchSort` | `new` | Chronological `new` or `old`; threads always oldest first |
| `searchTime` | `all` | Optional `hour`, `day`, `week`, `month`, `year` lower bound without explicit dates |
| `includeNSFW` | `false` | Exclude posts explicitly marked `over_18`; unknown stays unknown |
| `onlyWithFlair` | `false` | Require a post flair |
| `minScore` | unset | Minimum archived score; missing scores fail this filter |
| `includeKeywords`, `excludeKeywords` | empty | Require every included phrase; reject any excluded phrase |
| `maxPostsCount` | `50` | Saved posts per source across resumptions |
| `maxCommentsCount` | `100` | Saved independent comments per source |
| `maxCommentsPerPost` | `100` | Saved comments per thread |
| `maxCommunitiesCount` | `2` | Request-wide community metadata ceiling |
| `maxTotalItems` | `100` | Shared ceiling across all record families |
| `maxTotalChargeUsd` | unset | Additional row ceiling at $0.001 per result |
| `maxRequests` | `200` | Logical source requests including context; HTTP retries add attempts |
| `includeParentData`, `maxParentDepth` | `true`, `20` | Cached, bounded comment context lookups |
| `outputProfile` | `standard` | `compact`, `standard`, `full` |
| `includeRawData` | profile-dependent | False for compact/standard; true for full unless overridden |
| `outputFields` | unset | Select known fields; identity and recovery provenance remain |
| `resumeFromState` | `true` | Resume a matching request in the same storage |
| `dryRun` | `false` | Validate/preview without source HTTP, dataset writes or checkpoint changes |
| `skipInvalidTargets` | `false` | Explicitly skip invalid targets with diagnostics |
| `continueOnError` | `false` | Continue other sources after errors; unresolved writes always stop |

Dates accept `YYYY-MM-DD`, ISO datetimes and relative periods such as `7 days`, `1 hour` or `1 week ago`. Naive datetimes use UTC. Relative dates and the default upper bound freeze when a request is created. `all` removes a lower bound. Relative months/years mean 30/365 days.

Zero disables the corresponding result family. Filters apply before stored-row caps. Sources run in input order, so the first source can consume a shared cap. `searchComments` and `crawlCommentsPerPost` are independent.

Advanced controls: `limit` (`1`–`100` or `auto`) sets archive page size, `windowDays` defaults to 1 (`0` scans the bounded range), `minWindowSeconds` to 60, `timeoutSeconds` to 30, `retries` to 3, `retrySleepSeconds` to 2 and `requestDelayMs` to 0. `maxPagesPerKind` adds a partial-scan ceiling. `verboseLog` enables diagnostics. `baseUrl` overrides the archive endpoint. Transient source timeouts/rate limits are retried with bounded backoff; oversized ranges split adaptively and grow again after successful empty scans. Saturated timestamp boundaries stop with preserved partial data instead of skipping unseen records.

### Output contract

`dataType` is `post`, `comment`, `community` or `user_profile`. Fields describe the applicable family; missing source-dependent values remain `null`. Standard output uses familiar Reddit keys plus explicit recovery/provenance fields.

| Group | Main keys |
| --- | --- |
| Identity | `dataType`, `id`, `parsedId`, `recordKey`, `url` |
| Content | `title`, `body`, `bodyHtml`, `createdAt`, `edited`, `editedAt` |
| Author/community | `authorName`, `authorId`, `parsedAuthorId`, `communityName`, `communityId`, `parsedCommunityName` |
| Engagement | `score`, `upVotes`, `commentsCount`, `upvoteRatio`, `scoreHidden`, `totalAwardsReceived` |
| Post state | `over18`, `isSelf`, `isVideo`, `isGallery`, `spoiler`, `locked`, `archived`, `flair`, `removalStatus` |
| Links/media | `postUrl`, `contentUrl`, `domain`, `images`, `videoUrl`, `thumbnail`, `mediaAssets`, `galleryImages` |
| Relationships | `postId`, `parsedPostId`, `postTitle`, `parentId`, `parsedParentId`, `parentKind`, `rootCommentId`, `depth`, `missingParent`, `isSubmitter` |
| Provenance | `source`, `sourceRetrievedAt`, `crawledAt`, `sourceTarget`, `searchTerm` |
| Metadata | Archived names, descriptions, creation times, available flags, karma/member counts and archive activity fields |

`id` is a Reddit fullname (`t3_POST`, `t1_COMMENT`, `t2_USER`, `t5_COMMUNITY`). `parsedId` omits the prefix. `postId` and `parentId` also use fullnames for joins. Unknown IDs remain null; `recordKey` uses a stable name/hash fallback instead of inventing a Reddit ID.

`communityName` includes `r/`; `parsedCommunityName` is bare. `url`/`postUrl` are Reddit permalinks; `contentUrl` is an external destination. Media normalization preserves gallery order, decodes HTML entities and omits unsafe asset URLs.

`upVotes` is a compatibility alias for archived **net score**, not positive vote count. `sourceRetrievedAt` is the upstream observation time when available; `crawledAt` is when this Actor prepared the row. Age-adjusted metrics use source observation time and remain null when unknown. `removalStatus: "unknown"` does not assert a post is active. Archived metadata does not establish current community/profile state.

`compact` retains main text, IDs, relationships and provenance. `standard` adds normalized details. `full` also retains `rawData` by default. `outputFields` reduces any profile; identity/source fields, `sourceTarget` and comment `missingParent` remain for recovery. Selected fields for a different record family can be absent. Raw payloads increase export size.

The complete dictionary is in the [dataset schema](.actor/dataset_schema.json). Console offers `overview`, `threads`, `provenance` and `legacy` views. The schema covers both output contracts; an individual row does not contain both.

### Summaries, coverage and recovery

The default key-value store contains:

- `OUTPUT` and `RUN-SUMMARY`: JSON status, unique/new/recovered row counts, record families, filter/duplicate counts, unresolved ancestry, request budget and per-scan stop reasons.
- `RUN-MAP.html`: self-contained coverage report.
- `PROVENANCE`: `recordKey` → discovered source labels for this request. Thread rows identify their parent post URL.
- `REQUEST`, `STATE-*`, `PENDING-*`: internal request/checkpoint/write journals. Keep them with the original dataset for recovery.

Statuses are `completed`, `empty`, `partial`, `dry_run` or `failed`. A successful Actor process can have a **partial** export because a cap was reached. Inspect `coverageComplete`, `truncated`, `scans[].stoppedReason` and `pendingWrite`. Stops at item/page/request caps do not establish complete traversal. Context failures preserve rows with nulls and warnings.

`itemsTotal` is the unique saved count for this request; `totalRows` is newly saved this invocation. An intentionally reused dataset can also contain earlier requests. `estimatedResultCostUsd` estimates request result rows; Console reports actual charges.

Resuming a matching request in the **same key-value store and dataset** freezes dates, reconciles uncertain appends, replays unfinished pages and skips saved records. Raising row/request caps can continue it. Changed targets, dates, filters or output shape, or `resumeFromState: false`, creates a new request that can append records seen previously.

Only one writer may use this storage. Unexpected dataset changes or unresolved writes stop the run. Recover with the original input/storage before switching requests. New scheduled runs normally use fresh storage and do not share deduplication. Use explicit dates and downstream `recordKey` deduplication for recurring exports.

### Migration and supported scope

Use `startUrls`/`subredditUrls` and version 2 for new integrations. Legacy `targets` alone keeps version 1; explicitly set `outputVersion: 1` to pin an existing integration. Version 2 also accepts `targets`, `datasets`, `startDate`, `endDate` and `maxItemsPerKind` as aliases. Standard cap/date fields take precedence; `datasets` explicitly selects the legacy record families when present. Recover old pending writes before changing contracts; prefer fresh storage for upgrading.

| Original key | Standard key |
| --- | --- |
| `kind` (`post` / `comment`) | `dataType` (`post` / `comment`) |
| `redditId` | `parsedId` and fullname `id` |
| `description` | `body` |
| `author` | `authorName` |
| `subreddit` | `parsedCommunityName` |
| `commentCount` | `commentsCount` |
| `retrievedAt` | `crawledAt`; upstream capture is separate `sourceRetrievedAt` |

Live `hot`/`top`/`relevance`, global keyword discovery, community discovery, private/login-only data, current profile guarantees, AI sentiment/intent labels and external MCP delivery are unsupported. Enabling placeholders such as `aiAnalysis`, `customLabels`, `searchCommunities`, intent flags or `mcpConnector` fails before result writes. Unknown input keys also fail. Version 1 retains its original output and summary format.

### API and development

Use Console or the authenticated Actor API. Store your Apify account token in an environment variable, not the Actor input:

```bash
curl --request POST \
  --header "Authorization: Bearer $APIFY_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{"subredditUrls":["Python"],"postedAfter":"2024-01-01","postedBefore":"2024-01-01","maxTotalItems":5}' \
  'https://api.apify.com/v2/acts/aster_data~reddit-mcp-actor/runs'
```

The response provides run and storage IDs. Poll the run and retrieve dataset items or summary artifacts through the authenticated API. The Actor stays private until its owner chooses to publish it.

Python 3.12+ is supported. Runtime and development dependencies are separate:

```bash
python3 -m venv .venv
.venv/bin/pip install -r requirements-dev.txt
.venv/bin/python scripts/generate_schemas.py
.venv/bin/python -m coverage run --branch --source=src -m unittest discover -s tests -q
.venv/bin/python -m coverage report -m
npm exec --package apify-cli@1.10.0 -- apify validate-schema
```

Tests cover input rejection, dates, output types, media, parent chains, filtering, deduplication, shared budgets, both pagination directions, timestamp saturation, adaptive splitting, HTTP failures, partial/ambiguous appends and restart recovery with real local SDK storage. Generated cases vary record distributions and malformed JSON fields. Cloud checks use bounded historical inputs and validate actual output. See the [release test report](docs/releases/0.3.4/README.md) and [351-result scale validation](docs/tests/scale-2026-10-22/README.md). No finite suite guarantees every upstream condition.

Deploy with `apify push`. Apply [.actor/pricing.json](.actor/pricing.json) separately through the Actor API and read it back. Ordinary pushes must preserve private visibility. The dated [competitor research](docs/research/reddit-actors-2026-10-21/README.md) informed this release; field counts do not establish superior completeness or speed.

# Actor input Schema

## `startUrls` (type: `array`):

Post, comment, subreddit or public-user URLs. Enter URL strings or objects such as {"url":"https://reddit.com/r/Python/"}. Inputs are additive and share maxTotalItems.

## `subredditUrls` (type: `array`):

Names or subreddit URLs, for example Python or r/Python. Post URLs belong in startUrls.

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

One scoped search per phrase. All tokens must match; quoted phrases remain together. Requires withinCommunity or a subreddit/user target. No global ranked discovery.

## `withinCommunity` (type: `string`):

One subreddit name or URL. Required for a search with no other scoped target.

## `searchPosts` (type: `boolean`):

Collect posts from the selected listing/search sources.

## `searchComments` (type: `boolean`):

Collect comments independently from selected subreddit/user scopes. Different from fetching each post's thread.

## `crawlCommentsPerPost` (type: `boolean`):

Collect available archived comments belonging to selected posts. Missing or unarchived replies may exist.

## `includeCommunity` (type: `boolean`):

Save an archived community row for each known subreddit. Metadata may be stale or incomplete.

## `includeUserProfiles` (type: `boolean`):

Save an archived user row for known user targets. This is not a current Reddit profile lookup.

## `includeUserComments` (type: `boolean`):

User targets collect authored comments as well as posts. User /comments and /submitted URLs restrict the activity kind.

## `postedAfter` (type: `string`):

Inclusive UTC lower bound: date, ISO datetime, or 7 days / 1 hour. Listings default to the last 30 days; direct URLs have no implicit lower bound. all removes it.

## `postedBefore` (type: `string`):

Exclusive upper bound; a date-only value includes that entire UTC day. Defaults to the frozen run-start time.

## `commentedAfter` (type: `string`):

Independent inclusive lower bound for comments. Same formats as postedAfter. Thread scans default to their parent post's creation.

## `commentedBefore` (type: `string`):

Independent upper bound for comments; a date-only value includes that UTC day.

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

new means newest available archived records first; old means oldest first. Live hot/top/relevance rankings are unavailable.

## `searchTime` (type: `string`):

Relative to frozen run start, when no explicit lower bound is supplied. Does not override an explicit date.

## `includeNSFW` (type: `boolean`):

False excludes posts explicitly marked over_18. Missing flags remain unknown; source fields are not invented.

## `onlyWithFlair` (type: `boolean`):

Drop posts with no link flair before applying stored-row caps.

## `minScore` (type: `integer`):

Drop rows below this score or with no score. The value is an archive snapshot, not current engagement.

## `includeKeywords` (type: `array`):

Each phrase must occur in the post title/body or comment body. Applied before storing and charging results.

## `excludeKeywords` (type: `array`):

Drop a row when any phrase occurs in its text. Matching is case-insensitive.

## `maxPostsCount` (type: `integer`):

Stored-post ceiling per source across resumptions. Zero disables post rows; direct post URLs can still provide comment context.

## `maxCommentsCount` (type: `integer`):

Stored-comment ceiling for comment search, user activity, or a direct comment. Does not set each thread's allowance.

## `maxCommentsPerPost` (type: `integer`):

Maximum archived comments stored for each selected post across resumptions.

## `maxCommunitiesCount` (type: `integer`):

Request-wide cap for explicitly requested metadata rows. Zero disables community rows.

## `maxTotalItems` (type: `integer`):

Hard shared cap across all result types and scopes, including rows already saved by this request. Default 100.

## `maxTotalChargeUsd` (type: `number`):

Additional row cap at $0.001 per row, rounded down. Zero permits no result rows. Platform run limits and owner development costs are separate.

## `maxRequests` (type: `integer`):

Maximum logical source requests, including optional context lookups. HTTP retries can add attempts. Reaching this produces an explicit partial summary.

## `outputProfile` (type: `string`):

standard includes normalized fields; compact reduces response size; full includes the archive payload unless includeRawData is explicitly false.

## `outputFields` (type: `array`):

Optional field projection. Identity, source, sourceTarget, and comment ancestry status remain available for safe recovery. Unknown fields fail validation.

## `includeRawData` (type: `boolean`):

Optional override. Defaults false for standard/compact and true for full. Legacy version 1 defaults true.

## `includeParentData` (type: `boolean`):

Use bounded, cached lookups to add parent post text and comment ancestry. Context lookups do not create extra result rows.

## `maxParentDepth` (type: `integer`):

Bound ancestry resolution. Unknown, cyclic or incomplete chains have null depth and missingParent true.

## `resumeFromState` (type: `boolean`):

Continue matching checkpoints in the same storage. Recurring runs normally have fresh storage; they do not share deduplication automatically.

## `dryRun` (type: `boolean`):

Validate inputs and resolve dates without any source HTTP requests, dataset writes, or checkpoint changes.

## `skipInvalidTargets` (type: `boolean`):

Opt in to skipping invalid target entries with summary diagnostics. Invalid dates or filter values still fail.

## `continueOnError` (type: `boolean`):

Continue other sources after an HTTP/source failure. Unresolved dataset writes always stop the run.

## `verboseLog` (type: `boolean`):

Enable additional diagnostic logging.

## `deduplicate` (type: `boolean`):

Compatibility flag. Deduplication is always enabled; false is rejected.

## `outputVersion` (type: `integer`):

2 uses standard keys. Explicitly set 1 with legacy targets to retain the original output contract.

## `limit` (type: `string`):

1–100 or auto. This controls source requests, not output volume. Use item caps for small exports.

## `windowDays` (type: `number`):

Maximum scan window in days; 0 requests the full bounded range. Threads use their full range. Oversized-range responses split adaptively.

## `minWindowSeconds` (type: `integer`):

Smallest retry interval after oversized-range responses.

## `timeoutSeconds` (type: `number`):

Timeout for each HTTP attempt in seconds.

## `retries` (type: `integer`):

Retries after transient failures. Oversized-range errors are split without retrying the same range.

## `retrySleepSeconds` (type: `number`):

Base retry delay in seconds; source Retry-After is bounded.

## `requestDelayMs` (type: `integer`):

Delay after a successfully handled page, in milliseconds.

## `maxPagesPerKind` (type: `integer`):

Optional non-empty page ceiling. Reaching it is reported as partial coverage.

## `baseUrl` (type: `string`):

Advanced HTTP(S) archive override without credentials, query, or fragment.

## `datasets` (type: `array`):

Legacy input; use the version 2 fields for new integrations. Select which Reddit object types to download.

## `endDate` (type: `string`):

Legacy input; use the version 2 fields for new integrations. UTC upper bound. YYYY-MM-DD is exclusive of the next UTC day. Use now for the current time.

## `maxItemsPerKind` (type: `integer`):

Legacy input; use the version 2 fields for new integrations. Optional cap for newly pushed rows per selected dataset and target.

## `skipMetadata` (type: `boolean`):

Legacy input; use the version 2 fields for new integrations. Skip the subreddit/user metadata request. Provide startDate for large ranges when enabled.

## `startDate` (type: `string`):

Legacy input; use the version 2 fields for new integrations. UTC inclusive lower bound. Supports YYYY-MM-DD, ISO datetime, epoch seconds/milliseconds, N days ago, none, or all. Default: 30 days ago.

## `targets` (type: `array`):

Legacy input; use the version 2 fields for new integrations. Subreddit or user targets: r/Python, u/spez, or a full Reddit subreddit/user profile URL. Post, thread and search URLs are not supported.

## `aiAnalysis` (type: `boolean`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `competitor` (type: `boolean`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `customLabels` (type: `object`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `featureRequest` (type: `boolean`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `hasPain` (type: `boolean`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `isOwner` (type: `boolean`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `isVendor` (type: `boolean`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `mcpConnector` (type: `string`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `mcpServerToken` (type: `string`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `mcpServerUrl` (type: `string`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `mentionsPrice` (type: `boolean`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `painPoint` (type: `boolean`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `searchCommunities` (type: `boolean`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `wantsHelp` (type: `boolean`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## `willingToPay` (type: `boolean`):

Compatibility placeholder only. Enabling this unsupported external analysis/delivery/discovery option fails before result writes.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.reddit.com/r/Python/comments/18vkgtu/"
    },
    {
      "url": "https://www.reddit.com/r/Python/comments/18wacbi/"
    },
    {
      "url": "https://www.reddit.com/r/MachineLearning/comments/1916pu3/"
    }
  ],
  "searchPosts": true,
  "searchComments": false,
  "crawlCommentsPerPost": false,
  "includeCommunity": false,
  "includeUserProfiles": false,
  "includeUserComments": true,
  "searchSort": "new",
  "searchTime": "all",
  "includeNSFW": false,
  "onlyWithFlair": false,
  "maxPostsCount": 1,
  "maxCommentsCount": 100,
  "maxCommentsPerPost": 100,
  "maxCommunitiesCount": 2,
  "maxTotalItems": 3,
  "maxRequests": 3,
  "outputProfile": "standard",
  "includeParentData": true,
  "maxParentDepth": 20,
  "resumeFromState": true,
  "dryRun": false,
  "skipInvalidTargets": false,
  "continueOnError": true,
  "verboseLog": false,
  "outputVersion": 2,
  "limit": "100",
  "windowDays": 1,
  "minWindowSeconds": 60,
  "timeoutSeconds": 10,
  "retries": 1,
  "retrySleepSeconds": 1,
  "requestDelayMs": 0,
  "baseUrl": "https://arctic-shift.photon-reddit.com/api"
}
```

# Actor output Schema

## `results` (type: `string`):

No description

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

No description

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

No description

## `provenance` (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 = {
    "startUrls": [
        {
            "url": "https://www.reddit.com/r/Python/comments/18vkgtu/"
        },
        {
            "url": "https://www.reddit.com/r/Python/comments/18wacbi/"
        },
        {
            "url": "https://www.reddit.com/r/MachineLearning/comments/1916pu3/"
        }
    ],
    "maxPostsCount": 1,
    "maxTotalItems": 3,
    "maxRequests": 3,
    "continueOnError": true,
    "outputVersion": 2,
    "timeoutSeconds": 10,
    "retries": 1,
    "retrySleepSeconds": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("aster_data/reddit-mcp-actor").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 = {
    "startUrls": [
        { "url": "https://www.reddit.com/r/Python/comments/18vkgtu/" },
        { "url": "https://www.reddit.com/r/Python/comments/18wacbi/" },
        { "url": "https://www.reddit.com/r/MachineLearning/comments/1916pu3/" },
    ],
    "maxPostsCount": 1,
    "maxTotalItems": 3,
    "maxRequests": 3,
    "continueOnError": True,
    "outputVersion": 2,
    "timeoutSeconds": 10,
    "retries": 1,
    "retrySleepSeconds": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("aster_data/reddit-mcp-actor").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 '{
  "startUrls": [
    {
      "url": "https://www.reddit.com/r/Python/comments/18vkgtu/"
    },
    {
      "url": "https://www.reddit.com/r/Python/comments/18wacbi/"
    },
    {
      "url": "https://www.reddit.com/r/MachineLearning/comments/1916pu3/"
    }
  ],
  "maxPostsCount": 1,
  "maxTotalItems": 3,
  "maxRequests": 3,
  "continueOnError": true,
  "outputVersion": 2,
  "timeoutSeconds": 10,
  "retries": 1,
  "retrySleepSeconds": 1
}' |
apify call aster_data/reddit-mcp-actor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,aster_data/reddit-mcp-actor"
        }
    }
}
```

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/LvdmpQiS9qTxu1bfx/builds/8HqHbMid9p4RQIEPC/openapi.json
