Skip to content

exilonium/RedApi

Repository files navigation

RedApi

A small FastAPI service that re-implements, approximately, how Redlib talks to Reddit - so you get a REST API that serves Reddit data the way Redlib's own backend does, instead of hitting Reddit's official rate-limited public API directly.

How Redlib actually does it (and what this copies)

Per Redlib's own README and the maintainer's public write-up:

  1. OAuth "installed_client" token spoofing - Reddit's official Android app supports anonymous/logged-out browsing via the https://oauth.reddit.com/grants/installed_client grant. It needs no username/password, just a public Android client_id + a random device_id. Using this grant makes Reddit treat your traffic like the real app, which gets a much higher rate limit than a generic script hitting reddit.com/.json cold.
  2. Token refresh every ~24h, matching the real app's cadence, instead of re-authenticating per request.
  3. Header mimicking - Android-shaped User-Agent on every call.
  4. Fallbacks when something breaks: retry with backoff on 429/5xx, force-refresh the token on 401/403, rotate to another client_id if one's blocked, and if OAuth itself is unreachable, drop down to the public unauthenticated *.json endpoints on www.reddit.com then old.reddit.com.

This project implements that same chain in Python:

reddit_client.py
 ├── _fetch_token()        # installed_client OAuth grant
 ├── _get_token()           # cache + refresh + client_id rotation
 ├── _request_oauth()       # oauth.reddit.com, retries once on 401/403
 ├── _request_public_json() # unauthenticated *.json fallback
 └── get()                  # walks FALLBACK_TIERS, retries, stale-cache last resort

It's an approximation, not a port of Redlib's Rust source - the request shape and fallback strategy match, the exact header set and edge-case handling don't claim byte-for-byte parity.

Setup

pip install -r requirements.txt
uvicorn main:app --reload --port 8080

Endpoints

Route Mirrors
GET /r/{subreddit}/{sort} reddit.com/r/{sub}/{hot,new,top,rising,controversial}.json
GET /r/{subreddit}/about subreddit info
GET /r/{subreddit}/comments/{post_id} post + comment tree
GET /comments/{post_id} same, short form
GET /user/{username}/about user profile
GET /user/{username}/{sort} overview/submitted/comments/upvoted/gilded
GET /search?q=...&subreddit=... search, optionally scoped to a sub
GET /best r/popular-style front page
GET /raw/{path} escape hatch - any reddit.com JSON path through the same fallback chain
curl http://localhost:8080/r/python/hot
curl http://localhost:8080/r/python/comments/abc123
curl "http://localhost:8080/search?q=rust&subreddit=programming"
curl "http://localhost:8080/raw/r/python/top?t=week"

Things to know before you run this for real

  • ANDROID_CLIENT_IDS in config.py holds the historical public Android client_id. Reddit rotates/blocks these from time to time - if token requests start failing with 400/401, you'll need to capture a current one yourself (mitmproxy against the real app, same technique the Redlib maintainer used) or pull whatever Redlib's src/client.rs currently uses, and add it to the list. Multiple entries let the rotation logic actually do something when one gets blocked.
  • Cache is in-memory and per-process - fine for a single uvicorn worker, not for a multi-process/multi-machine deployment as-is.
  • ToS - this hits Reddit the same way Redlib does. Whether that's fine for your use case (personal self-hosted frontend vs. high-volume scraping) is worth checking against Reddit's terms yourself.

Files

  • config.py - client_id pool, UA pools, fallback tier order, timing constants
  • cache.py - tiny TTL cache (fresh + stale reads)
  • reddit_client.py - the actual client + fallback chain
  • main.py - FastAPI routes

About

Reddit Api Server With NO rate limits

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages