Two bugs surfaced by the first live comment-thread run.
A successful run reported "0 dataset items" and warned that it had produced nothing. The platform's item count can lag a write that has only just happened, and the run read it immediately. A run that delivered 41 rows said it delivered none. The rows actually pushed are now the source of truth for that check.
The billing summary claimed results were charged when they were not. Actor.charge() does not throw when an event is missing from the actor's pricing configuration - it logs a warning and returns - so counting our own charge calls overstated what was billed. The summary now reads the platform's own tally per event and reports that instead, and names any event that is not configured:
These events are not configured in this actor's pricing, so nothing was charged for them: subreddit-post, reddit-comment. Your results are complete and free.
Confirmed working in the same run: nested comment replies at depth 0, 1 and 2 with parent links intact, cursor pagination across 3 pages, isOP on the post author's own reply, isDeleted preserving a removed comment's position, and repliesTruncated where Reddit held more back.
Reddit ad data is gone, and this actor no longer claims to provide it.
Reddit shut down its public Ad Library. The upstream endpoints that read it were permanently retired and now refuse every request, so no tool can return Reddit ad data any more. This is a change at Reddit, not a fault here, and nothing can bring it back.
What that means in practice:
- The two ad modes are removed from the form. A Saved Task or API call that still asks for them gets a plain explanation and finishes cleanly, and is never charged.
- The two ad pricing events have been deleted, rather than left in place to charge for something that cannot be delivered.
- The title, description and README no longer mention ad data.
Everything else is unaffected: subreddit posts, site-wide search, search inside subreddits, complete comment threads, subreddit profiles, video transcripts and AI analysis.
Three output bugs fixed, all found in real run data.
- Text posts were labelled
mediaType: "unknown". The upstream response does not always include Reddit's is_self flag, so self-posts fell through to unknown. A self.* domain now settles it, and they are labelled text.
mediaUrls contained the post's own permalink on text posts. A self-post has no media; the field is now empty for them.
- Galleries were labelled
link. A reddit.com/gallery/ URL is now recognised as gallery, and v.redd.it as video.
Upvote ratios are rounded to three decimals instead of being returned as 17-digit floats.
Dataset views rebuilt. There were six, and four of them showed two irrelevant columns on any single-mode run, because an Apify view can pick columns but cannot filter rows. There are now four - Everything, Posts, Comments, AI analysis - and each leads with a Row type column so a mixed dataset reads clearly.
A run that returns nothing now tells you why.
Filters that remove everything used to look identical to a broken actor: the log repeated the same "0/15" line dozens of times and the run ended clean with an empty dataset. Three fixes:
- Every page now reports what happened -
fetched 25, kept 0 (25 removed by filters) instead of a bare running total.
- Paging stops after three straight pages with nothing kept, and says which filter is the likely cause. Before this, a run could make dozens of requests to collect nothing.
- A run ending at zero results warns explicitly, pointing at filters first and then at spelling and capitalisation, since subreddit names are case-sensitive at the source.
Keyword filtering is now documented honestly. Reddit's subreddit-search endpoint returns titles without post bodies, so in that mode keywords can only match the title. A post titled "Cooling advice needed" is dropped by a keyword filter of "fan" even though the body is all about fans. The field description says so and recommends running without it first.
The exact-date boxes are now calendar pickers. Click a day instead of typing and hoping the format is right.
The date reader was widened at the same time, so it now understands the longer phrasings a picker can produce - "7 days", "1 week", "3 months" - alongside the short forms it already took (7d, 1w, 3mo) and full calendar dates. An unreadable date is skipped with a message naming the formats that work, rather than silently doing nothing.
Three fields that made you type now let you choose.
- How far back to look - a new dropdown (Last 24 hours, Last 7 days, Last 30 days, and so on) replaces guessing at a date format. The two exact-date boxes are still there for a specific window like 1 to 15 March, and an exact date overrides the dropdown.
- Transcript language - a list of 25 languages instead of a two-letter code you had to know.
- Which Claude model - three options instead of a free-text model name.
AI analysis is Claude-only now. The provider picker and service-address boxes are gone, so the section is three fields: what to analyse, your key, and which model. Choose from:
| Model | When to use it |
|---|
| Haiku 4.5 (default) | Sentiment and intent on short Reddit text. Cheapest by a wide margin and good enough for most work. |
| Sonnet 5 | Extraction where quotes need to be sharper. |
| Opus 5 | Nuanced material where accuracy beats cost. |
A rejected key now says so plainly and points at console.anthropic.com, instead of showing a raw status code.
Input rewritten for people who have never used this before.
Every title and description is now plain business English with a concrete example, and no internal field names leak into the interface. "How many results? (0 = every result available)" instead of limit.
Ad filters are now checkboxes. Picking industry, budget, format, placement and campaign goal used to mean typing exact tokens like FINANCIAL_SERVICES from a list buried in the description. All 30 are now tickable, each labelled by what it does ("Industry: Financial services", "Budget: High spend"). Still one field, so the form stays short.
One click now works. The form arrives pre-filled with a real, working example - r/SaaS, top of this week, 50 results - so pressing Start with no editing returns data.
Sections consolidated from seven fragmented groups down to four: the four things that matter at the top, then job-specific options, filters, speed and cost, and AI analysis.
Date fields validate as you type. postedAfter and postedBefore accept a date (2026-03-01) or an age (7d, 24h, 3mo, 1y) and reject anything else with a clear message instead of being quietly ignored.
Over-limit message is now actionable. Asking for more than the ceiling explains that your results are complete up to that point, suggests splitting the work across runs, and states that the ceiling exists to protect the shared data source and prevent surprise bills - not because of any technical limit.
No field keys changed. Existing Saved Tasks, schedules and API integrations keep working. A field that used to accept a single value and is now multi-select also accepts the old bare string (and a comma-separated one), converted automatically.
AI enrichment, using your own LLM key.
Pick any combination under 🤖 AI enrichment and every post and comment row gains AI-derived fields:
- Sentiment - label, score from -1 to 1, and a one-word emotion
- Intent - question, complaint, recommendation, announcement, discussion, comparison, other
- Pain points - verbatim spans describing a problem, with a category and severity
- Feature requests - verbatim spans asking for something
- Buying intent - a post-level score and the signals behind it
You supply the key and pay your provider for tokens directly. This actor charges $0.002 per row for sentiment or intent and $0.004 for the extraction layers, covering the batching, prompting, validation and retries rather than the inference. Works with Anthropic or any OpenAI-compatible endpoint, including Groq, Together, OpenRouter and a local server via the base URL field.
Things worth knowing:
- Nothing runs without an explicit opt-in. No enrichment selected, or no key supplied, means no LLM call and no enrichment charge. The scrape is unaffected.
- Enrichment never fails a run. A missing key, an unparseable response or a provider outage degrades to "no enrichment" and the scrape completes normally.
- You are only billed for rows that came back enriched. A row carries
enrichedAt when the model actually returned data for it; rows without it cost nothing extra.
- Enrichment runs after filtering, so rows your filters drop never consume your tokens.
- Quotes are verified. Pain points and feature requests are checked against the source text and discarded if the model invented them.
- All layers run in one batched call per group of rows, to keep your token spend down.
- Reddit text is treated as untrusted data. Post bodies are passed inside delimiters with an explicit instruction to ignore any directives they contain, so a post cannot steer the model.
- Buying intent describes the post, not the person. Person-level lead scoring is out of scope by design - it conflicts with Reddit's user agreement and with this actor's own terms.
Read of the upstream API specification found nine places where this actor's assumptions did not match the real endpoints. All are fixed. Two of them were losing data silently.
Nested replies were being dropped entirely. The API nests replies as replies.items; the code checked for a plain array and for Reddit's native data.children. Neither matched, so every comment below top level was discarded and commentDepth did nothing. Comment threads now come back complete.
Comment threads now paginate. The endpoint returns one page plus a cursor and the actor only ever made a single call. Deep threads are followed to the cap, and a post row carries commentsReturned and commentsTruncated so a partial thread says so instead of just ending.
Subreddit search was broken three ways. It paginated with after where the endpoint expects cursor, so only the first page ever returned. Its posts use a slimmer shape (votes, created_at_iso, subreddit as an object) that the native transform mangled into zero scores and null dates. And the endpoint returns matching comments and media alongside posts on the same request, which were being thrown away - both are now returned, controlled by two new toggles.
Subreddit info was wrong on nearly every field. The response is flat, not nested, and uses different names. activeUserCount, createdAt, bannerUrl and rules were null or empty on every run. rules is a markdown string, not a structured list, and is now returned as rulesText.
moderators has been removed. The endpoint returns no moderator roster. It was documented as a field no competitor offers and was always empty. Removing a false claim.
Sort and timeframe values now match each endpoint. Each accepts a different enum: subreddit listings have no controversial and no hour; site-wide search uses comment_count, not comments, and has no hot. Presets are translated per mode to the nearest supported value instead of being sent verbatim and rejected.
New: video transcripts. 🎬 Video transcript pulls the plain-text caption track from Reddit video posts. Nothing else in this category returns transcripts. $0.008 per transcript. When Reddit publishes no captions the row still comes back with transcriptAvailable: false, so "no captions" is distinguishable from "failed".
New: caching. Pick a window under ⚡ Caching and a cached response inside it is served instead of a fresh scrape, at no upstream credit cost. Useful for daily monitoring where slightly stale data is fine.
New fields on posts and comments, all previously fetched and discarded: pollData (options and vote counts), controversiality, isEdited / editedAt, isOriginalContent, flairRich, removal, crossPostParent, awardCount, gilded, repliesTruncated, subredditSubscribers, distinguished, isArchived, isPinned.
Ads now return every carousel card. content[] was flattened to card one; multi-card creative was fetched and then discarded. New adCreatives[] keeps all of them, plus creativeType, allowComments and advertiserAvatarUrl.
Not possible, and dropped from the plan: author karma, account age and gold/mod status. There is no user endpoint in this API, so those fields cannot be delivered at all.
Filters. Six optional filters in a new collapsed section. Leave it empty and nothing changes; every filter narrows what reaches the dataset, so it also lowers what you pay - filtered rows are never written and never billed.
postedAfter / postedBefore - absolute (2026-03-01) or relative (7d, 24h, 3mo, 1y). This closes the last gap against the rest of the category. Runs client-side after each page, so it works on every mode and every sort order, unlike Reddit's own coarse relative windows.
includeNSFW - on by default; turn off to drop over-18 content.
minScore - skip posts and comments below a score.
minComments - skip posts with little discussion.
filterKeywords + filterKeywordMode - match on title and body, then keep only matches or drop them.
For ads, a date range matches the ad's flight window: an ad is kept when the period it ran overlaps your range.
Input goes from 7 fields to 13, still around half the category median of 26.
Breaking: comments are now one dataset row each.
Previously, post_comments billed one result per comment but delivered a single dataset row containing the whole tree nested inside it. A 200-comment thread charged for 200 results and showed you 1 row. That is fixed.
- Every billed result is now one row you can see.
post_comments emits one _recordType: "post" row plus one _recordType: "comment" row per comment, and bills exactly once per row.
- Comment rows carry
parentCommentId, depth and the new replyCount, so the thread is fully reconstructible. They also carry postTitle, postUrl and subreddit so a CSV export stands on its own without a join.
- The pre-assembled nested tree is still written to the key-value store under
thread-<postId>, at no extra charge, for anyone who wants it ready-nested.
If you parse output[0].comments[], switch to filtering rows on _recordType === "comment". The legacy post_with_comments shape is no longer emitted.
Repricing. Moved from a flat $4.00 / 1,000 results to per-event pricing, so commodity content is cheap and the Ads Library data is priced for what it is.
| Event | Was (flat) | Now |
|---|
| Reddit post | $0.004 | $0.0015 |
| Subreddit search match | $0.004 | $0.0015 |
| Reddit search result | $0.004 | $0.0015 |
| Reddit comment | $0.004 | $0.001 |
| Subreddit profile | $0.004 | $0.004 |
| Reddit ad (Ads Library) | $0.004 | $0.012 |
| Reddit ad - full detail | $0.004 | $0.025 |
Content scraping is now 62-75% cheaper. Ads Library data, which no other Reddit scraper on Apify returns, is priced accordingly. Still no run-start fee.
Dataset schema. Documented 12 fields that the actor emitted but never declared: commentId, parentCommentId, depth, replyCount, text, isOP, isDeleted, isRemoved, postTitle, postUrl, awards, description. The 💬 view now shows flat comment rows instead of a nested blob.
- Listing rewritten around the Reddit Ads Library, the one capability no other Reddit scraper on Apify offers.
- README restructured into question-shaped sections; Terms of Service collapsed so product content is above the fold. Added a mode-picker, a full input reference, integration examples for n8n / Make / Python / JavaScript, and an honest limitations section.
- Seven modes: subreddit posts, Reddit search, post comments, subreddit search, subreddit info, Ads Library search, ad details.
- Simplified input to four core fields with a universal
targets box and a combined sort + time preset.
0 = all convention on limit and commentDepth, with ceilings enforced in code rather than the schema so they cannot be bypassed via the API. Exceeding a ceiling warns in the log and on the run status instead of truncating silently.
- Five dataset views, key-value store snapshots, and an OpenAPI 3 description.
- Concurrent execution across subreddits, queries, post URLs and ad IDs; dataset writes batched per page.