API docs

A fast, read-only Reddit API — posts, comments, comment trees, subreddits, and user profiles. Pay per request — 1 credit = 1 call, $0.50 (333 credits) free on signup, no card required. Full machine-readable spec at /openapi.json.

Quick start

  1. Sign up and verify your email.
  2. Finish account setup, then open /developer and create an API key — you get $0.50 (333 credits) free, no card required.
  3. Make your first call with the key, below.
curl
curl "https://api.threadsnoop.com/v1/posts?subreddit=startups&limit=25" \
  -H "x-api-key: ts_live_YOUR_KEY"
python (requests)
import requests

r = requests.get(
    "https://api.threadsnoop.com/v1/posts",
    headers={"x-api-key": "ts_live_YOUR_KEY"},
    params={"subreddit": "startups", "limit": 25},
)
data = r.json()
print(data["_threadsnoop"])

Authentication

Pass your key as either header — both are accepted on every request:

x-api-key: ts_live_YOUR_KEY
# or
Authorization: Bearer ts_live_YOUR_KEY

A missing key returns 401; an unknown or revoked key also returns 401.

Credits

1 credit = 1 read = 1 request, regardless of endpoint. Credits never expire. The price you pay per credit is set at top-up time by a bulk-discount ladder — metering itself stays a flat 1 credit/request forever:

Top-upPer readPer 1,000 readsCredits
$5 – $24$0.0015$1.503,333 per $5
$25 – $49$0.0013$1.3019,230 at $25
$50 – $99$0.0012$1.2041,666 at $50
$100+$0.0010$1.00100,000 per $100

Run out of balance and a request returns 402 with a top-up link in the body — never silent degradation. If a call is charged and then fails upstream (502), the credit is refunded automatically.

Rate limits

Every key gets the same limit: 2 requests/second sustained, burst 10. Go over it and you get 429 with a Retry-After header (seconds to wait). Separately, all API traffic shares one global upstream reserve that protects capacity for ThreadSnoop's own discovery pipeline — if that shared pool is briefly exhausted you also get 429, but with an x-ratelimit-scope: global header so you can tell it apart from your own per-key limit. Neither case charges a credit.

Endpoint reference

7 endpoints. Every 200 response carries x-credits-used and x-credits-remaining headers alongside the JSON body's _threadsnoop block. Jump to a specific one from the sidebar (or the chip row above, on a narrow screen).

Post and comment objects both include permalink — a relative path, so prepend https://www.reddit.com for a clickable URL — and posts also carry an absolute url field.

GET/v1/posts

List posts by subreddit/author, or fetch specific posts by id in one call.

Two modes on one route. Pass subreddit and/or author to page through a listing (newest-first by default). Or pass ids (comma-separated, capped at 100) to fetch exact posts by id — in that mode every other listing param is ignored, and the response has cursor: null, has_more: false (there's no next page for a fixed id list). Either mode is 1 credit.

ParamTypeDefaultNotes
subredditstringSubreddit name, no r/. One of subreddit/author/ids is required.
authorstringReddit username, no u/.
idsstringComma-separated post ids (max 100). When set, listing params below are ignored.
afterstringEpoch seconds or relative form (e.g. 7d), passed through as-is.
beforestringSame accepted forms as after.
limitinteger251–100.
sortasc | descdescBy created_utc.
fieldsstringComma-separated field allowlist. Omit for the full untrimmed object.
qstringClient-side exact-phrase filter over title + selftext. See the pagination guide below.
curl
curl "https://api.threadsnoop.com/v1/posts?subreddit=startups&limit=2" \
  -H "x-api-key: ts_live_YOUR_KEY"
response (truncated)
{
  "data": [
    {
      "id": "1abcxyz",
      "title": "Anyone know a tool that watches Reddit for me?",
      "selftext": "Tired of manually searching every day...",
      "author": "some_founder",
      "created_utc": 1753000000,
      "subreddit": "startups",
      "permalink": "/r/startups/comments/1abcxyz/anyone_know_a_tool_that_watches_reddit_for_me/",
      "url": "https://www.reddit.com/r/startups/comments/1abcxyz/anyone_know_a_tool_that_watches_reddit_for_me/",
      "num_comments": 4,
      "score": 12,
      "hide_score": false
    }
  ],
  "_threadsnoop": {
    "cursor": 1753000000,
    "has_more": true,
    "credits_used": 1,
    "credits_remaining": 332
  }
}

GET/v1/comments

List comments by subreddit/author, or fetch specific comments by id.

Same shape as /v1/posts, including a matching ids batch mode: pass ids (comma-separated, capped at 100) to fetch exact comments by id in one call — every other listing param is ignored in that mode, and the response has cursor: null, has_more: false. Either mode is 1 credit.

ParamTypeDefaultNotes
subredditstringOne of subreddit/author/ids is required.
authorstringReddit username, no u/.
idsstringComma-separated comment ids (max 100). When set, listing params below are ignored.
afterstringEpoch seconds or relative form (e.g. 7d).
beforestringSame accepted forms as after.
limitinteger251–100.
sortasc | descdescBy created_utc.
fieldsstringComma-separated field allowlist. Omit for full object.
qstringClient-side exact-phrase filter over body. See the pagination guide.
curl
curl "https://api.threadsnoop.com/v1/comments?author=some_founder&limit=2" \
  -H "x-api-key: ts_live_YOUR_KEY"
response (truncated)
{
  "data": [
    {
      "id": "kxyzabc",
      "body": "I've been looking for exactly this",
      "author": "some_founder",
      "created_utc": 1753001200,
      "subreddit": "startups",
      "link_id": "t3_1abcxyz",
      "parent_id": "t3_1abcxyz",
      "permalink": "/r/startups/comments/1abcxyz/anyone_know_a_tool_that_watches_reddit_for_me/kxyzabc/"
    }
  ],
  "_threadsnoop": {
    "cursor": 1753001200,
    "has_more": true,
    "credits_used": 1,
    "credits_remaining": 331
  }
}

GET/v1/comments/tree

Full nested comment tree for a post, with a real comment count.

One call returns the whole tree, so there's no pagination — cursor/has_more are always null/false. Fresh posts can briefly report a score of 1 and 0 comments; use this endpoint for live comment counts.

ParamTypeDefaultNotes
post_id *stringWith or without the t3_ prefix.
limitinteger501–500.
curl
curl "https://api.threadsnoop.com/v1/comments/tree?post_id=1abcxyz&limit=50" \
  -H "x-api-key: ts_live_YOUR_KEY"
response (truncated)
{
  "data": [
    {
      "kind": "t1",
      "data": {
        "id": "kxyzabc",
        "body": "I've been looking for exactly this",
        "author": "some_founder",
        "created_utc": 1753001200,
        "score": 3
      },
      "replies": []
    }
  ],
  "_threadsnoop": {
    "cursor": null,
    "has_more": false,
    "credits_used": 1,
    "credits_remaining": 330
  }
}

GET/v1/subreddits/{name}/rules

A subreddit's posting rules.

ParamTypeDefaultNotes
name *string (path)3–21 chars, letters/digits/underscore only.
curl
curl "https://api.threadsnoop.com/v1/subreddits/SaaS/rules" \
  -H "x-api-key: ts_live_YOUR_KEY"
response (truncated)
{
  "data": {
    "subreddit": "SaaS",
    "rules": [
      { "short_name": "No self-promotion", "description": "Do not post ads or referral links.", "priority": 0 }
    ]
  },
  "_threadsnoop": { "credits_used": 1, "credits_remaining": 328 }
}

GET/v1/users/{name}

A Reddit user's profile aggregate — karma, post/comment counts, first/last activity.

Roughly Reddit's own /user/{name}/about. Exact username match, not prefix/fuzzy search. A username with no matching account is still 1 credit — the lookup made a real upstream call either way — and comes back as a normal 200 with data.user: null rather than a 404.

ParamTypeDefaultNotes
name *string (path)3–64 chars, letters/digits/underscore/hyphen. A name with no matching account is still charged — see above.
curl
curl "https://api.threadsnoop.com/v1/users/spez" \
  -H "x-api-key: ts_live_YOUR_KEY"
response (truncated, hit)
{
  "data": {
    "user": {
      "author": "spez",
      "id": "1w72",
      "_meta": {
        "num_posts": 549,
        "num_comments": 2568,
        "post_karma": 832984,
        "comment_karma": 666948,
        "total_karma": 1499932,
        "earliest_post_at": 1119552314,
        "earliest_comment_at": 1134392748,
        "last_post_at": 1751475161,
        "last_comment_at": 1729645028
      }
    }
  },
  "_threadsnoop": { "credits_used": 1, "credits_remaining": 327 }
}
response (miss — still 1 credit)
{
  "data": { "user": null },
  "_threadsnoop": { "credits_used": 1, "credits_remaining": 326 }
}

GET/v1/account

Check your credit balance and rate limit. Free — 0 credits.

Costs nothing and doesn't make an upstream request, but it's still key-authed and rate-limited like every other endpoint.

curl
curl "https://api.threadsnoop.com/v1/account" \
  -H "x-api-key: ts_live_YOUR_KEY"
response
{
  "data": { "credits_balance": 328, "rate_limit": { "qps": 2, "burst": 10 } },
  "_threadsnoop": { "credits_used": 0, "credits_remaining": 328 }
}

Pagination

The cursor is the created_utc of the last row in the page you got back. Pass it forward as after when sorting asc, or as before when sorting desc (the default), to fetch the next page. has_moreis true whenever the page came back full — keep going until it's false or you have enough.

q= is a client-side exact-phrase filter (with basic singular/plural flexibility) applied to whatever page comes back — it is not server-side search. You pay 1 credit per page fetched whether it matched your phrase or not, and cursor/has_more always describe the raw page, not the filtered result — a page that comes back with 0 rows after filtering does notmean there's nothing left; it means keep paginating with the returned cursor. Scope your window with after/before to control how much you scan (and pay for) per search.

MCP server

A remote MCP server at https://api.threadsnoop.com/mcp, authenticated with the same x-api-key header. Seven tools, each billed exactly like the HTTP endpoint it wraps (1 credit/call; check_credits is free):

  • search_posts, search_comments — list/search posts and comments, or fetch by id.
  • get_comment_tree — full comment tree for a post.
  • search_subreddits, get_subreddit_rules — subreddit lookup.
  • get_user_profile — a Reddit user's karma/post/comment aggregate.
  • check_credits — balance + rate limit. Free.
Claude Code
claude mcp add --transport http threadsnoop https://api.threadsnoop.com/mcp \
  --header "x-api-key: YOUR_KEY"
Claude Desktop / Cursor (JSON config)
{
  "mcpServers": {
    "threadsnoop": {
      "url": "https://api.threadsnoop.com/mcp",
      "headers": {
        "x-api-key": "YOUR_KEY"
      }
    }
  }
}

OpenAPI spec

Machine-readable reference: OpenAPI spec.