Fixes every tool returning Bootstrap could not obtain session cookies.
- Replaced
undici with impit as the HTTP client. Reddit now fingerprints the
caller: from the same residential IP, curl gets 200 and undici gets 403 on
every attempt, so the cookie bootstrap could never succeed. impit
impersonates a real Chrome signature and the bootstrap works again.
- A
200 response carrying the "Welcome to Reddit" HTML interstitial is now
treated as a dead session — the cookies are dropped and the session rotated,
instead of spending the remaining retries on a session Reddit already refused.
- Redirects are no longer followed: a
302 to /login means the session was
refused, and is now retried on a fresh sticky IP.
Initial public release.
- Apify Standby MCP server exposing seven Reddit tools over Streamable HTTP (
/mcp).
- JSON-RPC 2.0, protocol version
2025-06-18.
- Tools:
search_reddit, get_subreddit_posts, get_post_with_comments, get_user_posts, get_user_comments, get_subreddit_info, get_trending_subreddits.
- Residential proxy (Apify Proxy
RESIDENTIAL group) with fallback to default Apify Proxy.
- Puppeteer-extra + stealth against
old.reddit.com JSON endpoints; images/fonts/CSS/media blocked via request interception.
- Pay-per-event pricing:
$0.02 per successful tool call. initialize, tools/list, ping and notifications are free.
GET / returns a server manifest listing the tools (useful for debugging MCP client integrations).
Rebuilt on Reddit's public Atom feeds. Same 7 tools, same names, same inputs.
Reddit closed anonymous access to *.json on every host and restricted new Data API
registrations to moderation use cases. The impit + sticky-residential + cookie bootstrap
that worked in August now fails on every attempt: there is no challenge to pass.
lib/reddit-fetch.js rewritten: fetches /.rss feeds, no cookies, no bootstrap, no
sticky sessions. 429 is treated as a pace limit with exponential backoff, not a block.
- Residential proxy demoted to fallback. The feeds answer 200 from datacenter IPs;
residential was ~80% of the cost and bought nothing.
- New
lib/atom.js: minimal Atom parser shared by the tools.
search_reddit now passes type=link. Without it Reddit's search feed also returns
communities (t5_), which arrived as posts with no author and the subreddit name in
the title field.
- Vote data (
score, upvoteRatio, numComments) and moderation flags are null, never
0, so a caller can tell "unknown" from "zero". Every tool description says so, since
an MCP client picks tools by reading them.
get_subreddit_info now serves what the feed header carries (name, title, description,
icon, URL, last activity); subscriber and active-user counts are null — Reddit does
not publish them any more.
get_post_with_comments requires subreddit (the comment feed is per-subreddit) and
reports commentSortHonoured: false, since the feed serves one fixed order.
Hotfix. Two production bugs, fixed on top of 2.0.2 and nothing else: no HTML route,
no session pool, none of the 2.1 work. Behaviour is identical to 2.0.2 in every
other respect.
- 🔴 A 429 no longer kills the whole tool call. A rate limit on the feed route
threw a bare error that
runTool turned into isError: true; three calls died
that way in a single validation pass. Now Retry-After is honoured when Reddit
sends one, the fallback ladder carries ±30 % jitter so parallel containers stop
retrying in lockstep, and rate-limit retries get their own budget instead of
eating the attempts reserved for transport errors. Only once all of that is spent
does it throw, and what it throws says it is a pace limit worth retrying rather
than a generic failure.
- 🔴 Partial results are kept instead of discarded. If a rate limit lands part
way through a paginated feed, the pages already fetched are returned with
partial: true and a notice telling the caller to retry for the rest. For an
interactive MCP client that is worth far more than an exception that throws away
work already paid for. Only a failure on the first page still raises, because
then there is genuinely nothing to hand back.
- 🔴
get_user_comments returned created: null on every comment.
/user/<name>/comments/.rss entries carry <updated> and no <published>,
and the transform read only published, so the field was null on 100 % of that
tool's output. It now falls back to updated, for posts as well as comments.
edited deliberately still reads the raw pair, so a missing published cannot be
misreported as an edit.
- Adds a test suite (20 checks) that did not exist on this line, including a live
one that stands up a local server answering a real 429 over a real socket.