Free Reddit API. No API keys, no OAuth registration, no monthly fees.
All you need is Chrome with Reddit logged in, and Chrome DevTools Protocol enabled.
This MCP server talks to Reddit through your browser session. When you're logged into Reddit in Chrome, your browser already has all the authentication it needs. This server simply executes fetch() calls in your Reddit tab's context, using the same cookies your browser uses.
AI Assistant → this MCP server → Chrome DevTools Protocol → your Reddit tab → Reddit's internal API
Reddit's internal API (the same endpoints their website uses) gives you everything: read posts, write comments, vote, search, send messages, manage subscriptions. All free, all through your existing session.
Use the repo script (it verifies the port for you):
./scripts/chrome-bridge.sh
# Already have Chrome open? Close it first, or isolate the profile:
./scripts/chrome-bridge.sh --profile-dir /tmp/chrome-bridgeManual equivalent:
# macOS
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
# Linux
google-chrome --remote-debugging-port=9222
# Windows
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222Cheap probe before any tool call (milliseconds, saves a failed MCP round-trip):
curl -sf -m 3 http://localhost:9222/json/versionThen call reddit_ensure_session first. It returns bridge_ready plus per-layer state (cdp_reachable, reddit_tab_found, logged_in). Call other reddit_* tools only when bridge_ready is true.
Listing tools return a compact projection by default (sub, title, author, score, comments, body snippet). That cuts the payload roughly 40x versus raw Reddit JSON. Pass compact: false only when you need the full payload (media metadata, awards, facets).
Present reddit picks as full-permalink markdown links. Compact output always carries link, so URLs arrive with no extra fetch round.
Rank topical searches by relevance, not score. sort: "top" ranks by points and surfaces viral threads over matching ones. Prefer sort: "relevance" when the question is topical, sort: "top" when it is best-of.
Just open reddit.com and log in normally.
{
"mcpServers": {
"reddit": {
"command": "node",
"args": ["/path/to/reddit-unofficial-api/build/index.js"],
"env": {
"CHROME_CDP_URL": "http://localhost:9222"
}
}
}
}cd reddit-unofficial-api
npm install
npm run build| Tool | What it does |
|---|---|
reddit_me |
Get current logged-in user info |
reddit_get_post |
Get a post and its comments |
reddit_get_posts |
Get several posts + top comments in one paced call (max 25) |
reddit_get_comments |
Get all comments as a flat list |
reddit_get_user |
Look up any user's profile, posts, comments, or your private tabs |
reddit_get_subreddit |
Get subreddit info, rules, or browse posts |
reddit_search |
Search within a subreddit (subreddit required) |
reddit_get_inbox |
Read your messages, replies, and mentions |
reddit_get_home_feed |
Get your personalized home feed (hot/new/top/rising) |
reddit_get_subscriptions |
List the subreddits you subscribe to |
reddit_get_multis |
List your multis (custom feeds) and their member subreddits |
reddit_get_multi_feed |
Read posts from one of your multis by name |
| Tool | What it does |
|---|---|
reddit_comment |
Reply to any post or comment |
reddit_submit |
Create a new post (text or link) |
reddit_vote |
Upvote, downvote, or unvote |
reddit_save |
Save/unsave posts or comments |
reddit_hide |
Hide/unhide posts (reversible) |
reddit_send_message |
Send a private message |
reddit_mark_notifications_as_read |
Mark specified notifications as read |
reddit_edit |
Edit your own content |
reddit_delete |
Delete your own content |
reddit_subscribe |
Join or leave a subreddit |
reddit_multi_create |
Create a multi (custom feed) |
reddit_multi_update |
Add/remove subreddits in one of your multis |
reddit_multi_delete |
Delete one of your multis |
| Tool | What it does |
|---|---|
reddit_ensure_session |
Verify everything is connected and you're logged in |
Check bridge-ready: CDP answers, reddit.com tab exists, user is logged in. Probe this before any other reddit_* tool.
Arguments: none
Returns: Bridge state object with bridge_ready, cdp_reachable, chrome_version, reddit_tab_found, logged_in, username, bridge_version, build_sha, cdp_url.
Get current logged-in Reddit user info (karma, gold status, preferences, feature flags).
Arguments: none
Returns: Full user profile JSON.
Fetch a post by URL or ID, with its comment tree.
Arguments:
url(string, required): Reddit post URL or post ID (e.g.1sdv3lo)sort(enum, default"top"): Comment sort —top,new,best,controversial,old,qalimit(number, default100): Max comments to returncompact(boolean, defaulttrue): Compact projection (sub, title, author, score, comments, body snippet). False returns raw payload.
Returns: Object with post and comments arrays. Compact mode includes link (full permalink) on every item.
One call for many posts, paced server-side (2s gaps). Use this instead of N parallel reddit_get_post calls when curating a feed.
Arguments:
ids(string[], required, max25): Post URLs or IDs, returned in input ordersort(enum, default"top"): Comment sort —top,new,best,controversial,old,qalimit(number, default10, max50): Max comments per post (0= post only)compact(boolean, defaulttrue): Same projection asreddit_get_post
Returns: Array of {id, post, comments} in input order; per-item failures come back as {id, error} without failing the batch.
Get all comments for a post as a flat list with author, body, score, parent info, and depth.
Arguments:
url(string, required): Reddit post URL or post IDsort(enum, default"top"):top,new,best,controversial,old,qa
Returns: Flat array of comment objects with id, author, body, score, parent_id, depth, created_utc.
Get any user's profile, posts, comments, or your own private tabs (upvoted, downvoted, saved, hidden, controversial, trophies, friends, moderator).
Arguments:
username(string, required): Reddit username, or"me"for the logged-in accounttype(enum, default"about"):about— full profile (karma, avatar, bio, etc.)overview— mixed posts and commentssubmitted— posts onlycomments— comments onlycontroversial— your controversial posts/commentsupvoted— things you upvoted (private, requiresme)downvoted— things you downvoted (private, requiresme)saved— saved posts/comments (private, requiresme)hidden— hidden posts (private, requiresme)trophies— your trophy case (private, requiresme)friends— your friends list (private, requiresme)moderator— subreddits you moderate (private, requiresme)
limit(number, default25): Max items (listing types only)compact(boolean, defaulttrue): Compact projection. False returns raw payload.
Notes:
aboutreturns the full profile object (not compacted)trophies,friends,moderatorhave dedicated compact projectionsupvoted,downvoted,saved,hidden,controversialare private — only work for your own account (me)- Compact output always includes
link(full permalink)
Get subreddit metadata, rules, or browse its posts.
Arguments:
subreddit(string, required): Subreddit name withoutr/type(enum, default"hot"):about,rules,hot,new,top,risinglimit(number, default25): Max poststime(enum, default"day"): Time filter fortop/controversial—hour,day,week,month,year,allcompact(boolean, defaulttrue): Compact projection. False returns raw payload.
Returns: Subreddit object (for about/rules) or listing of posts (for feed types). Compact includes link on every post.
Search posts within a subreddit. Global search is not supported: unscoped search returns junk (CODING_STANDARDS §8.3), and the tool requires subreddit.
Arguments:
query(string, required): Search querysubreddit(string, required): Subreddit to search (withoutr/)sort(enum, default"relevance"):relevance,hot,top,new,commentstime(enum, default"all"):hour,day,week,month,year,alllimit(number, default25): Max resultscompact(boolean, defaulttrue): Compact projection. False returns raw payload.
Best practice: Use sort: "relevance" for topical questions, sort: "top" for best-of.
Read your Reddit messages: inbox, unread, sent, comment replies, post replies, or username mentions.
Arguments:
type(enum, default"unread"):inbox— all messagesunread— unread onlysent— sent messagescomments— replies to your commentsselfreply— replies to your postsmentions— username mentions
limit(number, default25): Max itemscompact(boolean, defaulttrue): Compact projection. False returns raw payload.
Compact output: Includes subject field for message-type items (comments, selfreply, mentions use title instead).
Get the logged-in account's home feed: posts from your subscriptions, exactly as reddit.com shows them.
Arguments:
sort(enum, default"hot"):hot,new,top,risinglimit(number, default15): Max posts (1-50). The server pages through the listing (2s between pages) up to this cap.time(enum, optional): Time filter —hour,day,week,month,year,all. Only valid whensortistop(defaults todaythere); passing it with any other sort returns an error.after_id(string, optional): Fullname cursor (t3_...) to page from — for reading past the first page.
Compact output: Standard item projection (sub, title, author, score, comments, link, body snippet).
List all subreddits the logged-in account subscribes to. Paginated with pacing (max 4 pages / 100 items, 2s between pages to avoid 429).
Arguments:
limit(number, default100): Max subreddits to return (capped at 100)compact(boolean, defaulttrue): Compact projection. False returns the first page's raw Reddit payload.
Compact fields per subreddit: kind, name, prefixed (e.g. r/opencode), title, subscribers, over18, link.
List the logged-in account's multis (custom feeds): display name, path, visibility, member subreddits.
Arguments:
compact(boolean, defaulttrue): Compact projection. False returns raw payload.
Compact fields per multi: kind, name, display_name, path, link, visibility (private/public), subCount, subs (array of subreddit names).
Read posts from one of your multis by name. Resolves the name against your multis (case-insensitive). Paginated with pacing (max 4 pages / 100 items, 2s between pages).
Arguments:
multi(string, required): Multi name (e.g."favoritos") or full path (/user/<name>/m/<multi>). Resolved against/api/multi/mine.json.limit(number, default25): Max posts (capped at 100)compact(boolean, defaulttrue): Compact projection. False returns first page's raw Reddit payload.
Compact output: Standard item projection (sub, title, author, score, comments, link, body snippet).
Arguments:
thing_id(string, required): Fullname of parent (t1_for comment,t3_for post)text(string, required): Comment text (markdown supported)
Returns: { success, commentId, errors }
Arguments:
subreddit(string, required): Subreddit name withoutr/title(string, required): Post titlekind(enum, required):self(text) orlinktext(string, optional): Post body text (for self posts)url(string, optional): URL (for link posts)flair_id(string, optional): Flair template IDflair_text(string, optional): Flair textnsfw(boolean, defaultfalse)spoiler(boolean, defaultfalse)
Returns: Reddit submit response JSON.
Arguments:
thing_id(string, required): Fullname (t1_ort3_)direction(enum, required):up,down,unvote
Returns: { success: true, direction }
Arguments:
thing_id(string, required): Fullname (t1_ort3_)unsave(boolean, defaultfalse): Set true to unsave
Returns: { success: true, action: "saved" | "unsaved" }
Arguments:
to(string, required): Username to send tosubject(string, required): Message subjecttext(string, required): Message body
Returns: Reddit compose response JSON.
Arguments:
notification_ids(string[], required): List of notification fullnames (t4_...) to mark as read. IDs not matchingt4_...are rejected before any write.
Returns: { success: true, count: N } on success; { success: false, count: 0, error, status? } when the write fails — a failed POST never reads as success.
Arguments:
thing_id(string, required): Fullname of your post/comment to edittext(string, required): New text content
Returns: Reddit edit response JSON.
Arguments:
thing_id(string, required): Fullname of your post/comment to delete
Returns: { success: true, deleted: thing_id }
Arguments:
subreddit(string, required): Subreddit nameunsubscribe(boolean, defaultfalse): Set true to unsubscribe
Returns: { success: true, action: "sub" | "unsub", subreddit }
Hidden posts disappear from your feeds. Fully reversible.
Arguments:
thing_id(string, required): Post fullname (t3_)unhide(boolean, defaultfalse): Set true to unhide
Returns: { success: true, action: "hidden" | "unhidden", thing_id }
Arguments:
name(string, required): Multi name — lowercase letters, numbers, underscores only (no hyphens or spaces)subreddits(string[], required): Subreddit names (withoutr/)description(string, optional): Multi descriptionvisibility(enum, default"private"):private,public,hidden
Returns: { success: true, name, subCount }
Add or remove member subreddits, or change the description.
Arguments:
multi(string, required): Multi name (e.g.favoritos)add_subs(string[], optional): Subreddit names to addremove_subs(string[], optional): Subreddit names to removedescription(string, optional): New description
Returns: { success: true, multi, before, after, added, removed }
Cannot be undone.
Arguments:
multi(string, required): Multi name to delete
Returns: { success: true, deleted }
Block user (/api/block), friend (/api/friend), and report (/api/report) are legacy endpoints that modern Reddit has silently retired:
/api/blockreturns 404 (route removed)/api/friend type=friendandtype=enemyreturn 200 with no errors — but the friends and blocked lists never change/api/reportaccepts a nonexistent target with 200 and no errors — same silent no-op signature
A tool that reports success while doing nothing is worse than no tool, so none of the three ship. Use the Reddit UI for blocking, following, and reporting until a working replacement endpoint appears.
All listing tools (get_post, get_user, get_subreddit, search, get_inbox, get_home_feed, get_subscriptions, get_multis, get_multi_feed) return a compact projection by default. This cuts the payload ~40x versus raw Reddit JSON.
Standard item fields (posts/comments):
kind— Reddit kind (t1=comment,t3=post,t5=subreddit)id— Reddit base36 IDlink— Full permalink (https://www.reddit.com/...)sub— Subreddit nametitle— Post title (truncated to 140 chars)subject— Message subject (for inbox items)author— Usernamescore— Upvotes minus downvotescomments— Number of commentsbody— Body text (truncated to 280 chars)url— External URL if different from permalinkmedia— What a click opens:gallery|video|image|text|link(structural, safe to branch on)preview— Selftext snippet (text posts, 200 chars) or gallery count — absent when Reddit sends no source textthumb— Thumbnail URL, only when Reddit sends an http thumbnail
Subreddit fields (get_subscriptions):
kind—t5name— Internal nameprefixed—r/nameformattitle— Subreddit titlesubscribers— Subscriber countover18— NSFW flaglink—https://www.reddit.com/r/name/
Multi fields (get_multis):
kind—LabeledMultiname— Internal namedisplay_name— Human-readable namepath— Full path (/user/name/m/multi)link— Full URLvisibility—privateorpublicsubCount— Number of member subredditssubs— Array of member subreddit names
Trophy fields (get_user type=trophies):
kind— Trophy kindname— Trophy namedescription— Descriptionicon— Icon URL (70px or 40px)
Friend fields (get_user type=friends):
kind— User kindname— Usernameid— User IDdate— Friend since timestamp
Moderator subreddit fields (get_user type=moderator):
kind—t5name— Subreddit nameprefixed—r/namesubscribers— Subscriber countover18— NSFW flaglink— Full URL
- Write operations: 1.5s minimum between calls (enforced server-side)
- Paginated reads: 2s between pages (enforced server-side for subscriptions, multi feeds)
- Reddit's native limit: ~100 req/min authenticated — the pacing avoids tripping it
- Read operations: No artificial delay, but don't fire parallel calls on a cold bridge
Listing tools cache GET responses in memory (PRD 4 stage 1: rate-limit/cache check):
| Category | TTL | Tools |
|---|---|---|
| Post | 300s | reddit_get_post, reddit_get_posts, reddit_get_comments |
| Feed | 120s | reddit_get_home_feed, reddit_get_user, reddit_get_subreddit, reddit_search, reddit_get_subscriptions, reddit_get_multis, reddit_get_multi_feed |
| Inbox | 30s | reddit_get_inbox |
- Session probes (
reddit_me,reddit_ensure_session) are never cached - Any write operation (vote, comment, hide, save, subscribe, multi create/update/delete, etc.) clears the whole cache
- Error responses are never cached
- TTLs are env-overridable:
CACHE_TTL_SECONDS(feed, 120),CACHE_TTL_INBOX_SECONDS(30),CACHE_TTL_POST_SECONDS(300)
- Monitor your posts: Check for new comments needing replies, categorize them (bug report, question, feature request, positive feedback), draft replies, approve, post
- Batch reply: Reply to 10+ comments in one go with personalized responses, auto-verified to go to the right person
- Update your posts: Edit post body to add changelogs, new links, corrections
- Search Reddit: Find all posts mentioning your product, competitor, or topic across any subreddit
- User research: Look up anyone's post history, comment history
- Subreddit discovery: Find relevant subreddits for your niche, check rules before posting
- Cross-post to multiple subreddits: Draft once, submit to r/LocalLLaMA, r/androiddev, r/machinelearning, etc.
- Track engagement: Check which of your posts/comments are getting upvoted or replied to
- Save interesting threads: Bookmark posts and comments for later reference
- Read DMs: Check if anyone messaged you about your project
- Send DMs: Reach out to users who want to contribute or reported bugs
- Read replies/mentions:
comments,selfreply,mentionstypes catch all engagement
- Upvote helpful feedback: Upvote users who gave useful bug reports or feature suggestions
- Subscribe to subreddits: Join relevant communities from your AI assistant
- Manage multis: List your custom feeds, read their combined posts
- Topic deep-dive: "Research what Reddit thinks about on-device LLM apps" → searches multiple subreddits, reads top posts and comment threads, summarizes sentiment and common complaints
- Competitor analysis: "What are people saying about Tool A vs Tool B" → finds all relevant threads, extracts comparisons, user experiences, pros/cons
- Market validation: "Is there demand for X" → searches across subreddits, analyzes upvotes and engagement, identifies audience and pain points
- Trend tracking: "What topics are trending this week on r/LocalLLaMA" → fetches top/rising posts, identifies emerging themes
Everything runs through your existing browser session. Zero cost, no API keys, no rate limit surprises.
Reddit killed free API access in 2023. The official API now requires app registration, OAuth flows, and has strict rate limits. If you're building something for personal use with your own account, jumping through those hoops makes no sense.
This approach uses the exact same endpoints Reddit's own website uses. Your browser is already authenticated. We just let your AI assistant use that same session.
This tool uses your real Reddit account. Reddit can't tell the difference between you typing and this tool typing, because it's the same browser session. That's the whole point. But it also means you need to behave like a human.
Why the risk is low:
- Requests come from your normal browser with your normal cookies. To Reddit's servers, it looks identical to you clicking buttons manually.
- The server adds delays between write operations (1.5s minimum). You're not hammering their API.
- Content is genuine (you write and approve the replies), not auto-generated spam.
Rules to follow:
- Don't batch reply too aggressively. 10-15 replies in one session is fine. 50 replies in 10 minutes is not. Spread it out across a few hours if you have a lot to respond to.
- Vary your reply content. If every reply has the exact same structure, links, and call-to-action, Reddit's spam filter will notice. Make each reply address the specific person's point.
- Mix in normal behavior. Browse, upvote a few things, read some posts. Don't make your entire session activity look like a bot replying to everything.
- Don't use this for spam, vote manipulation, or astroturfing. Obviously. This is for managing your own community and doing research, not gaming Reddit.
- Respect subreddit rules. Some subs don't allow self-promotion. Check before cross-posting.
What happens if Reddit flags you:
- Most likely: temporary rate limit (can't post for a few hours)
- Less likely: shadowban (your replies only visible to you, check at r/ShadowBan)
- Very unlikely: account suspension (only for obvious spam or manipulation)
Recovery:
- If rate limited, just wait. It resets.
- If shadowbanned, appeal at reddit.com/appeal. Usually reversed if your content is genuine.
- Best prevention: keep it natural. If a human wouldn't post 30 comments in 5 minutes, don't do it with this tool either.
- Needs Chrome running with DevTools Protocol (port 9222)
- Needs you to be logged into Reddit in that Chrome instance
- One Reddit account at a time (whichever is logged in)
- Rate limits are undocumented but generous for normal use
- Not suitable for high-volume scraping or bot armies (and you shouldn't do that anyway)
- All text fields in compact projections pass through
sanitizeTextperdocs/SANITIZATION.md. The pipeline strips ANSI, zero-width, and control chars, escapes markdown, and truncates with an ellipsis.
"CDP-unreachable" — Chrome isn't running with --remote-debugging-port=9222. Run scripts/chrome-bridge.sh.
"NO-REDDIT-TAB" — No reddit.com tab open in the debug Chrome window. Open reddit.com.
"NOT-LOGGED-IN" — Reddit tab found but not logged in. Log in to Reddit in that window.
"STALE: live sha=..." — The MCP host process is running an old build. Restart your MCP client (new session) after npm run build.
"429 Too Many Requests" — You're hitting Reddit's rate limit. Wait a minute. The server paces paginated reads automatically. This usually means you fired too many parallel calls.
MIT