# Reddit Scraper — Subreddit Posts, Comments & Search, No API Key (`steadyfetch/reddit-scraper`) Actor

Type a subreddit and get its posts as rows — title, text, score, upvote ratio, comment count, flair, date, image or playable video link — sorted hot, new, top or rising. Add comments per post, search all of Reddit, or paste post links. No API key, no login, exact limit, no result fee.

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

## Pricing

from $1.50 / 1,000 items

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/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 — Subreddit Posts, Comments & Search, No API Key

**Click Start with nothing set** and the run returns a small built-in sample — one public subreddit, five posts, comments off — so you see the output shape before you spend anything, at no result fee.

**Using an AI agent?** Pin this actor in Apify's MCP server with one link: `https://mcp.apify.com?tools=steadyfetch/reddit-scraper`

- **Actor id:** `steadyfetch/reddit-scraper`
- **Input:** `{ "subreddits": ["smallbusiness"] }` — the one field you have to set. Or `{ "searchQueries": ["apify"] }` to search all of Reddit, or `{ "postUrls": ["https://www.reddit.com/r/smallbusiness/comments/1wdl068/i_understand_why_my_supplier_doesnt_take_cards/"] }` for posts you already have links to.
- **Cap the bill:** set `maxTotalChargeUsd` on the run (a run option, not Actor input), e.g. `0.50` — the run stops when it reaches it.
- **Your cap is the cap.** `resultsLimit` (default 50) is exact and per subreddit or query; `maxItems` (default 1,000) caps the whole run, post rows and comment rows together. If your input carries `limit`, `count` or `maxPosts` instead — the names other Reddit scrapers use — the smallest of them is read as `maxItems` and an uncharged note row says which.

**Priced from $1.50 per 1,000 items** on the cheapest paid tier, $3.00 per 1,000 on the Apify free plan, platform usage included, no start fee. One item is one row — a post, or a comment. You are charged only when a row lands in your dataset: a subreddit Reddit will not show us, a post link that is gone, a search that matched nothing, and every row a limit or the run clock stopped us from collecting all cost $0.

### What one row looks like

A real delivered post row, built by this actor's own parser from a harvested subreddit listing:

```json
{
  "type": "post",
  "id": "1wdl068",
  "fullname": "t3_1wdl068",
  "permalink": "https://www.reddit.com/r/smallbusiness/comments/1wdl068/i_understand_why_my_supplier_doesnt_take_cards/",
  "subreddit": "smallbusiness",
  "subredditId": "t5_2qr34",
  "title": "I understand why my supplier doesn’t take cards but damn",
  "text": "We're placing our biggest inventory order so far and I completely forgot this supplier is ACH only…",
  "authorName": "…",
  "authorId": "…",
  "createdAt": "2026-09-11T16:24:41.000Z",
  "score": 80,
  "upvotes": 80,
  "upvoteRatio": 0.92,
  "commentCount": 46,
  "flair": null,
  "isNsfw": false,
  "mediaType": "text",
  "imageUrl": null,
  "videoUrl": null,
  "source": "subreddit_feed",
  "status": "delivered",
  "charged": true
}
```

The post text and the two author fields are trimmed for this page — a real row carries the body in full, as published and as HTML, and the author's name beside the stable ID behind it. A comment row carries the same columns plus the post it belongs to, its parent and its depth. Every column is listed in the table below; a row that could not be delivered carries the same columns with `null` in them plus a status saying why, and no result fee.

### What you get

One row per post and — with **Include comments** on — one row per comment, on **one column set** whichever door the row came through. `type` says which it is, so a post and its thread land in the same table.

| column | what it is |
|---|---|
| `type` | `post` or `comment` |
| `id` · `fullname` · `url` · `permalink` | the Reddit ID, the fullname Reddit keys it by, the URL the post points at, and the reddit.com permalink |
| `subreddit` · `subredditId` | the subreddit it came from, by name and by stable ID |
| `title` · `text` · `textHtml` | the post title, the post text as published, and the same text as HTML. On a comment row, `text` is the comment body. |
| `authorName` · `authorId` | the author's name and the stable ID behind it. A name can be changed by its owner; the ID cannot. |
| `createdAt` | when it was published, ISO-8601 UTC |
| `score` · `upvotes` · `upvoteRatio` · `commentCount` | the four engagement numbers, as Reddit serves them — real values, not zeros: a measured page carried a score on 25 of 25 rows, with the upvote ratio and the comment count beside it. |
| `flair` · `isNsfw` · `isSpoiler` | the flair text, and the over-18 and spoiler flags |
| `isVideo` · `postHint` · `domain` | Reddit's own media hints. **A row from Reddit's own search is thinner than a feed row:** search does not serve `flair`, `postHint` or `domain`, and on those rows they are explicit nulls rather than guesses. |
| `mediaType` | `text`, `image`, `video`, `gallery` or `link` |
| `imageUrl` · `videoUrl` · `videoAudioUrl` · `linkUrl` | the direct image link, the playable video link and its separate audio track, and the outbound link on a link post |
| `awards` | how many awards the post carries |
| `postId` · `parentId` · `depth` · `isReply` · `collapsed` | on a comment row: the post it belongs to, its parent, how deep in the thread it sits, whether it replies to another comment, and whether Reddit had it collapsed |
| `source` | the door this row came through: `subreddit_feed`, `search`, `comment` or `link` |
| `charged` · `chargedEvents` | whether this row was billed, and by which event. No row bills two. |
| `status` · `statusReason` | what happened, in a sentence, on every row including the ones that cost nothing |

**A gallery post ships as `mediaType: gallery` with the gallery page link and no member images.** Reddit's feed carries no gallery metadata at all — no image list, no image count, nothing — verified absent across three 82 KB pages of it. The gallery link is what exists, so the gallery link is what the row says, rather than an empty column that promises pictures.

### The video column no one else ships

**A Reddit-hosted video post comes out playable.** Reddit answers a video post with a bare `v.redd.it` link that plays nothing on its own, and the shelf's bigger listings hand you that link as-is. This row resolves it.

- `videoUrl` is the highest rendition Reddit publishes for that video, `CMAF_720.mp4`, read from Reddit's own DASH manifest for the post. The manifest is a public file and reading it costs you nothing extra — there is no second event and no surcharge on a video row.
- `videoAudioUrl` is a **separate track**, because that is how Reddit serves it: the video file carries no sound of its own. For the pictures take `videoUrl`, for the spoken words take `videoAudioUrl`, for both mux the two.
- A video whose manifest will not answer leaves `videoUrl` and `videoAudioUrl` null with `videoUrlReason` saying why — **and the post row is delivered and charged exactly as it would have been.** A link we could not resolve never costs you the row it sits on.

### What it costs

Two charged events. Nothing is charged for starting a run, and nothing is charged for a row that did not land.

| event | what one unit is | Apify free plan | paid plans, from |
|---|---|---|---|
| **Item** | one post row or one comment row, from a subreddit feed, from Reddit's own search, or from a post's comments | $0.003 | $0.0015 |
| **Post lookup** | one post you named by link, delivered with the same columns | $0.012 | $0.005 |

An **Item** is a post or a comment — the same row and the same price either way, so the bill reads straight off the row count and nothing else.

**50 posts from one subreddit** is 50 items: **$0.15** on the Apify free plan, **$0.075** from the cheapest paid tier.

**One post link with comments on** is one Post lookup plus that post's first page of comments — about 25 items — so **$0.087** and **$0.0425**. The comments ride on the same read: turning them on costs nothing beyond the rows they produce.

**Comments multiply rows, and that is the one number to set before you start.** 50 posts with **Max comments per post** at 50 is up to 2,550 rows, not 50. `maxItems` (default 1,000) is the ceiling on the whole run, and `maxTotalChargeUsd` on the run is the ceiling on the bill.

### Never charged

Every one of these is still **delivered as a row**, labelled, with a sentence saying which it was — never a silent gap in the dataset, and never a charge.

| the row says | what happened |
|---|---|
| `subreddit_unavailable` | Reddit returned no posts for that subreddit — it may not exist, be private, be banned or simply be empty |
| `post_not_found` | a post link Reddit answers with an empty shell: the post is gone, or was never there |
| `no_results` | a search that matched nothing. Typed, never retried, and never widened |
| `feed_unavailable` | the read failed on our side. A re-run is the fix, and the row says so |
| `unsupported_link` | a link this actor cannot serve: a `/user/` or `/wiki/` link, or a host that is not Reddit's |
| `skipped_date_window` | your own date window dropped a post you named by link |
| `skipped_nsfw` | your own over-18 setting dropped it |
| `skipped_seen` · `skipped_duplicate` | your account already had that row, or the same row arrived twice inside one run. A run whose API token cannot open key-value stores can produce neither — it says so on its first row |
| `skipped_max_items` · `skipped_budget` · `skipped_deadline` | your own row ceiling, your own `maxTotalChargeUsd`, or the run clock ended the collecting first |
| `skipped_targets` | this run's own ceiling of 200 targets trimmed the rest of your list. That ceiling is ours, not yours |
| `skipped.page_cap` | a walk stopped at this run's own reading depth while Reddit was still serving — a subreddit, a search, or one post's comment thread. That depth is ours, not yours, and the rows behind it were never read or charged |
| `vendor_budget` · `vendor_out_of_credit` | our own monthly collection allowance, or our collection credit running out mid-run. Both ours; neither is ever yours |
| `input_error` — and `input_error.subreddits`, `input_error.searchQueries`, `input_error.postUrls`, `input_error.startUrls` | something in that field could not be read. The row names the field, never what you typed |
| `undeclared_field` | you sent a field name this actor does not have, so nothing was read from it. The row names the name you sent and the field this actor uses instead, never what you typed |

**A walk that runs short also says WHY, on its own uncharged note row.** A subreddit is read to a depth of 40 pages and one search query to 5 — so a walk that stopped there says it stopped at this run's own depth, which is ours and not a statement about what Reddit holds, and tells you what narrows the ask (a date window, a different sort, a more specific query). Only a listing that genuinely ran out says the rest does not exist to collect. Those rows are counted on the run's record as `skipped.page_cap`, so the depth we chose is a number you can see rather than a shortfall that quietly shrinks your ask. One post's comment thread is read to a depth of 20 pages on exactly the same rule: the post row says the thread went deeper than one run reads, and the comments behind our depth are counted the same way. Your own "Max comments per post" ending a thread is the opposite case — that is your setting, nothing was refused, and nothing is counted. And if a read fails part-way through a subreddit you were already being served, that row opens with what was already delivered — those rows are yours and each says what it was charged — and the re-run is for the rest.

**And here is the one the shelf does not say out loud: a subreddit that does not exist, one that is private and one that is banned all come back as the same empty answer.** Reddit tells us nothing that separates them — one identical body for all three — so the row says all three rather than picking one and sounding certain, and we do not buy a second read to guess. You are charged for none of it. The complaint that fills the Issues tabs of the biggest Reddit scrapers on this store is a run that reports success and returns nothing; this section is the answer to it.

### Three things worth knowing

- **A Reddit user's own post list is not a door.** Reddit does not serve it to any reader we can be. That is a fact about Reddit, not a feature waiting on a roadmap — paste that user's post links instead, and each one comes back as a full row.
- **Comments come in pages of about 25**, with replies nested under their parents. **Max comments per post** (`maxCommentsPerPost`) is your cap: the run walks pages until it reaches the cap, the thread ends, or this actor's own ceiling of 20 comment pages for one post — so one thread can never spend a whole run. A post whose thread still had more keeps a `comments_truncated` note on its own row saying how many were delivered and which of those three stopped it. That is a note on a delivered, charged row — never a miss, and never an extra charge.
- **Search is Reddit's own search, and it returns 4 to 7 posts per page.** Narrow a query with a subreddit or a date window rather than paging deep. **And this actor never widens a query that came back empty** — an empty search ships one `no_results` row and stops there. Widening is why "the results are about the wrong topic" is the second thing buyers write on a Reddit scraper's Issues tab.

### How often the data changes

| feed | how fast it moves |
|---|---|
| `hot` · `rising` | turns over within the hour — the same run an hour later returns a different page |
| `new` | a stream. It is always moving and it never repeats |
| `top` | stable once its window has closed: last week's `top` for a finished week reads the same next month |
| a post's `score` and `commentCount` | keep moving for about 48 hours after it is published, then settle |

**The schedule that stays cheap.** Run `sort: new` with **Only posts published after** (`postedAfter`) set to your window — a day, an hour — and the walk stops as soon as the feed goes older than that, instead of paging into posts you already hold. Your account's memory does the rest: every row this actor has already delivered to your account is skipped on the next run, no row and no charge, so a daily schedule pays for what is new and nothing else. Switch **Include rows you already have** on to get them anyway, marked `repeat: true` and still uncharged. The memory is a key-value store in your own Apify account, so a run started with a scoped API token in restricted-access mode needs key-value store Read, Write and Create permission, or Actor runs set to Full access (Write is what lets the run remember what it delivered; without it every run pays again); without it the run says so on its status line and on its first row, and cannot skip what you already have.

For a leaderboard rather than a stream, `sort: top` over a closed `timeframe` is the one feed you can re-read without surprises — and the second read of it costs nothing, because the memory already has those rows — as long as the run's API token can open key-value stores in your account.

### Every run ends with a receipt

The last row of every run is a receipt: rows delivered by door, post rows against comment rows, what was asked for, what your account already had, what your date window and your over-18 setting dropped, what stopped the run, and the charged totals for both events — so an invoice reconciles from the dataset itself. **A cost cap or a time limit ends the collecting, never the delivering** — rows already in hand are always written out.

### Related actors

- The spoken words of a Reddit video: hand `videoAudioUrl` to `steadyfetch/media-transcriber` in its `urls` field — the audio track is the one with sound in it.
- Comments under a Facebook post: `steadyfetch/facebook-comments-scraper`. Posts from a Facebook page or public group: `steadyfetch/facebook-posts-scraper`.

### Something not right?

Open the **Issues** tab on this actor with your run ID and the input you used, and it gets looked at. If it earned its keep, a rating helps other buyers find it, and saving the actor keeps it one click away.

# Actor input Schema

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

Subreddit names, one per line — "smallbusiness", "r/smallbusiness" or a link to the subreddit; names are not case sensitive. Each one is walked under the sort you choose below, up to "Max posts per subreddit or query". A subreddit that does not exist, one that is private and one that is banned all answer identically, so they ship as one uncharged row saying exactly that rather than guessing which it was. Leave this empty and the run returns a small built-in sample instead of collecting anything, at no result fee. A post link put here is routed to the post box automatically, not refused.

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

Search terms, one per line — each one searches all of Reddit and returns post rows with the same columns as a subreddit walk. Reddit's own search serves 4 to 7 posts per page and is the slowest door here, so narrow a query with a date window instead of asking for hundreds of rows. A query that matches nothing ships one uncharged row and is never retried, and no query is ever widened or rewritten to find something — you get what you typed or you get told.

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

Individual Reddit post links, one per line — https://www.reddit.com/r/<subreddit>/comments/<id>/<slug>/, a redd.it/<id> short link, or a share link. Each one returns that post's own row, charged as one "Post lookup" when the row lands; with "Include comments" on, the same read also brings that post's first page of comments. A link Reddit answers is gone ships as an uncharged row instead.

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

One list for every kind of Reddit link, for buyers moving over from another scraper: subreddit links, post links, reddit.com/search?q= links and r/<subreddit>/search?q= links. Each line is sorted into the right door before anything is bought, so a post link never pays for a subreddit walk and a subreddit link never pays for a post lookup. A /user/ or /wiki/ link is refused on an uncharged row: a user's own post list is not a door Reddit serves to any reader we can be.

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

How each subreddit's own feed is ordered: hot, new, top, rising or best. Read only by subreddits, never by search. "top" reads the timeframe below and the others ignore it. A daily schedule wants new with "Only posts published after" set, so the run stops as soon as the feed goes older than your window.

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

How search results are ordered: relevance, new, top or comment\_count. Read only by "Search all of Reddit", never by a subreddit walk, which has its own sort above.

## `timeframe` (type: `string`):

The window that "top" ranks inside: hour, day, week, month, year or all. Read by a subreddit sorted top, by a search of all of Reddit, and — for any value other than the default week — by a search inside a subreddit, which stays over all time while this box is left alone. Every other feed ignores it, and the run says so rather than pretending it applied.

## `resultsLimit` (type: `integer`):

How many posts to take from EACH subreddit and EACH search query — exact, never overshot, and never padded: a feed that holds fewer gives you what it holds and the run says so. Accepted range 1 to 1,000; a number outside it is moved to the nearest value in range and one uncharged note row says so, rather than the run being refused.

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

Hard ceiling for the WHOLE run, counting post rows and comment rows together, across every subreddit, every query and every post link, whatever else is set. The per-subreddit cap is "Max posts per subreddit or query" above. Other scrapers call this limit, count or maxPosts; those names are read as this field too and the smallest of them wins, with one uncharged note row saying which was read. Accepted range 1 to 50,000; a number outside it is moved to the nearest value in range.

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

OFF (default): post rows only. ON: every post delivered also brings its comment rows — about 25 nodes per page, replies nested under their parents, each one its own row. A comment row is charged like a post row, so a 50-post run with comments on can deliver many times 50 rows: "Max comments per post" below is what bounds it, and maxTotalChargeUsd on the run is what caps the bill.

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

The cap on comment rows taken from ONE post, counting the nested replies. The run walks comment pages until it reaches this number or the thread runs out, and a post whose thread was longer keeps a note on its own row saying so — a note, never a miss, and nothing extra is charged for it. Read only when "Include comments" is on. Accepted range 1 to 1,000; a number outside it is moved to the nearest value in range and one uncharged note row says so.

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

A date, YYYY-MM-DD, an ISO timestamp, or a relative window like "7 days". Posts published before it are dropped, uncharged, and the status line says how many. A subreddit sorted new stops walking as soon as the feed goes older than this, so a daily schedule pays only for what is new.

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

A date, YYYY-MM-DD, an ISO timestamp, or a relative window like "30 days". Posts published after it are dropped, uncharged, and counted on the status line.

## `includeNsfw` (type: `boolean`):

ON (default): posts marked over 18 are delivered like any other, with isNsfw: true on the row so you can filter them yourself. OFF: they are dropped before anything is charged for them and the status line says how many. Reddit serves these posts to this actor either way, so this setting is your filter and never a claim about what Reddit hides.

## `maxRunSeconds` (type: `integer`):

The run stops cleanly before this many seconds and reports what is left, instead of being killed by a timeout. A time limit ends the collecting, never the delivering: rows already in hand are always written out. Accepted range 30 to 3,600 seconds; a number outside it is moved to the nearest value in range and one uncharged note row says so.

## `includeSeen` (type: `boolean`):

OFF (default): a post or comment already delivered to your account is skipped — no row, no charge. ON: those rows are delivered again anyway, marked repeat: true, and still not charged. Anything older than 90 days in your account's memory counts as new again either way.

## `resumeFromDatasetId` (type: `string`):

The dataset ID of a previous run of this actor. Posts and comments already in it are treated as rows you already have and are skipped, so a follow-up run collects only what is new even from a different Apify account. Selecting it here is what grants this run permission to read it.

## Actor input object example

```json
{
  "subreddits": [],
  "searchQueries": [],
  "postUrls": [],
  "startUrls": [],
  "sort": "hot",
  "searchSort": "relevance",
  "timeframe": "week",
  "resultsLimit": 50,
  "maxItems": 1000,
  "includeComments": false,
  "maxCommentsPerPost": 50,
  "includeNsfw": true,
  "maxRunSeconds": 900,
  "includeSeen": false
}
```

# Actor output Schema

## `items` (type: `string`):

One `type: post` row per post delivered, with the same columns whichever door it came through — a subreddit walk, Reddit's own search, or a link you pasted: the post ID and Reddit fullname, the permalink and the URL it points at, the subreddit, the title, the post text as published and as HTML, the author name and stable author ID, the moment it was published, the score, the upvote count and the upvote ratio, the comment count, the flair, the over-18 and spoiler flags, the media type (text, image, video, gallery or link) with a direct `imageUrl`, a playable `videoUrl` and its separate `videoAudioUrl` for a Reddit-hosted video, the external `linkUrl` for a link post, and the door the row came through. TWO EVENTS, ONE FLAG: `charged` is the row itself and `chargedEvents` names which event paid for it — `item` for a post from a subreddit walk or from search, `post-lookup` for a post you named by LINK. No row bills two events. A post row may also carry `comments_truncated` as a note when your "Max comments per post" cap ended a longer thread: it is a note on a delivered, charged row, never a miss and never an extra charge.

## `comments` (type: `string`):

One `type: comment` row per comment delivered when "Include comments" is on: the comment ID and fullname, its permalink, the body as published and as HTML, the author name and ID, the moment it was posted, the score and upvote count, the post it belongs to (`postId`), its `parentId`, its `depth` in the thread, whether it is a reply and whether Reddit had it collapsed. Comments arrive in pages of about 25 with replies nested under their parents, and the run walks pages until your "Max comments per post" cap or the end of the thread. Each comment row is charged as one `item`, the same event and the same price as a post row.

## `misses` (type: `string`):

One uncharged row for every subreddit, query or link that returned less than it was asked for, saying which happened: `subreddit_unavailable` (Reddit returned no posts for that subreddit — it may not exist, be private, be banned or be empty, and Reddit's answer is identical for all four, so we do not guess), `post_not_found` (Reddit answered with an empty shell for that post link — it is gone or was never there), `no_results` (a search that matched nothing; typed, and never retried or widened), `feed_unavailable` (the read failed on our side — a re-run is the fix), `unsupported_link` (a /user/ or /wiki/ link, or a link that is not Reddit's: a user's own post list is not a door Reddit serves to any reader we can be), `vendor_out_of_credit` (our own collection credit ran out mid-run — ours, never yours), `skipped_max_items`, `skipped_budget` and `skipped_deadline` (your own row ceiling, your own maxTotalChargeUsd, or the run clock stopped it first), `skipped_targets` (this run's own ceiling of 200 targets trimmed the rest of your list), `skipped_nsfw` (your own over-18 setting dropped it), `skipped_date_window` (your own date window dropped a post you named by link) and `skipped_seen` (your account already had it). None of these is charged.

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

Rows delivered by door — subreddit walks, search, pasted links — post rows against comment rows, what was asked for, rows your account already had, posts your date window and your over-18 setting dropped, what stopped the run, and the charged-event totals for `item` and `post-lookup`.

# 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": [],
    "searchQueries": [],
    "postUrls": [],
    "startUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyfetch/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": [],
    "searchQueries": [],
    "postUrls": [],
    "startUrls": [],
}

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

```

## MCP server setup

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