# 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).
## 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.
## 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.