<< All versions
Skill v1.0.0
currentAutomated scan100/100alinaqi/maggy/reddit-api
──Details
PublishedOctober 1, 2026 at 08:10 PM
Content Hashsha256:799411567a5a9520...
Git SHA72a456e6ccf0
──Files
Files (1 file, 14.0 KB)
SKILL.md14.0 KBactive
SKILL.md · 593 lines · 14.0 KB
version: "1.0.0" name: reddit-api description: Reddit API with PRAW (Python) and Snoowrap (Node.js) when-to-use: When building Reddit integrations or bots user-invocable: false effort: medium
Reddit API Skill
For integrating Reddit data into applications - fetching posts, comments, subreddits, and user data.
Sources: Reddit API Docs | OAuth2 Wiki | PRAW Docs
Setup
1. Create Reddit App
- Go to https://www.reddit.com/prefs/apps
- Click "Create App" or "Create Another App"
- Fill in:
- Name: Your app name
- App type:
script- For personal use / bots you controlweb app- For server-side apps with user authinstalled app- For mobile/desktop apps- Redirect URI:
http://localhost:8000/callback(for dev)
- Note your
client_id(under app name) andclient_secret
2. Environment Variables
bash
# .envREDDIT_CLIENT_ID=your_client_idREDDIT_CLIENT_SECRET=your_client_secretREDDIT_USER_AGENT=YourApp/1.0 by YourUsernameREDDIT_USERNAME=your_username # For script apps onlyREDDIT_PASSWORD=your_password # For script apps only
User-Agent Format: <platform>:<app_id>:<version> (by /u/<username>)
Rate Limits
| Tier | Limit | Notes | |
|---|---|---|---|
| OAuth authenticated | 100 QPM | Per OAuth client ID | |
| Non-authenticated | Blocked | Must use OAuth |
- Limits averaged over 10-minute window
- Include
User-Agentheader to avoid blocks - Respect
X-Ratelimit-*response headers
Python: PRAW (Recommended)
Installation
bash
pip install praw# oruv add praw
Script App (Personal Use / Bots)
python
import prawfrom pydantic_settings import BaseSettingsclass RedditSettings(BaseSettings):reddit_client_id: strreddit_client_secret: strreddit_user_agent: strreddit_username: strreddit_password: strclass Config:env_file = ".env"settings = RedditSettings()reddit = praw.Reddit(client_id=settings.reddit_client_id,client_secret=settings.reddit_client_secret,user_agent=settings.reddit_user_agent,username=settings.reddit_username,password=settings.reddit_password,)# Verify authenticationprint(f"Logged in as: {reddit.user.me()}")
Read-Only (No User Auth)
python
import prawreddit = praw.Reddit(client_id="your_client_id",client_secret="your_client_secret",user_agent="YourApp/1.0 by YourUsername",)# Read-only mode - can browse, can't post/votereddit.read_only = True
Common Operations
python
# Get subreddit postssubreddit = reddit.subreddit("python")# Hot postsfor post in subreddit.hot(limit=10):print(f"{post.title} - {post.score} upvotes")# New postsfor post in subreddit.new(limit=10):print(post.title)# Search postsfor post in subreddit.search("pydantic", limit=5):print(post.title)# Get specific postsubmission = reddit.submission(id="abc123")print(submission.title)print(submission.selftext)# Get commentssubmission.comments.replace_more(limit=0) # Flatten comment treefor comment in submission.comments.list():print(f"{comment.author}: {comment.body[:100]}")
Posting & Voting (Requires Auth)
python
# Submit text postsubreddit = reddit.subreddit("test")submission = subreddit.submit(title="Test Post",selftext="This is the body of my post.")# Submit link postsubmission = subreddit.submit(title="Check this out",url="https://example.com")# Votesubmission.upvote()submission.downvote()submission.clear_vote()# Commentsubmission.reply("Great post!")# Reply to commentcomment = reddit.comment(id="xyz789")comment.reply("I agree!")
Streaming (Real-time)
python
# Stream new postsfor post in reddit.subreddit("python").stream.submissions():print(f"New post: {post.title}")# Process post...# Stream new commentsfor comment in reddit.subreddit("python").stream.comments():print(f"New comment by {comment.author}: {comment.body[:50]}")
User Data
python
# Get user infouser = reddit.redditor("spez")print(f"Karma: {user.link_karma + user.comment_karma}")# User's postsfor post in user.submissions.new(limit=5):print(post.title)# User's commentsfor comment in user.comments.new(limit=5):print(comment.body[:100])
TypeScript / Node.js: Snoowrap
Installation
bash
npm install snoowrap# orpnpm add snoowrap
Setup
typescript
import Snoowrap from "snoowrap";const reddit = new Snoowrap({userAgent: "YourApp/1.0 by YourUsername",clientId: process.env.REDDIT_CLIENT_ID!,clientSecret: process.env.REDDIT_CLIENT_SECRET!,username: process.env.REDDIT_USERNAME!,password: process.env.REDDIT_PASSWORD!,});// Configure rate limitingreddit.config({requestDelay: 1000, // 1 second between requestscontinueAfterRatelimitError: true,});
Common Operations
typescript
// Get hot posts from subredditconst posts = await reddit.getSubreddit("typescript").getHot({ limit: 10 });posts.forEach((post) => {console.log(`${post.title} - ${post.score} upvotes`);});// Search postsconst results = await reddit.getSubreddit("programming").search({query: "typescript",sort: "relevance",time: "month",limit: 10,});// Get specific postconst submission = await reddit.getSubmission("abc123").fetch();console.log(submission.title);// Get commentsconst comments = await submission.comments.fetchAll();comments.forEach((comment) => {console.log(`${comment.author.name}: ${comment.body.slice(0, 100)}`);});
Posting
typescript
// Submit text postconst post = await reddit.getSubreddit("test").submitSelfpost({title: "Test Post",text: "This is the body.",});// Submit linkconst linkPost = await reddit.getSubreddit("test").submitLink({title: "Check this out",url: "https://example.com",});// Vote and commentawait post.upvote();await post.reply("Great post!");
Direct API (No Library)
Python with httpx
python
import httpximport base64from pydantic import BaseModelclass RedditClient:def __init__(self, client_id: str, client_secret: str, user_agent: str):self.client_id = client_idself.client_secret = client_secretself.user_agent = user_agentself.access_token: str | None = Noneself.client = httpx.AsyncClient()async def authenticate(self) -> None:"""Get application-only OAuth token."""auth = base64.b64encode(f"{self.client_id}:{self.client_secret}".encode()).decode()response = await self.client.post("https://www.reddit.com/api/v1/access_token",headers={"Authorization": f"Basic {auth}","User-Agent": self.user_agent,},data={"grant_type": "client_credentials",},)response.raise_for_status()self.access_token = response.json()["access_token"]async def get_posts(self, subreddit: str, sort: str = "hot", limit: int = 10) -> list[dict]:"""Get posts from a subreddit."""if not self.access_token:await self.authenticate()response = await self.client.get(f"https://oauth.reddit.com/r/{subreddit}/{sort}",headers={"Authorization": f"Bearer {self.access_token}","User-Agent": self.user_agent,},params={"limit": limit},)response.raise_for_status()return [post["data"] for post in response.json()["data"]["children"]]async def close(self) -> None:await self.client.aclose()# Usageasync def main():client = RedditClient(client_id="your_id",client_secret="your_secret",user_agent="YourApp/1.0",)try:posts = await client.get_posts("python", limit=5)for post in posts:print(f"{post['title']} - {post['score']} upvotes")finally:await client.close()
TypeScript with fetch
typescript
interface RedditPost {title: string;score: number;url: string;selftext: string;author: string;created_utc: number;}class RedditClient {private accessToken: string | null = null;constructor(private clientId: string,private clientSecret: string,private userAgent: string) {}async authenticate(): Promise<void> {const auth = Buffer.from(`${this.clientId}:${this.clientSecret}`).toString("base64");const response = await fetch("https://www.reddit.com/api/v1/access_token", {method: "POST",headers: {Authorization: `Basic ${auth}`,"User-Agent": this.userAgent,"Content-Type": "application/x-www-form-urlencoded",},body: "grant_type=client_credentials",});const data = await response.json();this.accessToken = data.access_token;}async getPosts(subreddit: string, sort = "hot", limit = 10): Promise<RedditPost[]> {if (!this.accessToken) await this.authenticate();const response = await fetch(`https://oauth.reddit.com/r/${subreddit}/${sort}?limit=${limit}`,{headers: {Authorization: `Bearer ${this.accessToken}`,"User-Agent": this.userAgent,},});const data = await response.json();return data.data.children.map((child: any) => child.data);}}
OAuth2 Web Flow (User Authorization)
For apps where users log in with their Reddit account:
python
from fastapi import FastAPI, Requestfrom fastapi.responses import RedirectResponseimport httpximport secretsapp = FastAPI()state_store: dict[str, bool] = {}REDDIT_CLIENT_ID = "your_client_id"REDDIT_CLIENT_SECRET = "your_client_secret"REDIRECT_URI = "http://localhost:8000/callback"@app.get("/login")async def login():state = secrets.token_urlsafe(16)state_store[state] = Trueauth_url = (f"https://www.reddit.com/api/v1/authorize"f"?client_id={REDDIT_CLIENT_ID}"f"&response_type=code"f"&state={state}"f"&redirect_uri={REDIRECT_URI}"f"&duration=permanent"f"&scope=identity read submit vote")return RedirectResponse(auth_url)@app.get("/callback")async def callback(code: str, state: str):if state not in state_store:return {"error": "Invalid state"}del state_store[state]# Exchange code for tokenasync with httpx.AsyncClient() as client:response = await client.post("https://www.reddit.com/api/v1/access_token",auth=(REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET),data={"grant_type": "authorization_code","code": code,"redirect_uri": REDIRECT_URI,},headers={"User-Agent": "YourApp/1.0"},)tokens = response.json()# Store tokens securely, associate with user sessionreturn {"access_token": tokens["access_token"][:10] + "..."}
Available Scopes
| Scope | Description | |
|---|---|---|
identity | Access username and signup date | |
read | Access posts and comments | |
submit | Submit links and comments | |
vote | Upvote/downvote content | |
edit | Edit posts and comments | |
history | Access voting history | |
subscribe | Manage subreddit subscriptions | |
mysubreddits | Access subscribed subreddits | |
privatemessages | Access private messages | |
save | Save/unsave content |
Full list: https://www.reddit.com/api/v1/scopes
Project Structure
project/├── src/│ ├── reddit/│ │ ├── __init__.py│ │ ├── client.py # Reddit client wrapper│ │ ├── models.py # Pydantic models for posts/comments│ │ └── scraper.py # Data collection logic│ └── main.py├── .env└── pyproject.toml
Pydantic Models
python
from pydantic import BaseModelfrom datetime import datetimeclass RedditPost(BaseModel):id: strtitle: strauthor: strsubreddit: strscore: intupvote_ratio: floaturl: strselftext: strcreated_utc: datetimenum_comments: intis_self: bool@classmethoddef from_praw(cls, submission) -> "RedditPost":return cls(id=submission.id,title=submission.title,author=str(submission.author),subreddit=submission.subreddit.display_name,score=submission.score,upvote_ratio=submission.upvote_ratio,url=submission.url,selftext=submission.selftext,created_utc=datetime.fromtimestamp(submission.created_utc),num_comments=submission.num_comments,is_self=submission.is_self,)class RedditComment(BaseModel):id: strauthor: strbody: strscore: intcreated_utc: datetimeparent_id: stris_submitter: bool
Anti-Patterns
- No User-Agent - Reddit blocks requests without proper User-Agent
- Ignoring rate limits - Respect 100 QPM, check
X-Ratelimit-*headers - Storing credentials in code - Use environment variables
- Not handling `MoreComments` - Use
replace_more()in PRAW - Polling instead of streaming - Use
.streamfor real-time data - No error handling - Handle 429 (rate limit), 403 (forbidden), 404 (not found)
Quick Reference
bash
# PRAW installationpip install praw# Snoowrap installationnpm install snoowrap# Test authenticationpython -c "import praw; r = praw.Reddit(...); print(r.user.me())"
Endpoints
| Operation | Endpoint | |
|---|---|---|
| Auth token | POST https://www.reddit.com/api/v1/access_token | |
| API requests | https://oauth.reddit.com/... | |
| Subreddit posts | GET /r/{subreddit}/{sort} | |
| Submission | GET /comments/{id} | |
| User info | GET /user/{username}/about | |
| Submit post | POST /api/submit | |
| Vote | POST /api/vote |