# Reddit Scraper — Posts, Comments, Search, Subreddit Monitoring (`moxlade/reddit-scraper`) Actor

Subreddit listings, keyword search and full comment trees, no login and no proxy to configure. Posts with full text, score, flair and media; comments with depth and parent. Schedule it with onlyNew to get just what appeared since the last run. Pay per row, no start fee.

- **URL**: https://apify.com/moxlade/reddit-scraper.md
- **Developed by:** [Moxlade](https://apify.com/moxlade) (community)
- **Categories:** Social media, News
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 posts

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

## Reddit Scraper — Posts, Comments, Search, Subreddit Monitoring

**Subreddit listings, keyword search and full comment trees — no Reddit login, no proxy to set up, no start fee.** Give it subreddits, search queries or post URLs and get posts with their full text, score, upvote ratio, flair and media, and comments with author, score, depth and parent. Turn on `onlyNew` and schedule it: each run returns only what appeared since the last one, and a run with nothing new costs nothing. Pay per delivered row — $2.00 per 1,000 posts, $1.00 per 1,000 comments.

### What you get

- **Three ways in, one row shape.** `subreddits` walks a listing by `new`, `hot`, `top` (with a time range) or `rising`; `searches` runs Reddit's own post search, sitewide or inside each subreddit you name; `postUrls` fetches specific posts. Every row is the same 27 typed fields, `kind` = `post` or `comment`, `found_by` says which input produced it.
- **Full text on every post, not a preview.** Listing posts carry the complete body as Reddit renders it (`body_text` with paragraph breaks, `body_html` with links), the score, upvote ratio, comment count, flair, type, media URLs, language, stickied/locked flags. Search hits are filled with author and body (`fetchBodies`, on by default).
- **Comment trees with structure.** `includeComments` delivers each post's comments right after it — `depth`, `parent_id`, `post_id`, author, score, permalink — in Reddit's `Best`/`Top`/`New`/… order, deep branches expanded up to `maxCommentsPerPost`.
- **Monitoring that remembers.** `onlyNew` keeps the ids it delivered in a named store and, on a chronological walk, the newest post it delivered per source; the next run stops at that point. Schedule a task and each run is the delta — the same lever as `postedSince` (`12h`, `7d`, `2w`, a date) for a one-off window.
- **Nothing to configure, nothing to babysit.** No cookies, no account, no proxy field. Reddit is read from a maintained residential exit that rotates on any wall and waits out the rate limit; a page that fails is retried before the run is failed, and the failure reason is in the status message.
- **Measured, not promised.** The acceptance suite runs the deployed build before every release. On the release runs: 25 listing rows with score, ratio, counts, type, flags and language on 25 of 25; 20 search rows with author and body on 20 of 20; a thread of 40 comments with a resolved parent on 22 of 22 nested comments; the second monitoring run at 0 rows and $0.00.

### Who it's for

- **Community and brand monitoring** — watch the subreddits and keywords that matter, on a schedule, and get only the new posts — with the text, not a link to click.
- **Research and content teams** — pull a subreddit's top posts of the month with their comment trees, or every post matching a query since a date, into one typed dataset.
- **Product and lead-gen builders** — a stable id (`id`), `permalink`, `created_utc` and `found_by` on every row, so deduplication, joins and incremental pulls are one line each.
- **Data pipelines and AI agents** — one call, JSON rows with full text and structure, no browser and no login to keep alive.

### Quick start

**Newest posts in a subreddit**

```json
{
  "subreddits": [
    "Upwork"
  ],
  "sort": "new",
  "maxItems": 50
}
```

**Top posts of the month with their comments**

```json
{
  "subreddits": [
    "ClaudeCode"
  ],
  "sort": "top",
  "time": "month",
  "includeComments": true,
  "maxCommentsPerPost": 50,
  "maxItems": 25
}
```

**Search a topic across Reddit since a date**

```json
{
  "searches": [
    "claude code"
  ],
  "searchSort": "new",
  "postedSince": "7d",
  "maxItems": 100
}
```

**Search inside chosen subreddits**

```json
{
  "subreddits": [
    "ClaudeCode",
    "ChatGPTCoding"
  ],
  "searches": [
    "hooks",
    "mcp server"
  ],
  "maxItems": 100
}
```

**Specific posts with every comment**

```json
{
  "postUrls": [
    "https://www.reddit.com/r/Upwork/comments/1wd745i/here_are_my_tips_for_upwork_newcomers/"
  ],
  "includeComments": true,
  "maxCommentsPerPost": 500
}
```

**Monitor: only what is new since the last run**

```json
{
  "subreddits": [
    "Upwork",
    "freelance"
  ],
  "sort": "new",
  "onlyNew": true,
  "maxItems": 200
}
```

### Output

One row per post or comment (`kind` says which):

| field | meaning |
|---|---|
| `kind` | `post` or `comment`. |
| `id` | Reddit's own id: `t3_…` for a post, `t1_…` for a comment. Stable; deduplicate and join on it. |
| `subreddit` | Subreddit name without the `r/`. |
| `title` | Post title. Null on comment rows. |
| `author` | Username without the `u/`. Null when the account is deleted. |
| `created_utc` | When it was posted, ISO 8601 UTC. |
| `score` | Net upvotes as Reddit showed them at fetch time. Null on a post reached by URL alone — Reddit's post page carries no score for a visitor; a post reached through a subreddit listing or a search has it. |
| `upvote_ratio` | Share of upvotes, 0–1. Subreddit listings only. |
| `comment_count` | Comments on the post as Reddit counts them (a comment row carries the count of its post). |
| `post_type` | `text`, `image`, `gallery`, `video`, `multi_media`, `crosspost`, `link` or `poll`. Subreddit listings only. |
| `flair` | The post's flair text, when it has one. |
| `url` | What the post links to: the external URL, the media, or the crossposted post. For a text post this is its own permalink. |
| `domain` | Domain of `url` as Reddit labels it (`self.<sub>` for text posts, `i.redd.it`, `youtube.com`, …). |
| `permalink` | The post's or comment's own URL on reddit.com. |
| `body_text` | Full text of the post or comment, paragraphs separated by blank lines. Empty for a link post. |
| `body_html` | The same body as Reddit's rendered HTML, links kept. |
| `media` | Media URLs the post carries (images, galleries, video). |
| `nsfw` | Marked NSFW. Known on search hits; null where Reddit did not say. |
| `stickied` | Pinned by the moderators. Subreddit listings only. |
| `locked` | Comments locked. Subreddit listings only. |
| `language` | Reddit's language tag for the post (`en`, `de`, …). Subreddit listings only. |
| `award_count` | Awards on the post. Subreddit listings only. |
| `post_id` | Comment rows: the `t3_…` id of the post the comment belongs to. |
| `parent_id` | Comment rows: the id of the parent comment (`t1_…`), or null for a top-level comment. |
| `depth` | Comment rows: 0 for a top-level comment, 1 for a reply to it, and so on. |
| `found_by` | How the row was reached: `r/<sub>/<sort>` for a subreddit listing, `search:<query>` (with `@r/<sub>` when scoped), `url` for a post given by URL, and `comments:<post id>` for a comment. |
| `fetched_at` | When this row was read from Reddit, ISO 8601 UTC. |

Example record:

```json
{
  "kind": "post",
  "id": "t3_1wd745i",
  "subreddit": "Upwork",
  "title": "Here are my tips for Upwork newcomers as a top Freelancer",
  "author": "Pierre_Zarokian",
  "created_utc": "2026-09-11T05:27:33.222000+00:00",
  "score": 47,
  "upvote_ratio": 0.7582417582417582,
  "comment_count": 66,
  "post_type": "text",
  "flair": null,
  "url": "https://www.reddit.com/r/Upwork/comments/1wd745i/here_are_my_tips_for_upwork_newcomers_as_a_top/",
  "domain": "self.Upwork",
  "permalink": "https://www.reddit.com/r/Upwork/comments/1wd745i/here_are_my_tips_for_upwork_newcomers_as_a_top/",
  "body_text": "My stats: 5 years, $500K+ earned, ~900 jobs completed.\n\nMy #1 tip: Find an uncrowded niche. My core skill set is digital marketing and SEO, but the mainstream lanes such as SEO, Google Ads, social media marketing are too saturated. Instead, I built my practice around Online Reputation Management, PR, and Wikipedia page creation. Wikipedia work was a strong earner for years until Upwork restricted it about a year ago. Since then, I've shifted mainly to ORM and PR, and I've started picking up AEO (Answer Engine Optimization) jobs too — it's far less competitive than SEO, and I've already landed 2 AEO contracts in the past few months.\n\nAdditional tips:\n\nMove fast. Try to be among the first 10–15 applicants on any job post, ideally applying within 15 minutes of it going live. Earlier bids win more often.\n\nSkip overcrowded listings. Don't bother applying once a job already has 20–50 proposals — unless you're confident you're a top-tier fit and the budget justifies it.\n\nBid for visibility. Aim to be the #1 bidder when you can, but set yourself a spending cap (say, 20–30 connects) so you don't overspend chasing hyper-competitive listings.\n\nDon't chase underpriced jobs hoping to negotiate up. Check the client's hiring history and average hourly rate paid. If they've hired 20+ freelancers averaging $10/hour, walk away unless that rate works for you. Personally, I won't bid below $75/hour.\n\nKeyword-optimize your profile. Your headline and overview should reflect the terms clients actually search for.\n\nTarget jobs with your keywords in the title. If a client wants to hire you under a vague or irrelevant job title, ask them to repost with a more specific, keyword-aligned title before accepting.\n\nAlways secure reviews. If a client doesn't leave one after project completion, follow up more than once to ask.\n\nGet direct contact info. Once hired, ask for the client's phone number and email, which will be useful if they go unresponsive, and handy later when requesting a review.\n\nStrengthen your proposals with proof. Attach case studies, testimonials, and a client list (especially if it includes recognizable brands).\n\nFeature your reviews. Include 4 strong job reviews at the bottom of every proposal.\n\nPersonalize every application. Even reused templates should open with a line specific to that client's stated needs, so it doesn't read as copy-paste.\n\nProject confidence. Don't undersell your experience. Use phrases like \"I'm the best candidate for this, look no further.\"\n\nUnderprice early to build your review base. In your first few months, take lower-paying jobs to get hired more often and rack up reviews. Once you hit 10–20 reviews, gradually raise your rates.\n\nApply to small unrelated gigs to increase your reviews. Take on $5–$50 jobs in unrelated categories (survey/review-type gigs, for instance) purely to build your review history, even though some of these may be against Upwork's policies.\n\nGood luck and reach out if you have any questions.",
  "body_html": "<p>\n      <strong>My stats:</strong> 5 years, $500K+ earned, ~900 jobs completed.\n    </p><p>\n      <strong>My #1 tip: Find an uncrowded niche.</strong> My core skill set is digital marketing and SEO, but the mainstream lanes such as SEO, Google Ads, social media marketing are too saturated. Instead, I built my practice around Online Reputation Management, PR, and Wikipedia page creation. Wikipedia work was a strong earner for years until Upwork restricted it about a year ago. Since then, I've shifted mainly to ORM and PR, and I've started picking up AEO (Answer Engine Optimization) jobs too — it's far less competitive than SEO, and I've already landed 2 AEO contracts in the past few months.\n    </p><p>\n      <strong>Additional tips:</strong>\n    </p><ul>\n        <li>\n      <p>\n      <strong>Move fast.</strong> Try to be among the first 10–15 applicants on any job post, ideally applying within 15 minutes of it going live. Earlier bids win more often.\n    </p>\n    </li><li>\n      <p>\n      <strong>Skip overcrowded listings.</strong> Don't bother applying once a job already has 20–50 proposals — unless you're confident you're a top-tier fit and the budget justifies it.\n    </p>\n    </li><li>\n      <p>\n      <strong>Bid for visibility.</strong> Aim to be the #1 bidder when you can, but set yourself a spending cap (say, 20–30 connects) so you don't overspend chasing hyper-competitive listings.\n    </p>\n    </li><li>\n      <p>\n      <strong>Don't chase underpriced jobs hoping to negotiate up.</strong> Check the client's hiring history and average hourly rate paid. If they've hired 20+ freelancers averaging $10/hour, walk away unless that rate works for you. Personally, I won't bid below $75/hour.\n    </p>\n    </li><li>\n      <p>\n      <strong>Keyword-optimize your profile.</strong> Your headline and overview should reflect the terms clients actually search for.\n    </p>\n    </li><li>\n      <p>\n      <strong>Target jobs with your keywords in the title.</strong> If a client wants to hire you under a vague or irrelevant job title, ask them to repost with a more specific, keyword-aligned title before accepting.\n    </p>\n    </li><li>\n      <p>\n      <strong>Always secure reviews.</strong> If a client doesn't leave one after project completion, follow up more than once to ask.\n    </p>\n    </li><li>\n      <p>\n      <strong>Get direct contact info.</strong> Once hired, ask for the client's phone number and email, which will be useful if they go unresponsive, and handy later when requesting a review.\n    </p>\n    </li><li>\n      <p>\n      <strong>Strengthen your proposals with proof.</strong> Attach case studies, testimonials, and a client list (especially if it includes recognizable brands).\n    </p>\n    </li><li>\n      <p>\n      <strong>Feature your reviews.</strong> Include 4 strong job reviews at the bottom of every proposal.\n    </p>\n    </li><li>\n      <p>\n      <strong>Personalize every application.</strong> Even reused templates should open with a line specific to that client's stated needs, so it doesn't read as copy-paste.\n    </p>\n    </li><li>\n      <p>\n      <strong>Project confidence.</strong> Don't undersell your experience. Use phrases like \"I'm the best candidate for this, look no further.\"\n    </p>\n    </li><li>\n      <p>\n      <strong>Underprice early to build your review base.</strong> In your first few months, take lower-paying jobs to get hired more often and rack up reviews. Once you hit 10–20 reviews, gradually raise your rates.\n    </p>\n    </li><li>\n      <p>\n      <strong>Apply to small unrelated gigs to increase your reviews.</strong> Take on $5–$50 jobs in unrelated categories (survey/review-type gigs, for instance) purely to build your review history, even though some of these may be against Upwork's policies.\n    </p>\n    </li>\n      </ul><p>\n      Good luck and reach out if you have any questions.\n    </p>",
  "media": [],
  "nsfw": false,
  "stickied": false,
  "locked": false,
  "language": "en",
  "award_count": 0,
  "post_id": null,
  "parent_id": null,
  "depth": null,
  "found_by": "r/Upwork/new",
  "fetched_at": "2026-09-12T21:29:45Z"
}
```

### Pricing

**Pay per delivered row, nothing else.** `post` — one post row, from a listing, a search or a URL — **$2.00 per 1,000**. `comment` — one comment row (`includeComments`) — **$1.00 per 1,000**. No start fee, no minimum, and a run that returns nothing costs nothing: on the acceptance runs the charged event count equals the row count on every run, and the zero-row run charged $0.00. A row is charged only after it is in your dataset, so `maxItems` and `maxCommentsPerPost` together are your spending cap.

### Usage patterns

- **List a subreddit** — Set `subreddits` and a `sort`. `new` is chronological — pair it with `postedSince` for a window or `onlyNew` for a schedule. `top` with `time` gives the period's best. `maxPostsPerSource` says how far down each listing to look (Reddit itself stops at about 1,000). Ready-made: [Newest posts in a subreddit](https://apify.com/moxlade/reddit-scraper/examples/newest-posts-in-a-subreddit) and [Top posts of the month, with their comments](https://apify.com/moxlade/reddit-scraper/examples/top-posts-of-the-month-with-comments).
- **Search for posts** — Set `searches`; each query runs across Reddit, or inside each of `subreddits` when both are given. `searchSort` is Reddit's own ordering (`new`, `relevance`, `hot`, `top`, `comments`). Hits come with author and full text unless you turn `fetchBodies` off to save the extra request per post. Ready-made: [Search Reddit for a topic, last 7 days](https://apify.com/moxlade/reddit-scraper/examples/search-reddit-since-a-date).
- **Fetch posts by URL, with their comments** — Paste post URLs or ids into `postUrls`, turn on `includeComments`, set `maxCommentsPerPost` and `commentSort`. Comments follow their post in the dataset, each with `depth` and `parent_id`. A post reached by URL alone carries no score (Reddit's post page shows a visitor none); posts reached through a listing or a search do.
- **Monitor on a schedule** — Turn on `onlyNew`, save the run as a task, add a schedule. The first run seeds the memory; every later run delivers only what appeared since, or nothing at all — and nothing is charged for nothing. Name the memory with `stateStoreName` to share it between tasks or to reset it. Ready-made, schedule it: [Monitor subreddits: only new posts each run](https://apify.com/moxlade/reddit-scraper/examples/monitor-subreddits-only-new).

### Input configuration

| field | type | default | what it does |
|---|---|---|---|
| `subreddits` | `array` |  | Subreddit names or URLs (Upwork, r/Upwork, https://www.reddit.com/r/Upwork/). Each is listed by `sort` and `time`. With `searches` set as well, every search runs inside each of these subreddits instead. |
| `sort` | `new` / `hot` / `top` / `rising` | `"new"` | How each subreddit is listed. `new` is chronological, which is what `postedSince` and `onlyNew` walk most cheaply. |
| `time` | `hour` / `day` / `week` / `month` / `year` / `all` | `"week"` | Applies to `sort: top` only. |
| `searches` | `array` |  | Keyword searches for posts, across all of Reddit — or inside each of `subreddits` when both are given. One row per matching post. |
| `searchSort` | `new` / `relevance` / `hot` / `top` / `comments` | `"new"` | Order of search results, as Reddit's own search offers it. |
| `postUrls` | `array` |  | Specific posts to fetch: URLs (https://www.reddit.com/r/Upwork/comments/1w8w2hb/…) or ids (1w8w2hb, t3\_1w8w2hb). Each comes back with its full body and, with `includeComments`, its comment tree. |
| `includeComments` | `boolean` | `false` | Fetch the comment tree of every delivered post — one `comment` row per comment, with author, score, depth and parent, right after its post. Billed as `comment` per row. |
| `maxCommentsPerPost` | `integer` | `100` | Cap on comment rows per post. Deep threads are expanded breadth-first until the cap. |
| `commentSort` | `confidence` / `top` / `new` / `controversial` / `old` / `qa` | `"confidence"` | Reddit's comment ordering for the tree. |
| `fetchBodies` | `boolean` | `true` | A search hit alone carries title, score, comment count and date. Leave this on to read each hit's author and full text as well (one extra request per post). Subreddit listings and post URLs always carry the body. |
| `postedSince` | `string` |  | Keep only posts created after this point: a date (2026-09-01), a timestamp, or a window before now — 12h, 7d, 2w, 1m. With `sort: new` the listing walk stops at the cutoff, so nothing older is fetched. |
| `onlyNew` | `boolean` | `false` | Remember every post delivered and skip it next time. Schedule the task and each run returns only what appeared since the previous one — a run with nothing new delivers no rows and costs nothing. The memory is a named key-value store (`stateStoreName`, or one derived from the targets when left empty). |
| `stateStoreName` | `string` |  | Name of the key-value store that keeps the delivered ids for `onlyNew`. Leave empty to derive one from the subreddits, searches and post URLs; set it to share one memory between tasks or to reset it (a new name starts fresh). |
| `maxItems` | `integer` | `100` | Stop after this many post rows across the whole run. Comment rows are bounded separately by `maxCommentsPerPost`. With no start fee, this is also your spending cap: posts × $0.002 (+ comments × $0.001). |
| `maxPostsPerSource` | `integer` | `100` | How far down each listing or search to look. Reddit itself stops a listing at about 1,000 posts. |

### FAQ

**Does it need a Reddit account or a proxy?**

No. Reddit is read logged out, through an exit we maintain, and nothing is stored on your side. There is no cookie or proxy field because there is nothing for you to supply.

**Why does a post fetched by URL have no score?**

Reddit's post page renders nothing but a script shell to a visitor; the post's body and its comment tree come from two other endpoints that do not carry the post's score. A post reached through a subreddit listing or a search has its score, upvote ratio and comment count, because those pages do.

**How many comments does a post return?**

Up to `maxCommentsPerPost` (default 100, up to 2,000). The first page of a thread holds about 25 top-level comments with their visible replies; deeper branches are expanded breadth-first until the cap. A thread's `comment_count` is Reddit's total; the delivered count can be lower when comments are deleted or collapsed.

**What does a run cost?**

One event per row that lands in your dataset — $2 per 1,000 posts, $1 per 1,000 comments — nothing for the run itself and nothing for a zero-row run. Measured on our release runs: 25 listing rows in a 6 s run, 20 search rows with bodies in 26 s, one post with 40 comments in 17 s.

**Who makes this, and what else is there?**

[Moxlade](https://moxlade.com) — corpora your agent can ask. Its other actor is the [Upwork freelancer census](https://apify.com/moxlade/upwork-freelancers) (search by rate, JSS, badge, country; exact earnings; every contract), and its MCP endpoint for Upwork buyer intelligence is [buyer.moxlade.com](https://buyer.moxlade.com). Working code for the same client calls, in Python, JavaScript and curl: [github.com/getmoxlade/upwork-freelancers-examples](https://github.com/getmoxlade/upwork-freelancers-examples) — this actor takes the same calls with its own input.

**Is the data current?**

Every row is read from Reddit at run time — `fetched_at` says when — so scores and comment counts are what Reddit showed at that moment.

### Integration

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('moxlade/reddit-scraper').call({"subreddits": ["Upwork"], "sort": "new", "maxItems": 50});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('moxlade/reddit-scraper').call(run_input={'subreddits': ['Upwork'], 'sort': 'new', 'maxItems': 50})
items = client.dataset(run['defaultDatasetId']).list_items().items
```

#### CLI

```bash
apify call moxlade/reddit-scraper --input '{"subreddits": ["Upwork"], "sort": "new", "maxItems": 50}'
```

#### REST

```bash
curl -X POST "https://api.apify.com/v2/acts/moxlade~reddit-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' -d '{"subreddits": ["Upwork"], "sort": "new", "maxItems": 50}'
```

### Support

support@moxlade.com

*This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.*

# Actor input Schema

## `subreddits` (type: `array`):

Subreddit names or URLs (Upwork, r/Upwork, https://www.reddit.com/r/Upwork/). Each is listed by `sort` and `time`. With `searches` set as well, every search runs inside each of these subreddits instead.

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

How each subreddit is listed. `new` is chronological, which is what `postedSince` and `onlyNew` walk most cheaply.

## `time` (type: `string`):

Applies to `sort: top` only.

## `searches` (type: `array`):

Keyword searches for posts, across all of Reddit — or inside each of `subreddits` when both are given. One row per matching post.

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

Order of search results, as Reddit's own search offers it.

## `postUrls` (type: `array`):

Specific posts to fetch: URLs (https://www.reddit.com/r/Upwork/comments/1w8w2hb/…) or ids (1w8w2hb, t3\_1w8w2hb). Each comes back with its full body and, with `includeComments`, its comment tree.

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

Fetch the comment tree of every delivered post — one `comment` row per comment, with author, score, depth and parent, right after its post. Billed as `comment` per row.

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

Cap on comment rows per post. Deep threads are expanded breadth-first until the cap.

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

Reddit's comment ordering for the tree.

## `fetchBodies` (type: `boolean`):

A search hit alone carries title, score, comment count and date. Leave this on to read each hit's author and full text as well (one extra request per post). Subreddit listings and post URLs always carry the body.

## `postedSince` (type: `string`):

Keep only posts created after this point: a date (2026-09-01), a timestamp, or a window before now — 12h, 7d, 2w, 1m. With `sort: new` the listing walk stops at the cutoff, so nothing older is fetched.

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

Remember every post delivered and skip it next time. Schedule the task and each run returns only what appeared since the previous one — a run with nothing new delivers no rows and costs nothing. The memory is a named key-value store (`stateStoreName`, or one derived from the targets when left empty).

## `stateStoreName` (type: `string`):

Name of the key-value store that keeps the delivered ids for `onlyNew`. Leave empty to derive one from the subreddits, searches and post URLs; set it to share one memory between tasks or to reset it (a new name starts fresh).

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

Stop after this many post rows across the whole run. Comment rows are bounded separately by `maxCommentsPerPost`. With no start fee, this is also your spending cap: posts × $0.002 (+ comments × $0.001).

## `maxPostsPerSource` (type: `integer`):

How far down each listing or search to look. Reddit itself stops a listing at about 1,000 posts.

## Actor input object example

```json
{
  "subreddits": [
    "Upwork"
  ],
  "sort": "new",
  "time": "week",
  "searchSort": "new",
  "includeComments": false,
  "maxCommentsPerPost": 100,
  "commentSort": "confidence",
  "fetchBodies": true,
  "onlyNew": false,
  "maxItems": 100,
  "maxPostsPerSource": 100
}
```

# Actor output Schema

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

All scraped records in the default dataset. One row per post or comment (`kind` says which):

# 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 = {
    "subreddits": [
        "Upwork"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("moxlade/reddit-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 = { "subreddits": ["Upwork"] }

# Run the Actor and wait for it to finish
run = client.actor("moxlade/reddit-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 '{
  "subreddits": [
    "Upwork"
  ]
}' |
apify call moxlade/reddit-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,moxlade/reddit-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/mNsA8bCsqDu02GdoW/builds/5wffBtz8ayRhiZjmN/openapi.json
