Symptom
All scrapers/feed readers pointed at old.reddit.com started failing with HTTP 302 redirects to /login/?reason=lor2 (served as an HTML login page). This hit EVERY old.reddit surface: RSS feeds (/r/<sub>/top/.rss), HTML listings (/r/<sub>/top/), and post permalinks -- with or without the user=/feed= RSS auth tokens from /prefs/feeds/, and from BOTH residential and datacenter egress. This is a host-level wall, not IP reputation.
What no longer works (measured 2026-09-04)
- old.reddit.com + RSS tokens: 302 login wall on every surface, tokens ignored.
- FeedBurner proxying (the classic zero-code workaround): dead. 10/14 test burns serve reddit's 'Welcome to Reddit' login HTML re-served as HTTP 200 (so a naive status check passes while content is garbage); 4/14 serve Atom frozen weeks stale. Reddit walls Google's fetcher too.
- old.reddit permalink SSR for deletion/liveness checks: returns the login page, so og:description-based checks silently fail open.
What works
https://www.reddit.com/r/<sub>/top/.rss?t=day&limit=25 with the user=<account>&feed=<40-hex> tokens from https://www.reddit.com/prefs/feeds/: 10/10 HTTP 200 with full entries in 7s residential, and 3/3 from a cloud datacenter egress (Render). Without tokens, www 429s after the first request per ~60s -- the tokens are load-bearing at any real scrape cadence.
Fix pattern
Rewrite the host at the single fetch callsite instead of migrating stored feed URLs:
_OLD_REDDIT_RE = re.compile(r'^https?://old\.reddit\.com/')
def normalize_reddit_feed_url(url: str) -> str:
return _OLD_REDDIT_RE.sub('https://www.reddit.com/', url)Apply before appending auth params. Covers every stale DB row with zero migration.
Caveats
- www.reddit.com HTML (listings, permalinks) serves a JS challenge shell to programmatic clients -- no SSR markers -- so engagement scraping and permalink liveness checks do NOT port to www by host swap. Those need the official OAuth API.
- If you filter the auth tokens out of VCR cassettes via filter_query_parameters, recording with real tokens still replays fine (python-vcr filtering is symmetric), but unauthenticated re-records will flake on the 1-req/60s 429.