I wanted a script that checks a handful of subreddits every morning, ranks the top posts, and drops a CSV I can diff day over day. No dashboard, no scraper, just a cron job and a JSON response. Here's the whole thing.
The request
`import os, requests
h = {"X-API-Key": os.environ["SERPENT_API_KEY"]}
# 50, not 40 — most block-billed APIs charge a started block whole,
# so round to a clean boundary (25/50/75/100 here) instead of a random number.
p = {"subreddit": "python", "sort": "top", "t": "week", "limit": 50}
data = requests.get("https://apiserpent.com/api/reddit/posts",
params=p, headers=h, timeout=120).json()
if "delivery" in data:
d = data["delivery"]
print(d["returned"], "of", d["requested"], "—", d["reason"])
for post in data["posts"]:
print(post["score"], post["num_comments"], post["title"])`
That's it — no HTML to parse, no headless browser, no rate-limit dance. Every field (score, num_comments, upvote_ratio, flair, is_nsfw, etc.) comes back named, and an absent value is null rather than a missing key, so you don't need defensive .get() chains everywhere.
The one gotcha worth knowing
Paginated endpoints like this one bill in blocks of 25 items. If your limit isn't a clean multiple of 25, you're paying for a full extra block for a partial one. Snap it before you send the request:
def snap_to_block(limit, block=25, cap=100):
return min(cap, ((limit + block - 1) // block) * block)
Turning it into a daily sweep
Wrap the same request in a loop over a subreddit list and a cron entry, and you've got a diffable daily CSV with zero infrastructure:
while IFS= read -r sub; do
curl -s -G "https://apiserpent.com/api/reddit/posts" \
--data-urlencode "subreddit=$sub" -d "sort=top" -d "t=day" -d "limit=25" \
-H "X-API-Key: $SERPENT_API_KEY" \
| jq -r --arg s "$sub" \
'[$s, (.count|tostring), ([.posts[].score] | max | tostring),
(.delivery.reason // "complete")] | @csv' \
| sed "s|^|$(date -u +%F),|" >> reddit-daily.csv
done < subreddits.txt
I'm using Serpent API's Reddit endpoint here (10 free calls to try it, no card), but the pattern — snap to block boundaries, check for a delivery/short-response field before trusting a count — applies to any block-billed API you're wiring up. Happy to answer questions on the request shape in the comments.
Top comments (0)