# Reddit profile API: 6 new reads, people not posts (https://www.socialcrawl.dev/blog/reddit-profile-api) > Reddit profile API: spez + 23 posts for 1 credit. Comment search 14/1 isn't history: 5 dated comments cost 10. Subreddit search 25, 5 of 25 ids repeated. A Reddit profile API is how you follow a *person*, not a thread. On 8 September 2026 we called production: `GET /v1/reddit/profile?handle=spez` returned the account card for **1 credit** (karma **940,980**, cake day 2005-06-06, bio "Reddit CEO"). `profile/posts` returned **23** submissions for **1 credit**. Four more new reads ship with it — comment search, subreddit discovery, and media search (all 1 credit a page this harvest), plus metered comment history at **2 credits per comment** (`limit=5` billed **10**). The cheap `author:spez` comment search returned **14** rows whose newest was 30 July; the 10-credit history page's five comments are all 5 August. Search is not history. [Official Reddit docs](https://www.reddit.com/dev/api) name user listings and a single `GET /search`. They do not print `len(items)` or credits per call. [PRAW's quick start](https://praw.readthedocs.io/en/stable/getting_started/quick_start.html) prints `link_karma` and a post's comment tree. This post is SocialCrawl's measured people reads behind `x-api-key` — not [Devvit](https://developers.reddit.com/docs/capabilities/server/reddit-api), not the [official Data API](https://support.reddithelp.com/hc/en-us/articles/16160319875092-Reddit-Data-API-Wiki). Search page-size and thread comments — the [reddit search api](/blog/reddit-api-more-per-credit) story — are a different post. **Stack:** Python 3.10+ · `requests` · `GET https://www.socialcrawl.dev/v1/reddit/…` · header `x-api-key`. Print `len(items)` and `credits_used`. Live catalogue: [`/docs/reddit`](/docs/reddit). Platform hub: [`/platforms/reddit`](/platforms/reddit). Credits: [`/pricing`](/pricing). Isometric Reddit profile API account card beside a stack of post tiles. ## How do you read a Reddit profile (and the posts that account wrote)? A reddit user profile api call returns the canonical author object; `profile/posts` returns that account's submissions. `author.id` is the **bare username** — the same `handle` the sibling reads take. No remap. ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/reddit/profile?handle=spez" ``` ```python BASE = "https://www.socialcrawl.dev" r = requests.get( f"{BASE}/v1/reddit/profile", params={"handle": "spez"}, headers={"x-api-key": os.environ["SOCIALCRAWL_API_KEY"]}, timeout=30, ) r.raise_for_status() payload = r.json() author = payload["data"]["author"] print(author["id"], author["likes_count"], payload.get("credits_used")) # spez, 940980, 1 ``` This harvest (`request_id` `req-o6ZvUhjCKniBuhgN`, `cached=false`): | Field | Live 2026-09-08 | | --- | --- | | `author.id` / `author.username` | `spez` | | `author.display_name` | `t2_1w72` (Reddit fullname) | | `author.bio` | `Reddit CEO` | | `author.joined_at` | `2005-06-06T04:00:00.000000+0000` | | `author.likes_count` (total karma) | **940,980** | | `ext.post_karma` / `ext.comment_karma` / `ext.awardee_karma` | 184,487 / 756,493 / 0 (sum equals `likes_count`) | | `ext.trophy_count` | 52 | | `author.followers` | **null** (Reddit publishes no public follower count) | | `author.avatar_url` | populated | | credits_used | 1 | Trimmed author object under the unified schema: ```json { "id": "spez", "username": "spez", "display_name": "t2_1w72", "bio": "Reddit CEO", "followers": null, "likes_count": 940980, "joined_at": "2005-06-06T04:00:00.000000+0000", "ext": { "post_karma": 184487, "comment_karma": 756493, "awardee_karma": 0, "trophy_count": 52 } } ``` A reddit user api that only prints `link_karma` stops at the card. The karma split is the rest of the profile. The reddit account posts api — reddit user post search against a known username — uses the same handle: ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/reddit/profile/posts?handle=spez" ``` `GET /v1/reddit/profile/posts?handle=spez` returned **23** posts, `dropped=0`, `has_more=false`, `next_cursor=null`, **1 credit** (`request_id` `req-PyKS7G1J9RUkMenv`). Newest `2026-08-05` (“Modernizing Reddit’s infrastructure with you”, 331 likes / 445 comments). Oldest on the page `2015-07-11`. `ext.subreddit` was populated on 16/23, null on 7/23, empty string on **0/23**. Null means the post sat on the user’s profile page, not that the field is broken. Row 0 (profile-page post): ```json { "id": "1vgbkge", "url": "https://www.reddit.com/user/spez/comments/1vgbkge/modernizing_reddits_infrastructure_with_you/", "author": { "username": "spez" }, "engagement": { "likes": 331, "comments": 445, "shares": null }, "published_at": "2026-08-05T16:03:56.264Z", "ext": { "subreddit": null, "title": "Modernizing Reddit’s infrastructure with you" } } ``` Print `len(items)` and the pagination block. `has_more=false` is what *this* call returned. It is not a page-size constant, and it is not “every post spez has ever made.” [`reddit.com/dev/api`](https://www.reddit.com/dev/api) names user methods; [PRAW's quick start](https://praw.readthedocs.io/en/stable/getting_started/quick_start.html) prints `name` + `link_karma` and never loops `redditor.submissions`. Neither prints `credits_used=1`. Profile card **1** credit; **23** posts **1** credit (`handle=spez`, 2026-09-08). Print `len(items)` — 23 is this call, not a page size. ## Can you search Reddit comment text without opening threads? A reddit comment search api searches comment **text**. You don't need a post id. Official [`GET /search`](https://www.reddit.com/dev/api) does not list a comment-index method; trees are `GET /comments/{article}` plus `morechildren`. Thread expansion (`/v1/reddit/post/comments`) is a [different post](/blog/reddit-api-more-per-credit). This is a reddit comments api for the index. To [scrape reddit comments](/blog/how-to-scrape-reddit-2026) yourself, follow a separate walkthrough. ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/reddit/search/comments?query=best+mechanical+keyboard" ``` ```python r = requests.get( f"{BASE}/v1/reddit/search/comments", params={"query": "best mechanical keyboard"}, headers={"x-api-key": os.environ["SOCIALCRAWL_API_KEY"]}, timeout=30, ) r.raise_for_status() payload = r.json() items = payload["data"]["items"] pag = payload.get("pagination") or {} print(len(items), payload.get("credits_used"), pag.get("has_more")) # 22, 1, True ``` Topical `query=best+mechanical+keyboard` returned **22** comments, **1 credit**, `has_more=true` (`request_id` `req-6sDLTdBCzFkIGXUR`). Sample row 0: `ext.subreddit=GamingLaptops`, post title “Money is not object: best gaming laptop”, `ext.subreddit_subscribers=402826`. Each hit carries the parent post inline (`ext.post_title`, `ext.subreddit`, `ext.post_score`), so a bare comment body is readable. Open the permalink at `comment.url`. Do not paste `ext.post_url` — on this sample it embedded a `t3_` fullname in the path. Same endpoint, author operator: ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/reddit/search/comments?query=author:spez" ``` `query=author:spez` returned **14** comments, **1 credit**, `has_more=true` (`request_id` `req-DvUIutwnvTUYxMKX`). Newest on the page **2026-07-30**, oldest **2026-06-04**. `parent_id` **null on all 14**. Dates are **not** newest-first (July cluster, then June). All 14 authors are `spez`. ```json { "id": "p0ri6c3", "url": "https://www.reddit.com/r/RDDT/comments/1vb4oe8/comment/p0ri6c3/", "parent_id": null, "text": "Thank you for your support of RDDT…", "author": { "username": "spez" }, "engagement": { "likes": 15 }, "published_at": "2026-07-30T22:37:36.676Z", "ext": { "post_title": "Reddit Announces Q2’26 Earnings (plus AMA!)", "subreddit": "RDDT", "subreddit_subscribers": 12585 } } ``` Same endpoint, Hangul query: `query=기계식 키보드` returned **4** comments, **1 credit**, `has_more=false` (`request_id` `req-H7R0Vm7C6Q8szT2Z`), all `ext.subreddit=Mogong`. Comment search can also return loosely related hits rather than empty — judge relevance on the rows, not the count. This 14-row `author:` page is a relevance subset. History is a different read. ## How do you find a subreddit when you don't know its name? Until now, you needed the community's name to read it. Reddit subreddit search is the topic-to-name hop — the API version of a subreddit finder, not a consumer app. A reddit user search still needs the handle; this hop is for the community. ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/reddit/subreddits/search?query=machine+learning" ``` ```python page1 = requests.get( f"{BASE}/v1/reddit/subreddits/search", params={"query": "machine learning"}, headers={"x-api-key": os.environ["SOCIALCRAWL_API_KEY"]}, timeout=30, ) page1.raise_for_status() p1 = page1.json() print(len(p1["data"]["items"]), p1.get("credits_used")) # 25, 1 cursor = (p1.get("pagination") or {}).get("next_cursor") page2 = requests.get( f"{BASE}/v1/reddit/subreddits/search", params={"query": "machine learning", "cursor": cursor}, headers={"x-api-key": os.environ["SOCIALCRAWL_API_KEY"]}, timeout=30, ) p2 = page2.json() ids1 = {row["author"]["id"] for row in p1["data"]["items"]} ids2 = [row["author"]["id"] for row in p2["data"]["items"]] print(len(ids2), len(ids1.intersection(ids2))) # 25, 5 ``` `GET /v1/reddit/subreddits/search?query=machine+learning` returned **25** communities, **1 credit**, `has_more=true` (`request_id` `req-q8qaH8RShZp1qwQI`). Rank 1: `author.id=MachineLearning`, **3,070,326** subscribers, url `https://www.reddit.com/r/MachineLearning`. `author.id` is the bare community name — the same string `/v1/reddit/subreddit` and `/v1/reddit/subreddit/details` take. No remap. | # | `author.id` | subscribers | | ---: | --- | ---: | | 1 | MachineLearning | 3,070,326 | | 2 | learnmachinelearning | 676,458 | | 3 | machinelearningnews | 151,586 | | 4 | MLQuestions | 113,445 | | 5 | ResearchML | 22,407 | `ext.weekly_active_users` / `weekly_contributions` / `rules_text` / `language` are **null on these discovery rows** — those fill on `/v1/reddit/subreddit/details`. Do not treat a discovery row as a full community card. Page 2 of the same query also returned 25, 1 credit, `has_more=true` (`req-AKrr3z8fPrDzMtOZ`). **5 of those 25 ids were already on page 1:** `Learning`, `AIJobs`, `learndatascience`, `elearning`, `machinetranslation`. Page 2 otherwise opened with `science`, `technology`, `datascience`. De-duplicate on `author.id` before treating a walk as 50 communities. This is one query, two pages — not a published repeat rate. The official catalog lists [`GET /subreddits/search`](https://www.reddit.com/dev/api); [PRAW's quick start](https://praw.readthedocs.io/en/stable/getting_started/quick_start.html) only does `reddit.subreddit("known_name")`. Neither prints 25 / 1 credit or the repeat-row caveat. ## What does Reddit media search return for 1 credit? A reddit media search api returns image/video-scoped posts — same post schema, not a new object type. The official catalog has no named “search media” method; media is a filter on [`GET /search`](https://www.reddit.com/dev/api). ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/reddit/search/media?query=mechanical+keyboard+build" ``` ```python r = requests.get( f"{BASE}/v1/reddit/search/media", params={"query": "mechanical keyboard build"}, headers={"x-api-key": os.environ["SOCIALCRAWL_API_KEY"]}, timeout=30, ) payload = r.json() items = payload["data"]["items"] print(len(items), payload.get("credits_used")) # 25, 1 ``` `GET /v1/reddit/search/media?query=mechanical+keyboard+build` returned **25** posts, **1 credit**, `has_more=true`, `dropped=0` (`request_id` `req-MkoYw012z9QhfH0m`). `content.thumbnail_url` populated on **25/25**. `content.media_urls` type on this page: **string on 24**, **null on 1**, **array on 0**. Callers that assume a list should wrap a string. Row 0 (the null case): title “First Mechanical keyboard build”, `ext.subreddit=MechanicalKeyboards`, YouTube link in the body, thumbnail populated, `media_urls=null`, 4 likes / 4 comments. Row 1 (string case): ```json { "id": "1thgcsn", "url": "https://www.reddit.com/r/PHMechanicalKeyboard/comments/1thgcsn/first_custom_mechanical_keyboard_deep_and_thocky/", "content": { "media_urls": "https://packaged-media.redd.it/fyj7uj0dz12h1/dl/m2-res_640p.mp4", "thumbnail_url": "https://external-preview.redd.it/…", "duration_seconds": 31 }, "ext": { "subreddit": "PHMechanicalKeyboard", "title": "First Custom Mechanical Keyboard (Deep and Thocky)" } } ``` Do not describe `media_urls` as an array from this evidence. Two trays of comment cards comparing Reddit comment search to dated comment history. ## When is comment history worth 2 credits a comment? A reddit comment history api reads the account’s own listing, newest first, with real parent ids. The 1-credit author search above is a relevance sample of the search index. Same handle, same hour, two jobs. | | `/v1/reddit/search/comments?query=author:spez` | `/v1/reddit/profile/comments?handle=spez&limit=5` | | --- | --- | --- | | What it reads | Comment **search index** (relevance-ranked subset) | The account’s **own listing**, newest first | | `len(items)` this call | **14** | **5** | | credits_used | **1** | **10** (2 per comment) | | `has_more` | **true** (pages with `cursor`) | **false** (no cursor; raise `limit` to go deeper) | | Newest on this response | **2026-07-30T22:39:07Z** | **2026-08-05T18:31:50Z** | | Oldest on this response | 2026-06-04T00:24:28Z | 2026-08-05T16:24:51Z | | Order | Not chronological | Newest first | | `parent_id` | **null on all 14** | populated on all 5 | | Includes the 5 Aug comments? | **No** | **Yes — all five** | Run `search/comments?query=author:username` (1 credit) first. Pay for history when you need the listing, in date order, with real parent ids. The history page’s five comments are **newer than every row** on the 1-credit search page. Search `has_more=true`, so this is not “search stopped at 14 forever.” The first search page is a relevance subset that did not contain the account's newest comments. ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/reddit/profile/comments?handle=spez&limit=5" ``` ```python r = requests.get( f"{BASE}/v1/reddit/profile/comments", params={"handle": "spez", "limit": 5}, headers={"x-api-key": os.environ["SOCIALCRAWL_API_KEY"]}, timeout=30, ) payload = r.json() items = payload["data"]["items"] print(len(items), payload.get("credits_used")) # 5, 10 ``` `limit` is a **depth control (1–100)**, not a page size. No cursor. `credits_used == 2 × items.length` held on this call (5 × 2 = 10). Raising `limit` reaches further back in **one** call, at 2 credits per comment **returned**. Keep `limit` small; this harvest used 5. All five history rows sit under post `1vgbkge`, all `ext.is_submitter=true`, all `ext.subreddit=u_spez`, window ~2 hours on 5 August (`request_id` `req-8XgsIGNYx7uPAv6r`). Row 2: “If we replace every line of code but the output is the same, is it still old Reddit?” 14 comments / 1 credit is a sample; 5 comments / 10 credits is the listing. Start cheap. ## How do you start using this? Get an API key. The free pack needs no card — the current credit amount lives on [`/pricing`](/pricing). The first billed call is the profile read above, then `profile/posts`. The reddit api python path is `requests` with one API key in `x-api-key`. Print `len(data["data"]["items"])` and `credits_used` on list endpoints; print `data["data"]["author"]` on the profile card. ```python BASE = "https://www.socialcrawl.dev" headers = {"x-api-key": os.environ["SOCIALCRAWL_API_KEY"]} profile = requests.get( f"{BASE}/v1/reddit/profile", params={"handle": "spez"}, headers=headers, timeout=30, ) profile.raise_for_status() card = profile.json() print(card["data"]["author"]["id"], card.get("credits_used")) posts = requests.get( f"{BASE}/v1/reddit/profile/posts", params={"handle": "spez"}, headers=headers, timeout=30, ) body = posts.json() print(len(body["data"]["items"]), body.get("credits_used")) # spez 1 # 23 1 ``` See your data in the visual explorer before writing a single line. Live catalogue: [`/docs/reddit`](/docs/reddit). Platform hub: [`/platforms/reddit`](/platforms/reddit). Check `GET /v1/credits/balance` first. This harvest billed **18 credits** on 8 September 2026: the six new reads (history at `limit=5` for **10**), a second subreddit-search page, and two extra comment-search queries. The six-endpoint spine alone is **15**. Keep history `limit` small. ## Frequently asked questions ### How many credits does Reddit comment history cost? `GET /v1/reddit/profile/comments` is metered at **2 credits per comment returned**. This harvest: `handle=spez&limit=5` returned **5** comments and billed **10**. `limit` is a depth control (1–100), not a page size. The other five new reads each billed **1 credit** on 8 September 2026. Start with `search/comments?query=author:username` at 1 credit. ### Do I need Reddit OAuth to call a Reddit profile API? No. These Reddit calls use `x-api-key`. You don't register a Reddit OAuth app. Official Data API access *does* require OAuth — a rate-limit and contract story in the [Reddit Data API Wiki](https://support.reddithelp.com/hc/en-us/articles/16160319875092-Reddit-Data-API-Wiki), expanded in the [official Reddit API landscape](/blog/reddit-data-api-2026) and in [Reddit OAuth and API keys](/blog/reddit-api-key-limits-alternatives-2026). ### How do I tell a missing Reddit user from a bad handle? Call `GET /v1/reddit/profile`. A 23-character handle that fails format rules returned HTTP **400** (`INVALID_REQUEST` — “Invalid `handle` for reddit: must match platform handle rules.”) and **0 credits** (`thisuserdoesnotexistzzz`, `req-VGTNIIRe1iw9DYCc`). A well-formed handle that does not exist returned HTTP **404** (`RESOURCE_NOT_FOUND` — “This Reddit account is suspended, deleted, or does not exist. Your credits have been refunded.”) and **0 credits** (`zzznobodyexists99`, `req-2X3zgAJAHfzxkcZe`). Do not collapse 400 and 404. This harvest did not probe a real account that has never commented. ### How does pagination work on these Reddit endpoints? `search/comments`, `subreddits/search`, and `search/media` page with `cursor` at 1 credit a page (`has_more` / `next_cursor`). `profile/comments` does **not** page — raise `limit` (1–100). `profile/posts` this run returned 23 with `has_more=false` and `next_cursor=null`. On `subreddits/search`, de-duplicate on `author.id`: this walk repeated **5 of 25** ids on page 2. ### Is `author:username` comment search the same as comment history? No. `search/comments?query=author:spez` billed **1 credit** for **14** relevance-ranked rows (newest on the page 30 July, `parent_id` null, `has_more=true`). `profile/comments?limit=5` billed **10 credits** for **5** chronological rows (all 5 August, real `parent_id`, no cursor). History’s comments are newer than every row on the search page. Search samples the index. Use search first. The live catalogue is [`/docs/reddit`](/docs/reddit). Reproduce the harvest curls; keep history `limit` small.