Reddit API in Python
Short answer: Install requests, send a GET with your API key in the Authorization header, and read data from the JSON response. The script below covers listings, pagination, threads, search and retries in about 40 lines.
Set up
pip install requests export APIXSTAR_API_KEY="xstar_..."
Create the key in the console after signing in with Google. Keep it in an environment variable, not in your source.
A small client
import os, time, requests
BASE = "https://api.apixstar.com/reddit/v1"
AUTH = {"Authorization": f"Bearer {os.environ['APIXSTAR_API_KEY']}"}
def get(path, **params):
for attempt in range(5):
r = requests.get(BASE + path, params=params, headers=AUTH, timeout=30)
if r.status_code == 429: # our limit or Reddit's
time.sleep(float(r.headers.get("Retry-After", 2 ** attempt)))
continue
if r.status_code >= 500: # upstream trouble, not charged
time.sleep(2 ** attempt)
continue
body = r.json()
if not body["ok"]:
raise RuntimeError(body["error"]["code"])
return body
raise RuntimeError("gave up after 5 attempts")
Fetch posts from a subreddit
page = get("/r/python/new", limit=100)
for post in page["data"]["posts"]:
print(post["score"], post["title"])
print("charged:", page["meta"]["billing"]["charged"],
"balance:", page["meta"]["billing"]["balanceRemaining"])
Paginate past 100
def all_posts(sub, pages=5):
cursor = None
for _ in range(pages):
page = get(f"/r/{sub}/new", limit=100, **({"cursor": cursor} if cursor else {}))
yield from page["data"]["posts"]
cursor = next_cursor(page) # the token returned with the page
if not cursor:
return
Five pages is 500 posts, which costs $0.03. You pay per 10 posts returned.
Read a thread with comments
thread = get("/posts/1abc2de", commentLimit=200)["data"]
Search
hits = get("/r/python/search", q="asyncio", sort="new", timeRange="week")["data"]
everywhere = get("/search", q='"vector database"', sort="top", timeRange="month")["data"]
Go faster with threads
from concurrent.futures import ThreadPoolExecutor
subs = ["python", "rust", "golang", "typescript"]
with ThreadPoolExecutor(max_workers=4) as pool:
results = list(pool.map(lambda s: get(f"/r/{s}/top", limit=100), subs))
Stay under your account's requests-per-minute limit. A request rejected by the limit returns 429 and is not charged.
Using PRAW instead
If you need to post, reply or moderate, use PRAW with the official API. The same three reads written both ways are on the PRAW comparison page. Every parameter used above is in the API reference.
Python questions
Do I need PRAW to use Reddit from Python?
No. PRAW is one option, and it is the right one for the official API. Any HTTP library works with a REST API, and this guide uses requests.
How do I get more than 100 posts?
Each response includes a cursor for the next page. Pass it back as the cursor parameter and repeat until no cursor is returned.
How should I handle errors?
Check the ok field. On HTTP 429, wait for the Retry-After header and try again. On 5xx, retry with a growing delay. Failed requests are not charged.
Can I run requests in parallel?
Yes, up to your account's limit, which is 30 requests per second per account, regardless of top-up amount.
Is there an official Python SDK?
Not yet. The API is a handful of GET endpoints, so a small wrapper like the one on this page is all you need.