Answers
How long should I cache social media API results to avoid paying twice?
Short answer
Cache by how fast the data changes: account profiles for a day to a week, post text indefinitely (refresh only the metrics you need), comments on posts older than a week for days, and hot lists not at all, since each snapshot is its own record. The biggest saving is on per-object calls: a dashboard that re-fetches 200 Xiaohongshu notes on each of 50 daily page views spends $200.00 a day on okdata, against $4.00 with a one-day cache.
Paying twice for the same data usually happens by accident: a dashboard that calls the API on every page load, a nightly job that refetches everything, a notebook re-run during analysis. A small cache in front of your calls fixes all three. The only real decision is how long each kind of data may sit before you fetch it again.
Lifetimes that fit social data
| Data | Endpoint | Changes | Suggested cache |
|---|---|---|---|
| Account profile, followers | Douyin account profile | slowly | 1 to 7 days |
| Post text and images | Xiaohongshu note detail | almost never | keep indefinitely |
| Post metrics | same call | fast at first, then slowly | hours in the first week, then days |
| Comments on posts older than a week | TikTok video comments | slowly | days; re-check only the first page |
| Hot lists | Weibo hot search | within hours | do not cache; store each snapshot |
| Search results | per query | depends on the keyword | your monitoring interval |
The prices tell you where caching pays most. Xiaohongshu note detail is $0.02 per note, so 1,000 repeat lookups waste $20.00. A Douyin profile is $0.002; for cheap lookups like that, a cache also keeps big jobs clear of rate limits.
A small file cache
import hashlib, json, os, pathlib, time, requests
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
CACHE = pathlib.Path(".okcache"); CACHE.mkdir(exist_ok=True)
def cached(path, ttl_seconds, **params):
key = hashlib.sha256(json.dumps([path, params], sort_keys=True).encode()).hexdigest()
f = CACHE / key
if f.exists() and time.time() - f.stat().st_mtime < ttl_seconds:
return json.loads(f.read_text())
body = requests.get(f"https://api.okdata.online{path}", headers=H, params=params, timeout=60).json()
if body["code"] == "ok":
f.write_text(json.dumps(body, ensure_ascii=False))
return body
profile = cached("/v1/douyin/users/get", 3 * 86400, id="MS4wLjABAAAA...")
Only successful responses are cached, so an error never sticks; errors were free anyway.
Two things that are not your cache
- Idempotency keys. Resending the same request with the same
Idempotency-Keywithin 24 hours replays the stored result for free. That protects retries; it is not a general cache across different requests. meta.cached. The service may answer from a short-lived cache of its own and says so in each response. You should not count on it for savings.
For a monitoring setup that only pays for what is new, see competitor monitoring.
Updated