# Reddit Scraper API — Posts, Comments, Search, Users (`vonsensey/reddit-scraper-posts-comments-api`) Actor

Scrape Reddit posts, comments, subreddits, users and search into one flat table. Score and upvote ratio on every row, no flag to enable. No API key, no login. Paste any Reddit URL or community name. Filters run before billing, so the rows you discard are free.

- **URL**: https://apify.com/vonsensey/reddit-scraper-posts-comments-api.md
- **Developed by:** [Blackcube Agency AB](https://apify.com/vonsensey) (community)
- **Categories:** Social media, Marketing, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 post, community or user rows

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

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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 API — Posts, Comments, Search, Users

**More from this account:** [YouTube Transcript Suite](https://apify.com/vonsensey/youtube-transcript-scraper) · [Website Contact & Email Suite](https://apify.com/vonsensey/website-contact-email-extractor) · [Career Site & ATS Jobs Suite](https://apify.com/vonsensey/career-page-job-postings-scraper-api) · [Google News Suite](https://apify.com/vonsensey/google-news-scraper-api) · [Keyword Research Suite](https://apify.com/vonsensey/google-keyword-ideas-scraper) · [Shopify Store Intelligence Suite](https://apify.com/vonsensey/shopify-store-leads-scraper) · [eBay Data Suite](https://apify.com/vonsensey/ebay-scraper-api) · [Amazon Reviews Suite](https://apify.com/vonsensey/amazon-reviews-scraper-api) · [Meta Ad Library](https://apify.com/vonsensey/facebook-ads-library-scraper-meta-ad-api) · [Vinted](https://apify.com/vonsensey/vinted-scraper-api)

**Paste anything from Reddit. Get back a flat table with the score, the upvote ratio, the media and the full comment thread already in it.**

A community name, a post link, a `redd.it` short link, a user profile, a search-results URL, or a list of five hundred of them — this Actor works out what each one is and returns the same 37-column schema for all of them. No API key. No approval queue. No login. No developer token.

> **You pay for rows you actually receive.** Starting a run costs a fraction of a cent — $0.003, falling to $0.001 by volume. That is the only tiered start fee in this category and it is 8× to 86× below what the largest Actors here charge. After that: a community that turns out to be private, a search with no hits, a user that no longer exists, every row a filter discarded, every duplicate, and every row a previous run already gave you are **free**. They come back as rows explaining themselves and they never reach your invoice.

> **Unofficial.** Not affiliated with, endorsed by, or connected to Reddit. It reads only what Reddit publishes publicly to logged-out visitors.

***

### Why this one

#### 1. The score and the upvote ratio are on every row, by default

This is the field buyers in this category most often do not get. There is no flag to switch on, no "detailed mode" that halves your throughput, and no best-effort caveat.

On the last 1,500-post benchmark run — five communities, `new` sort, 34 seconds — `score`, `upvoteRatio`, `createdAt` and `title` were populated on **1,500 of 1,500** rows. `author` was populated on 1,499; the one gap was a deleted account, which is returned as `null` rather than as the literal text `[deleted]`.

**A missing value is always `null`, never `0`.** A post with no score and a post scored zero are different facts, and a filter on `score > 0` must not silently swallow the second kind.

#### 2. Paste the URL you already have

| You paste | What you get |
|---|---|
| `rust` or `r/rust` | The community's posts |
| `https://www.reddit.com/r/rust/top/?t=week` | That exact feed, sort and window already applied |
| `https://www.reddit.com/r/rust/comments/1vq17rg/…` | That post, plus its comment thread |
| `https://redd.it/1vq17rg` | Same, from the short link |
| A link to a specific comment | The post it belongs to, with the thread |
| `https://www.reddit.com/user/spez/` | That user's public posts |
| `https://www.reddit.com/search/?q=rust+async` | That search, exactly as Reddit ranks it |
| `u/spez`, `/r/rust`, `old.reddit.com/…`, `sh.reddit.com/…` | All understood |

Anything it cannot read comes back as a free row naming the input and the reason. It is never guessed at. A bare word like `marketing` is **not** silently treated as a community — that is far more likely to be a search term pasted into the wrong box, and resolving it to a community would bill you for data you never asked for.

#### 3. A spending cap that actually binds

**Total row limit** is a hard ceiling on billable rows for the entire run, counting posts and comments together, and it is enforced at the moment of delivery rather than checked hopefully in a loop. Set it to 1,000 and you get 1,000 — not 1,004 because four workers were in flight, and not 15,000 because the limit was per-source and you supplied twenty sources.

It survives interruption, too: if the platform migrates the container mid-run, the count continues from what was already delivered instead of restarting.

#### 4. Repeat runs only charge for what is new

Turn on **Only rows I have not had before** and a scheduled run returns — and bills for — only what has appeared since last time. The first run returns everything; every run after it returns the delta.

| | Run 1 | Run 2 | Run 30 |
|---|---|---|---|
| Normal | 500 rows | 500 rows | 500 rows |
| **Only new** | 500 rows | ~20 rows | ~20 rows |

Each schedule keeps its own memory, and **editing the input list does not reset it** — adding one more community to a daily job does not make the next run re-deliver and re-charge for everything it already gave you.

#### 5. Date windows and keyword filters, and you are not billed for what they discard

Filtering is the most-requested and least-available feature in this category, and the reason is always the same: when an Actor bills for every row it touches, throwing rows away costs the developer money. Discarding is cheap here, so it is free for you.

- **Posted after** / **Posted before** — an absolute date (`2026-01-31`) or an age (`7 days`, `12h`, `3 months`). Use an age in a scheduled run; a fixed date silently goes stale.
- **Must contain** / **Must not contain** — keyword filters over title, body and flair.
- **Minimum score.**

Every row these remove is discarded **before** billing, and the run log tells you how many and why.

#### 6. Comment threads that are actually complete

Reddit truncates long threads and leaves a "load more" stub in place of the rest. This Actor follows those stubs and keeps going until it has the number of comments you asked for, so a 5,000-comment thread returns comments rather than stubs. Replies carry `depth`, `parentId` and `isSubmitter`, so the tree can be rebuilt exactly.

#### 7. Deep coverage, past the per-community ceiling

Reddit stops any single community feed at roughly 1,000 posts and then simply stops paginating. Switch on **Deep coverage** and the same community is read through its other sorts and time windows and the results are de-duplicated.

Measured on `r/rust`: the best single feed returned **998** unique posts; four feeds combined and de-duplicated returned **1,488**.

**What this is not:** it is not a full historical archive, and no live scraper can be one. If a community has 200,000 posts going back ten years, this reaches a few thousand of them, not all of them. That limit is Reddit's and it applies to Reddit's own official API as well. Where a run stops short, the log says which of the two reasons it was — a limit you set, or the ceiling itself.

***

### What you get

One flat row per post, comment, community or user, plus free rows for anything that produced nothing. Every row carries `type`, `sourceRef` (which of your inputs produced it) and `scrapedAt`.

**Posts** — `id` · `fullId` · `url` · `permalink` · `subreddit` · `subredditId` · `title` · `body` · `bodyHtml` · `author` · `authorId` · `createdAt` · `score` · `upvoteRatio` · `numComments` · `flair` · `linkUrl` · `domain` · `thumbnail` · `images[]` · `videoUrl` · `galleryImages[]` · `isNsfw` · `isSpoiler` · `isOc` · `isSelf` · `isVideo` · `isPinned` · `isStickied` · `isLocked` · `isArchived` · `totalAwards` · `editedAt` · `crosspostParentId`

**Comments** — `id` · `fullId` · `postId` · `postTitle` · `parentId` · `permalink` · `subreddit` · `author` · `authorId` · `body` · `bodyHtml` · `score` · `createdAt` · `depth` · `isSubmitter` · `isStickied` · `editedAt` · `totalAwards`

**Communities** — `name` · `title` · `description` · `publicDescription` · `subscribers` · `activeUsers` · `createdAt` · `isNsfw` · `lang` · `iconUrl` · `bannerUrl`

**Users** — `username` · `createdAt` · `linkKarma` · `commentKarma` · `totalKarma` · `isGold` · `isMod` · `isEmployee` · `isVerified` · `iconUrl` · `bio`

**Free rows** — `sourceRef` · `errorReason` · `message` · `statusCode`. `errorReason` is one of `notFound`, `private`, `banned`, `quarantined`, `empty`, `blocked`, `badInput`, `maxItemsReached`, `chargeLimitReached`, `requestFailed` — a stable machine-readable value, so a pipeline can branch on it.

Text arrives unescaped. A title containing `&` arrives as `&`, not `&amp;`.

***

### How to scrape a subreddit

Put the community name in **Communities** — `rust`, or `r/rust`, either works — and pick a **Sort**. `top` and `controversial` also use the **Time window**.

Set **Results per source** for how many posts you want from each. Beyond roughly 1,000, turn on **Deep coverage**.

### How to scrape Reddit comments

Switch on **Include comments** and set **Comments per post**. Every post the run returns then also returns its thread, with replies followed to **Reply depth**.

For one specific thread, put its URL in **Reddit URLs** instead — you get the post and its comments and nothing else. Comments are billed at their own, lower rate.

### How to scrape Reddit search results

Put your terms in **Keywords**. Reddit's own operators work and are passed through untouched: `title:launch`, `author:spez`, `flair:news`, `"an exact phrase"`, `self:yes`, and `AND` / `OR` / `NOT`.

Your query is never rewritten, never split into separate single-word searches, and never quietly widened. If you also list **Communities**, the search is restricted to them; if you do not, it runs across Reddit.

Reddit's search returns roughly 250 results per query. To go deeper, split the query — by time window, by community, or by adding terms.

### How to scrape a Reddit user

Put usernames in **Users**, or paste profile URLs. `…/user/name/comments/` returns their comments instead of their posts; `…/user/name/about` returns the profile record on its own.

### How to monitor a subreddit for new posts

Sort by `new`, switch on **Only rows I have not had before**, set **Posted after** to something like `2 days`, and put the Actor on a schedule. Each run returns only what appeared since the last one, and you are billed only for those rows.

***

### Pricing

Two units, because a thread returns an order of magnitude more comments than posts and charging both at one rate makes a comment-heavy pull absurd.

| | FREE | BRONZE | SILVER | GOLD | PLATINUM | DIAMOND |
|---|---|---|---|---|---|---|
| **Per 1,000 posts** | $6.00 | $5.40 | $3.90 | $3.00 | $2.80 | $2.60 |
| **Per 1,000 comments** | $0.90 | $0.80 | $0.70 | $0.60 | $0.55 | $0.50 |
| **Per run started** | $0.003 | $0.0025 | $0.002 | $0.0015 | $0.0012 | $0.001 |

Communities and user profiles are billed at the post rate. Platform usage is included — what is above is what you pay, with nothing added afterwards.

**Everything here is tiered, including the run fee.** Every other Actor in this category charges a flat start fee that its largest customers pay at the same rate as its smallest — and charges between $0.02 and $0.216 for it. The ladder here also keeps descending past Gold, where the rest of the category flattens out and high-volume buyers stop being rewarded for volume.

**Never billed:** rows a filter discarded, rows an earlier run already delivered when **Only new** is on, duplicate rows, and every free row explaining a gap.

A ten-row evaluation run costs about **$0.063** all in.

***

### Honest limits

- **A residential proxy is required**, and it is the default. Reddit refuses datacenter addresses outright, so a run configured without one will return free `blocked` rows rather than data. Leave the proxy setting alone unless you know why you are changing it.
- **Roughly 1,000 posts per community feed**, ~250 per search query, ~500 per `top` window. Deep coverage combines feeds to beat this; nothing gets you the complete history of a large community.
- **Public content only.** Private, banned and quarantined communities return a free row saying which. Nothing behind a login is read.
- **Deleted content is gone.** An author who deleted their account is `null`, not a name.

### Frequently asked

**Do I need a Reddit account, an app, or an API key?** No. Nothing to register, nothing to wait for approval on.

**Why is there a run fee at all, when the rest of the billing is per row?** Because reaching Reddit at all costs something before a single row exists, and a fee that covers it is what lets everything else — the filters, the duplicates, the failures — genuinely stay free. It is a fraction of a cent and it is tiered; the alternative most of this category picked was a flat fee 8× to 86× larger.

**What if I type a date it cannot read?** You get a free row saying so, and the run does not pretend the filter ran. It will never quietly bill you for rows a filter you thought was active should have removed.

**What happens if a community in my list is private?** You get a free row with `errorReason: "private"` and the run carries on. Every input you supply produces either data or an explanation — never silence.

**Can I get more than 1,000 posts from one community?** Yes, with **Deep coverage** — measured at 1,488 unique on a community where a single feed gave 998. Not unlimited, and not the full archive.

**Why did my run return fewer rows than I asked for?** The log says which of the two reasons applied: a limit you set, or Reddit's own ceiling. They are reported separately on purpose.

**Can I use this from Python / n8n / Make / an LLM agent?** Yes — it is a standard Actor with a standard dataset, callable from the Apify API and client libraries.

***

*You are responsible for how you use the data you collect, including compliance with Reddit's terms and with privacy law in your jurisdiction. Scrape public content, and honour deletion requests.*

> **Run it without configuring anything** — [Scrape the top posts of a subreddit](https://apify.com/vonsensey/reddit-scraper-posts-comments-api/examples/top-posts-and-comments-of-a-subreddit), a ready-made example you can start as-is or copy.

### Use cases

- **Research what people actually say.** Posts and comments in one flat table, with score and upvote ratio on every row.
- **Track a brand or a topic.** Search across Reddit and re-run it on a schedule to catch new mentions.
- **Mine a community.** Pull a subreddit's history for product research, sentiment or training data.
- **Follow a thread properly.** Comment trees come back whole rather than truncated at the first page.

### Run it on a schedule

A one-off pull answers a question; a schedule answers it every day without you. Open **Schedules** in the Apify Console, point a cron at this Actor, and the dataset keeps filling on its own — no server, no cron box, no babysitting. Everything here is built to be re-run: you are billed per row delivered, so a scheduled run that finds nothing new costs nothing.

### FAQ

#### Do I need a Reddit API key or login?

No. No key, no OAuth, no account.

#### Can I paste any Reddit URL?

Yes — post, subreddit, user or search URL, and mixed in one run.

#### Are scores and upvote ratios included?

Yes, on every row, with no flag to enable.

#### Can I get comments as well as posts?

Yes, in the same run and in the same table, with a type column separating them.

***

Something wrong, or a field you need that is missing? Open an issue on the **Issues** tab — it is read and it gets fixed. If this saved you time, a rating on the Store page helps the next person find it.

# Actor input Schema

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

Paste any Reddit address and it is routed for you: a community, a sorted community feed, a post, a comment permalink, a user profile, a search results page, or a redd.it short link. Mix them freely.

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

Community names, with or without the r/ prefix — for example `askreddit` or `r/rust`. If you also fill in Keywords, these become the communities those keywords are searched inside.

## `searchQueries` (type: `array`):

Search terms. Supports Reddit's own operators, e.g. `title:launch`, `author:spez`, `"exact phrase"`, `flair:news`. Searched across all of Reddit, or inside the communities above if you listed any.

## `usernames` (type: `array`):

Reddit usernames, with or without the u/ prefix. Returns that user's public posts.

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

Which community feed to read. `top` and `controversial` also use the time window below.

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

Applies to Top and Controversial sorts and to keyword searches.

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

How many posts to take from each community, search or user. Reddit itself stops a single feed at about 1,000 — switch on Deep coverage below to go past that.

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

A hard ceiling on billable rows for the whole run, counting posts and comments together. Leave at 0 for no limit. This is a spending safety net: the run stops here even if more data exists.

## `deepCoverage` (type: `boolean`):

Reddit stops any single feed at roughly 1,000 posts. With this on, the same community is read through its other sorts and time windows and the results are de-duplicated, which reaches materially more of it. Costs more requests, so leave it off for small pulls.

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

Fetch the comment thread under every post returned. Comments are billed at their own, lower rate.

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

Upper bound on comments returned for each post, including replies pulled out from behind Reddit's 'load more' links.

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

Which comments Reddit returns first when a thread is larger than your per-post limit. Best is Reddit's own default ranking.

## `maxCommentDepth` (type: `integer`):

How deep to follow reply chains. 0 returns only top-level comments.

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

Keep only posts and comments newer than this. Takes a date (`2026-01-31`) or an age (`7 days`, `12h`, `3 months`) — an age is the one to use in a scheduled run, because a fixed date goes stale. Rows outside the window are discarded before billing, so you are never charged for them.

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

Keep only posts and comments older than this. Same formats as above. Combine the two to pull an exact date range.

## `mustIncludeKeywords` (type: `array`):

Keep only rows whose text contains at least one of these words. Case-insensitive. Discarded rows are free.

## `mustExcludeKeywords` (type: `array`):

Drop rows whose text contains any of these words. Discarded rows are free.

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

Drop posts and comments below this score. Leave empty for no minimum. Discarded rows are free.

## `skipNsfw` (type: `boolean`):

Drop posts marked over-18 before they are delivered or billed.

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

For scheduled runs. Remembers what this input already returned and delivers only what is new since last time — so a daily run does not re-charge you for the same posts every day. The first run returns everything.

## `feedName` (type: `string`):

Optional label that groups runs sharing one 'only new' memory. Leave empty and it is derived from your inputs, so each distinct input list remembers separately.

## `maxConcurrency` (type: `integer`):

Lower this if you are on a small proxy allowance.

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

Reddit refuses datacenter addresses, so residential proxy is the default and is required for the Actor to return anything.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.reddit.com/r/dataisbeautiful/top/?t=month"
    }
  ],
  "subreddits": [
    "rust"
  ],
  "sort": "hot",
  "time": "all",
  "maxPostsPerSource": 100,
  "maxItems": 0,
  "deepCoverage": false,
  "includeComments": false,
  "maxCommentsPerPost": 50,
  "commentSort": "confidence",
  "maxCommentDepth": 10,
  "skipNsfw": false,
  "onlyNew": false,
  "maxConcurrency": 8,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

No description

## `csv` (type: `string`):

No description

## `consoleDataset` (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/dataisbeautiful/top/?t=month"
        }
    ],
    "subreddits": [
        "rust"
    ],
    "postedAfter": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("vonsensey/reddit-scraper-posts-comments-api").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/dataisbeautiful/top/?t=month" }],
    "subreddits": ["rust"],
    "postedAfter": "",
}

# Run the Actor and wait for it to finish
run = client.actor("vonsensey/reddit-scraper-posts-comments-api").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/dataisbeautiful/top/?t=month"
    }
  ],
  "subreddits": [
    "rust"
  ],
  "postedAfter": ""
}' |
apify call vonsensey/reddit-scraper-posts-comments-api --silent --output-dataset

```

## MCP server setup

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

```

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/qOI8wbt3CtY2GbOsi/builds/sIGBP5XXGaUxKtM20/openapi.json
