Reddit API in Python: The Complete No-PRAW Tutorial
Use the Reddit API in Python without PRAW — plain HTTP with requests or httpx. Code examples for posts, comments, search, votes, and DMs from $0.002 per call.

Most Python tutorials on Reddit start the same way: install PRAW, register a Reddit developer app, copy a client ID and secret into your code, then bolt on an OAuth flow. That works fine for hobby projects. It breaks at the production line.
Reddit's free OAuth tier explicitly forbids commercial use, throttles you to 100 queries per minute, and caps you at 10,000 calls per month. Going commercial means signing the Standard tier — $12,000 per year minimum plus roughly $0.024 per call at scale. Most teams hit one of those walls long before they ship.
This tutorial does the same thing the other guides do — fetch posts, walk comment trees, search, comment, vote, send DMs — but with plain requests and one bearer token. No developer app. No OAuth dance. No 10K monthly cap. Code is copy-paste runnable at $0.002 per read call with $0.50 in free credits on every new account.
Why not just use PRAW?
PRAW (the Python Reddit API Wrapper) is well-maintained and handles a real problem: Reddit's API is verbose, the auth flow is fiddly, and the rate-limit headers are easy to misread. PRAW papers all of that over with import praw.
What PRAW doesn't paper over is the layer underneath it — Reddit's API itself. PRAW sits on Reddit's OAuth tier, which means:
- Free tier: 100 QPM with OAuth · 10K monthly cap · no commercial use allowed
- Standard tier: $12K/year minimum · 100 RPM at base · scales with payment tier
- Commercial calls beyond Standard: roughly $0.24 per 1,000 calls
- App-review queue: 2–4 weeks for write scopes (post, vote, DM)
If you're building anything that touches money — a SaaS, an internal tool with paying users, an agency dashboard — the free tier is off the table by Reddit's own terms. And Standard at $12K/year is steep for any project that hasn't validated revenue yet.
The alternative is to skip Reddit's OAuth layer entirely and call a third-party Reddit API. That's what this tutorial covers. RedditAPI exposes the same endpoints PRAW would call, but with one bearer token, pay-per-call pricing from $0.002, no developer-app review, and no monthly cap.
Quick start: Reddit API in Python in 5 lines
You don't need a wrapper, an SDK, or an async runtime. Plain requests works:
import os
import requests
API_KEY = os.environ["REDDITAPI_KEY"]
BASE = "https://api.redditapis.com"
response = requests.get(
f"{BASE}/api/reddit/posts",
params={"sub": "python", "sort": "top", "t": "week"},
headers={"Authorization": f"Bearer {API_KEY}"},
)
posts = response.json()
print(f"Fetched {len(posts.get('data', []))} top posts from r/python this week")
Five lines of actual work. No client ID, no client secret, no OAuth refresh tokens. Your REDDITAPI_KEY is the only credential — generate one at signup and pass it as a bearer token on every request.
If you prefer httpx for async or HTTP/2 support, swap the import — the request shape is identical:
import os
import httpx
API_KEY = os.environ["REDDITAPI_KEY"]
BASE = "https://api.redditapis.com"
async def fetch_top():
async with httpx.AsyncClient() as client:
r = await client.get(
f"{BASE}/api/reddit/posts",
params={"sub": "python", "sort": "top", "t": "week"},
headers={"Authorization": f"Bearer {API_KEY}"},
)
return r.json()
Same for aiohttp, urllib3, or whatever HTTP client your codebase already uses. The Reddit API in Python doesn't need a dedicated wrapper — it's just JSON over HTTPS.
Start building with RedditAPI
Reads $0.002, votes $0.005, writes $0.012, DMs $0.025. $0.50 free credits.
Reddit API Python examples
These are the operations every Reddit-API project ends up doing. Each is one HTTP call, returning structured JSON.
Fetch posts from a subreddit
def get_subreddit_posts(sub: str, sort: str = "hot", limit: int = 25):
r = requests.get(
f"{BASE}/api/reddit/posts",
params={"sub": sub, "sort": sort, "limit": limit},
headers={"Authorization": f"Bearer {API_KEY}"},
)
r.raise_for_status()
return r.json()["data"]
posts = get_subreddit_posts("MachineLearning", sort="top")
for p in posts:
print(f"{p['score']:>6} {p['title']}")
sort accepts hot, new, top, rising, controversial. For top and controversial, pass t (timeframe) as hour, day, week, month, year, or all.
Walk a comment tree
def get_comments(post_id: str):
r = requests.get(
f"{BASE}/api/reddit/comments",
params={"post_id": post_id},
headers={"Authorization": f"Bearer {API_KEY}"},
)
return r.json()
tree = get_comments("1abc123")
def walk(comments, depth=0):
for c in comments:
print(f"{' ' * depth}{c['author']}: {c['body'][:80]}")
walk(c.get("replies", []), depth + 1)
walk(tree["data"])
The endpoint returns the full nested tree in one response — no pagination required for typical threads.
Search across subreddits
def search_reddit(query: str, sort: str = "relevance"):
r = requests.get(
f"{BASE}/api/reddit/search",
params={"q": query, "sort": sort, "limit": 100},
headers={"Authorization": f"Bearer {API_KEY}"},
)
return r.json()["data"]
mentions = search_reddit("\"my product name\"")
sort accepts relevance, top, new, comments. For brand monitoring, combine new sort with a polling loop.
Get a user profile
def get_user(username: str):
r = requests.get(
f"{BASE}/api/reddit/user/{username}",
headers={"Authorization": f"Bearer {API_KEY}"},
)
return r.json()["data"]
Returns karma, account age, comment count, and recent activity timestamps — enough to filter out spam accounts in a lead-gen pipeline.
Post a comment
def post_comment(parent_id: str, body: str):
r = requests.post(
f"{BASE}/api/reddit/comment",
json={"parent_id": parent_id, "body": body},
headers={"Authorization": f"Bearer {API_KEY}"},
)
r.raise_for_status()
return r.json()
parent_id is either a post ID (t3_xxxxx) or a comment ID (t1_yyyyy). Comments cost $0.012 per call. No developer-app approval needed.
Vote on a post or comment
def vote(thing_id: str, direction: int):
"""direction: 1 (upvote), -1 (downvote), 0 (clear)"""
r = requests.post(
f"{BASE}/api/reddit/vote",
json={"id": thing_id, "dir": direction},
headers={"Authorization": f"Bearer {API_KEY}"},
)
return r.json()
Send a DM
def send_dm(to: str, subject: str, body: str):
r = requests.post(
f"{BASE}/api/reddit/dm",
json={"to": to, "subject": subject, "text": body},
headers={"Authorization": f"Bearer {API_KEY}"},
)
return r.json()
DMs are $0.025 per call. PRAW can technically do this too, but you'd need a Reddit account with verified email and the privatemessages OAuth scope — RedditAPI handles those headers for you.
Comparing Python Reddit API wrappers
Three real-world options for using the Reddit API in Python:
| Approach | Setup time | Commercial use | Monthly cap | Write scopes |
|---|---|---|---|---|
| PRAW + Reddit free tier | ~30 min (dev-app, OAuth) | ❌ forbidden by Reddit ToS | 10,000 calls | needs scope review |
| PRAW + Reddit Standard tier | ~2–4 weeks (dev-app approval) | ✅ allowed | metered | included |
RedditAPI + requests |
~2 min (signup) | ✅ allowed | none | included with vote/write/DM tiers |
PRAW is the right choice for academic research, personal bots, and learning. For anything that touches paying users, a managed third-party API is faster to ship and cheaper to scale at low-to-medium volume. Above ~5M calls/month, it's worth re-running the cost calculator to compare both paths at your specific volume.
The cheapest Reddit API. Try it free.
Reads from $0.002 per call. $0.50 free credits. No credit card required.
How much will this cost?
Four tiers, one bearer token. Cost per call:
- Reads (any
GET):$0.002 - Votes (
POST /vote):$0.005 - Writes (comments, login, profile updates):
$0.012 - DMs (
POST /dm*):$0.025
Three concrete scenarios for a typical Python pipeline:
# Scenario 1: brand monitoring (read-heavy)
# 500 search calls / day × 30 days = 15,000 reads
monthly_cost = 15_000 * 0.002
print(f"Brand monitoring: ${monthly_cost:.2f}/month") # $30.00
# Scenario 2: ML training corpus collection (read-only, one-shot)
# 200,000 posts + 1,000,000 comment-tree fetches
one_shot_cost = (200_000 * 0.002) + (1_000_000 * 0.002)
print(f"ML corpus: ${one_shot_cost:.2f} one-time") # $2,400
# Scenario 3: comment-reply bot (mixed)
# 50,000 reads + 500 comment posts / month
mixed_cost = (50_000 * 0.002) + (500 * 0.012)
print(f"Reply bot: ${mixed_cost:.2f}/month") # $106
The official Reddit Data API at the Commercial tier costs roughly $0.024 per call regardless of method on top of the $12K/year minimum. At the comment-bot scenario above, Reddit's official path would cost roughly $12,000 + (50,500 × $0.024) = $13,212. The same workload on RedditAPI runs $106.
If your volume is high enough that those numbers cross, the calculator does the math both ways.
Production patterns: retries, async, error handling
Three things every production Reddit API Python project ends up needing.
Idempotent retries on transient failures
Reddit's upstream occasionally returns 502 or 503 under load. RedditAPI surfaces those transparently — wrap your call site:
import time
from requests.exceptions import HTTPError
def reddit_get_with_retry(path: str, params: dict, max_retries: int = 3):
for attempt in range(max_retries):
try:
r = requests.get(
f"{BASE}{path}",
params=params,
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=15,
)
r.raise_for_status()
return r.json()
except HTTPError as e:
if e.response.status_code in (502, 503, 504) and attempt < max_retries - 1:
time.sleep(2 ** attempt) # exponential backoff
continue
raise
GET calls are safe to retry. POST calls (comment, vote, DM) are not automatically idempotent — re-running a comment-post creates a duplicate comment. Track the request ID server-side or use an in-app dedupe key before retrying.
Async at scale
For corpus collection or sustained search polling, plain requests blocks the event loop. Use httpx.AsyncClient with asyncio.gather:
import asyncio
import httpx
import os
API_KEY = os.environ["REDDITAPI_KEY"]
BASE = "https://api.redditapis.com"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
async def fetch_one(client, sub):
r = await client.get(f"{BASE}/api/reddit/posts", params={"sub": sub, "limit": 100}, headers=HEADERS)
return sub, r.json()
async def fetch_many(subs):
async with httpx.AsyncClient(timeout=30) as client:
results = await asyncio.gather(*(fetch_one(client, s) for s in subs))
return dict(results)
subs = ["python", "MachineLearning", "datascience", "learnpython"]
data = asyncio.run(fetch_many(subs))
Four subreddits, one round trip. No platform-level rate caps means you can scale this to 50+ concurrent fetches without hitting a wall.
Logging cost as you go
Track spend per script so you don't surprise yourself at month-end:
import json
from pathlib import Path
COST_LOG = Path(".reddit_cost.json")
def log_call(method: str, path: str):
cost = {"GET": 0.002, "VOTE": 0.005, "WRITE": 0.012, "DM": 0.025}
normalized_path = path.rstrip("/")
if method == "GET":
tier = "GET"
elif normalized_path.endswith("/vote"):
tier = "VOTE"
elif "/dm" in normalized_path:
tier = "DM"
else:
tier = "WRITE"
delta = cost[tier]
total = json.loads(COST_LOG.read_text()) if COST_LOG.exists() else {"total": 0}
total["total"] += delta
COST_LOG.write_text(json.dumps(total))
return delta
Or skip the local file and use the X-Credits-Remaining header that every RedditAPI response includes — it tells you the running balance after each call.
Where to go from here
This tutorial covers the read and write surface of the Reddit API in Python with plain HTTP. A few links for what's next:
- Reddit API pricing — the full endpoint cost table
- Reddit API alternatives — how RedditAPI compares to PRAW, Apify, and the official Reddit Data API
- Reddit API use cases — 14 production workloads built on the same endpoints (datasets, MCP servers, sentiment, bots)
- Reddit API cost calculator — plug in your monthly volume to estimate spend
Frequently asked questions.
You don't need one. The Reddit API in Python is just JSON over HTTPS — any HTTP library works. `requests` for sync code, `httpx` or `aiohttp` for async. RedditAPI exposes a stable bearer-token interface, so a 5-line wrapper around `requests.get` covers everything PRAW does without the OAuth flow or developer-app review.
This page is a working Reddit API Python example — every code block above is copy-paste runnable. Set `REDDITAPI_KEY` from your environment, install `requests`, and you can fetch posts, walk comment trees, search subreddits, post comments, vote, and send DMs in plain Python. Each call is one HTTP request returning JSON.
For hobby projects, PRAW is fine. For production — anything with paying customers or commercial intent — Reddit's free OAuth tier is forbidden by their terms of service, which rules PRAW out unless you sign the $12,000-per-year Standard tier. A managed third-party API like RedditAPI is typically 5–80× cheaper at production volume and ships in two minutes instead of four weeks.
Similar reads.
More guides on the Reddit API, scraping, pricing, and MCP servers.



