# Post



<MethodPage method="GET" path="/v1/reddit/post" credits={1}>
  <MethodSignature name="getPost" args={[{ name: "url" }, { name: "options", optional: true }]} returns="PostResponse" />

  Returns a post with up to `max_comments` comments, nested as on Reddit, and a digest: the original poster's replies in the thread, the most upvoted comments, and the ones Reddit marks as controversial. The digest only sorts what Reddit reports; nothing is scored or summarized. Reddit hides long threads behind "load more comments"; threadapi follows those links until it has the comments you asked for.

  Costs 1 credit for up to 500 comments and 1 more for each further 100 returned.

  <Security permission="reddit:read" />

  <SchemaGroup title="Query parameters">
    <SchemaField name="url" type="string" location="query" required>
      The post: a reddit.com URL on any subdomain (`www`, `old`, `new`), a `redd.it` short link, a `t3_` fullname or the bare post ID. Share links (`reddit.com/r/…/s/…`) aren't supported: open them and copy the post URL. You can pass `id` instead of `url`. A comment permalink focuses on that comment, as `comment` does.
    </SchemaField>

    <SchemaField name="comment" type="string" optional location="query">
      A comment ID to focus on. The response holds that comment, `context` levels of its parents and its replies, instead of the whole thread. `meta.focus_comment_id` names it.
    </SchemaField>

    <SchemaField name="context" type="integer" optional location="query">
      Parent levels to include above the focused comment, 0 to 8. Default `3`.
    </SchemaField>

    <SchemaField name="max_comments" type="integer" optional location="query">
      Most comments to return, 0 to 2,000. Default `200`. Comments are kept widest first: every top-level comment before any reply, every first-level reply before deeper ones. `0` returns the post alone.
    </SchemaField>

    <SchemaField name="format" type="string" optional location="query">
      `json` (default), `md` for one Markdown document, or `graph` for the digest and `meta` only.
    </SchemaField>
  </SchemaGroup>

  <div id="returns" className="mt-8">
    Response [#response]

    Headers on every success: `X-Credits-Used`, `X-Comments-Returned`, `X-Has-More` (`true` when a larger `max_comments` would return more), and `X-Cache-Tier` (`MISS` and `PARTIAL` mean some of it was fetched from Reddit just now).

    **`format=json`**

    ```jsonc
    {
      "post": {
        "id": "1x144ok",
        "subreddit": "programming",
        "title": "How big is a Git commit?",
        "author": "fagnerbrack",
        "score": 88,
        "upvote_ratio": 0.82,
        "num_comments": 29,               // Reddit's count, deleted comments included
        "permalink": "/r/programming/comments/1x144ok/how_big_is_a_git_commit/",
        "url": "https://ratfactor.com/cards/git-commit-size",
        "selftext": "",
        "created_at": "2026-10-08T22:00:15Z",
        "over_18": false,
        "media": [],                      // images, galleries and videos, as URLs
        "comments": [
          {
            "id": "o2f8m1c",
            "parent_id": "t3_1x144ok",    // t1_<id> for a reply
            "author": "Bpofficial",
            "score": 157,
            "body": "At least 3",
            "created_at": "2026-10-08T22:14:02Z",
            "depth": 0,
            "is_submitter": false,        // true for the original poster
            "replies": [ /* comments */ ]
          }
        ]
      },
      "discussion_graph": {
        "author_followups": [ /* the original poster's comments */ ],
        "most_upvoted": [ /* highest score, the original poster, AutoModerator and deleted comments left out */ ],
        "controversial": [ /* Reddit's controversial flag, or a negative score */ ],
        "total_analyzed": 29
      },
      "meta": {
        "comments_returned": 29,
        "comments_total": 29,
        "has_more": false,
        "max_comments": 200,
        "credits_used": 1,
        "cache": "MISS",
        "limited_by_balance": false       // true when the balance covered fewer comments than asked for
      }
    }
    ```

    **`format=md`** returns `text/markdown`: a header line, the post's text, a short digest and the comments as a nested list. Each comment appears once, in full.

    ```markdown
    # How big is a Git commit?

    r/programming, u/fagnerbrack, 88 points (82% upvoted), 29 comments, posted 2026-10-08 22:00 UTC
    https://www.reddit.com/r/programming/comments/1x144ok/how_big_is_a_git_commit/

    ## Digest

    Most upvoted:
    - u/Bpofficial (+157): At least 3

    ## Comments (29 of 29)

    - u/Bpofficial (+157): At least 3
      - u/shiny0metal0ass (+13): A commit of three gits.
    ```
  </div>

  <MethodSamples>
    <LanguageSample language="cURL">
      ```bash
      curl "https://api.threadapi.dev/v1/reddit/post?max_comments=500&url=https://www.reddit.com/r/programming/comments/1x144ok/" \
        -H "Authorization: Bearer $THREADAPI_API_KEY"
      ```
    </LanguageSample>

    <LanguageSample language="Python">
      ```python
      import os, requests

      r = requests.get(
          "https://api.threadapi.dev/v1/reddit/post",
          params={
              "url": "https://www.reddit.com/r/programming/comments/1x144ok/",
              "max_comments": 500,
          },
          headers={"Authorization": f"Bearer {os.environ['THREADAPI_API_KEY']}"},
      )
      r.raise_for_status()
      thread = r.json()

      def walk(comments, depth=0):
          for c in comments:
              print("  " * depth + f"{c['author']} ({c['score']}): {c['body'][:60]}")
              walk(c.get("replies", []), depth + 1)

      walk(thread["post"]["comments"])
      ```
    </LanguageSample>

    <LanguageSample language="TypeScript">
      ```ts
      const params = new URLSearchParams({
        url: "https://www.reddit.com/r/programming/comments/1x144ok/",
        format: "md",
        max_comments: "500",
      });
      const res = await fetch(`https://api.threadapi.dev/v1/reddit/post?${params}`, {
        headers: { Authorization: `Bearer ${process.env.THREADAPI_API_KEY}` },
      });
      if (!res.ok) throw new Error((await res.json()).error.message);

      const markdown = await res.text();
      console.log(res.headers.get("X-Credits-Used"), "credits");
      ```
    </LanguageSample>
  </MethodSamples>
</MethodPage>
