Reddit User Scraper — Profile, Posts & Comments avatar

Reddit User Scraper — Profile, Posts & Comments

Pricing

from $1.50 / 1,000 profile results

Go to Apify Store
Reddit User Scraper — Profile, Posts & Comments

Reddit User Scraper — Profile, Posts & Comments

Look up public Reddit user profiles in bulk and optionally collect each user's recent posts and comments. Usernames, u/name, @name, profile URLs or CSV in; one clean profile row per user out — karma, account age, verified/premium flags, avatar and status. No Reddit login or API key.

Pricing

from $1.50 / 1,000 profile results

Rating

0.0

(0)

Developer

Delowar Munna

Delowar Munna

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Categories

Share

Reddit User Scraper

Look up Reddit users in bulk and get one clean public profile record per username — karma, account age, verification and premium flags, avatar and status — with optional recent posts and comments. Accept usernames, u/name, @name, profile URLs or CSV. No Reddit login, cookies or API key required.

What this Actor does

  • One row per submitted user, always. Every input ends in exactly one profile row: found, not_found_or_suspended, deleted, invalid_input, skipped, or — when Reddit could not be read — rate_limited / provider_error / timeout. Nothing is dropped silently.
  • Bulk input in any form. Plain usernames, u/name, /u/name, @name, profile URLs on any Reddit host, JSON records with your own IDs, or a CSV file. The same user named twice is looked up once, and every input and external ID that named them is kept on the row.
  • Profile-only by default. One lookup per user — the fastest and cheapest mode.
  • Optional recent activity. Switch on posts and/or comments to get one row per item, linked to the user by username, user ID and your external ID, with per-user and whole-run caps.
  • Community footprint. With activity on, each profile row carries the user's top communities and activity date range from what was collected.

Profile-only quick start

{
"users": ["spez", "u/kn0thing", "https://www.reddit.com/user/AutoModerator/"],
"maxUsers": 1000,
"includePosts": false,
"includeComments": false
}

Include recent posts and comments

{
"records": [
{ "user": "example_user", "externalId": "lead_001" },
{ "user": "u/example_two", "externalId": "lead_002" }
],
"includePosts": true,
"includeComments": true,
"maxPostsPerUser": 25,
"maxCommentsPerUser": 25,
"maxTotalActivityItems": 1000,
"publishedAfter": "30d",
"subredditFilter": ["SaaS", "Entrepreneur"],
"includeNsfw": false,
"skipActivityIds": ["t3_1abc234"]
}

Activity is fetched only for users whose profile was found. Each user's posts and comments are read newest first by default (activitySort: new, top, hot, controversial).

Bulk: CSV and API

  • CSV — upload a file, paste its text, or give an https link. Columns: user (username or profile URL) and optional external_id. username, url and id are recognised as aliases, and a file with no header is read as one user per line. Maximum 5 MB.
  • API — send users as a string array or records as [{ "user": "...", "externalId": "..." }]. Every boolean you leave out takes its documented default; activity stays off unless you send true.

Input formats

You typeLooked up as
spez, u/spez, /u/spez, @spez, user/spezspez
https://www.reddit.com/user/spez/, https://old.reddit.com/u/spez/comments/spez
SPEZ together with spezone lookup, both inputs kept on the row
not a name!, a subreddit URL, a non-Reddit URLan invalid_input row naming the reason

Reddit usernames are 1–20 letters, digits, _ or -.

Output

All rows share one dataset. Every submitted user gets one recordType: "profile" row; with activity on, each post and comment gets its own recordType: "activity" row, linked back to the user by username, userId and your externalId.

Reddit User Scraper — Comments view, table (one row per comment with its subreddit, parent post and distinction)

The dataset has five views. Views choose columns; they cannot hide rows, so split an export on recordType (profile / activity) and activityType (post / comment) in your spreadsheet or integration. One real record from each view follows, taken from a run of this input, which returned exactly 20 rows — 6 profile rows (3 found, 1 deleted, 1 not found, 1 invalid) and 14 posts and comments:

{
"users": [
"u/kn0thing",
"https://www.reddit.com/user/GallowBoob/",
"violentacrez",
"zz_no_such_q8x7w2",
"not a valid name!"
],
"records": [{ "user": "spez", "externalId": "lead_001" }],
"includePosts": true,
"includeComments": true,
"maxPostsPerUser": 3,
"maxCommentsPerUser": 2,
"maxTotalActivityItems": 14
}

Profiles

A found profile. spez was submitted as a record, so externalId travels with the row; this one was served by the fallback source (provider: "tikhub"), which is why isEmployee, isNsfwProfile and the public post and comment counts are filled. topSubreddits counts only what this run collected:

{
"recordType": "profile",
"username": "spez",
"resultStatus": "found",
"userId": "1w72",
"profileUrl": "https://www.reddit.com/user/spez/",
"createdAt": "2005-06-06T04:00:00.000Z",
"accountAgeDays": 7784,
"totalKarma": 940980,
"linkKarma": 184487,
"commentKarma": 756493,
"isVerified": true,
"isPremium": true,
"isEmployee": true,
"isModerator": null,
"isAutomatedAccount": false,
"isNsfwProfile": false,
"avatarUrl": "https://styles.redditmedia.com/t5_3k30p/styles/profileIcon_uj015iwx9s7g1.png?width=256&height=256&frame=1&auto=webp&crop=256:256,smart&s=b3afd3e423e96bcdc7e3c49d60a60a50dc2903aa",
"profileDescription": "Reddit CEO",
"publicPostCount": 845,
"publicCommentCount": 3209,
"activityStatus": "capped",
"postsReturned": 3,
"commentsReturned": 2,
"topSubreddits": [
{
"subreddit": "u_spez",
"posts": 2,
"comments": 2,
"total": 4
},
{
"subreddit": "redditstock",
"posts": 1,
"comments": 0,
"total": 1
}
],
"externalId": "lead_001",
"inputValue": "spez",
"provider": "tikhub",
"scrapedAt": "2026-09-28T05:12:29.982Z"
}

null means "not published by the source that served this row", never "false". Reddit's public profile card shows karma, cake day, the verification, premium and automated-account badges, the avatar and the description. It does not show:

  • awardeeKarma, awarderKarma, hasVerifiedEmailFlag — not public logged out; always null. hasVerifiedEmailFlag would only ever be a yes/no account flag — this Actor never collects or guesses email addresses.
  • isModerator — set to true when the user's own collected activity shows a moderator distinction, otherwise null. Nothing public proves the negative.
  • isEmployee, isNsfwProfile, profileTitle, publicPostCount, publicCommentCount — filled when the profile was served by the fallback source (provider: "tikhub"), otherwise null. isEmployee is also set to true when collected activity shows an admin distinction.
  • createdAt is exact to the day on the public card (createdAtPrecision: "day") and to the second from the fallback source ("exact").

Profile statuses

Every input's outcome, including the ones that were not found — with every input and external ID that named the user:

{
"recordType": "profile",
"inputValue": "zz_no_such_q8x7w2",
"externalId": null,
"sourceInputs": [
"zz_no_such_q8x7w2"
],
"sourceExternalIds": [],
"username": "zz_no_such_q8x7w2",
"resultStatus": "not_found_or_suspended",
"statusDetail": "Reddit renders a missing and a suspended account identically logged out",
"activityStatus": "not_applicable",
"provider": "reddit-web",
"capturedSequence": 2,
"scrapedAt": "2026-09-28T05:12:17.519Z"
}

Posts

A post in a community, with its media link:

{
"activityType": "post",
"username": "GallowBoob",
"subreddit": "aww",
"title": "She’s enjoying the summer breeze [OC]",
"text": null,
"score": 67,
"commentCount": 9,
"upvoteRatio": 0.9714285714285714,
"createdAt": "2026-07-17T18:03:16.834Z",
"url": "https://www.reddit.com/r/aww/comments/1uz79k3/shes_enjoying_the_summer_breeze_oc/",
"linkUrl": "https://v.redd.it/8u59jcvuxtdh1",
"domain": "v.redd.it",
"postType": "hosted_video",
"isNsfw": false,
"isStickied": false,
"isCrosspost": false,
"awardCount": null,
"activityId": "t3_1uz79k3",
"externalId": null,
"provider": "tikhub"
}

isNsfw is the post's own NSFW mark. Since 1.0.4 post rows also carry isSubredditNsfw — whether the community the post was made in is marked NSFW (the sample above predates it). With Include NSFW activity off, a post is dropped when either is true; null (not shown by the source) is kept.

Comments

A comment with its parent post. distinguished is admin or moderator when the user spoke in that capacity, and isSubmitter is true when they wrote the post they commented on. If a comment came from the fallback source and its text reached the source's preview length, isTextTruncated is true:

{
"activityType": "comment",
"username": "spez",
"subreddit": "u_spez",
"text": "If we replace every line of code but the output is the same, is it still old Reddit?",
"score": 20,
"createdAt": "2026-08-05T17:30:18.963Z",
"parentPostTitle": "Modernizing Reddit’s infrastructure with you",
"parentPostId": "t3_1vgbkge",
"url": "https://www.reddit.com/user/spez/comments/1vgbkge/comment/p1w9sot/",
"distinguished": "admin",
"isSubmitter": true,
"isTextTruncated": null,
"activityId": "t1_p1w9sot",
"externalId": "lead_001",
"provider": "reddit-web"
}

Community activity

A compact post-and-comment timeline per user, for counting activity by community and date:

{
"recordType": "activity",
"username": "kn0thing",
"userId": "1wh0",
"activityType": "comment",
"subreddit": "GTA",
"createdAt": "2026-07-13T13:52:10.283Z",
"score": 7,
"activityId": "t1_ox9viy9",
"url": "https://www.reddit.com/r/GTA/comments/1uv84qa/comment/ox9viy9/"
}

Not-found and status behaviour

resultStatusMeaningCharged
foundProfile readyes
not_found_or_suspendedReddit shows no profile. Logged out, Reddit renders a non-existent username and a suspended account identically, so the two cannot be told apart.no
deletedThe account was deleted by its ownerno
invalid_inputNot a Reddit username or profile URL; statusDetail says whyno
skippedOn your skip listno
rate_limited, provider_error, timeoutReddit could not be read for this user this runno

Users in the last group are written to the RETRY_INPUT key-value record, ready to run again as-is. Not-found and deleted users are left out of it — re-running would only confirm them.

activityStatus on each found profile says how its activity went: not_requested, complete (the feed ended), capped (a per-user or total limit stopped it), or partial (a page could not be read; what was collected is kept). Every other resultStatus row says not_applicable.

Limits and incremental use

  • Per user: maxPostsPerUser, maxCommentsPerUser (up to 1,000 each — Reddit's own profile listings stop at roughly 1,000 items, so full lifetime history is not available).
  • Whole run: maxUsers and maxTotalActivityItems. The activity budget is shared fairly: each user gets an equal share of what remains when its activity starts, split between posts and comments. Unused budget flows on: a user who runs out of share before its own limits gets a fair slice of what is still unspent, so budget that not-found or quiet users leave is used by the others. Reaching the total stops activity only; every remaining profile is still looked up.
  • Dates: publishedAfter / publishedBefore take a date or a window (12h, 30d, 2w, 6m, 1y). With the new sort, a user's feed stops being read once it passes publishedAfter.
  • Incremental runs: skipUsernames (no request made), skipUserIds, skipActivityIds. Profiles and activity refresh differently: karma and flags change over time, so re-running a user gives a fresh profile row; activity IDs never change, so skipActivityIds with publishedAfter is the way to collect only what is new.
  • Unknown values are never filtered out. A post whose NSFW flag or score the source does not show is kept by the NSFW and score filters.

Pricing

Pay per result, with two events you can see in the Pricing tab of this Actor:

  • Profile result — once per unique profile found. Not found, suspended, deleted, invalid, skipped and unreadable users are free.
  • Activity result — once per unique post or comment delivered. Only charged when you switch activity on; filtered, skip-listed, duplicate and over-limit items are free.

There is no start fee: a run that finds nothing costs nothing in events. Live prices are on the Pricing tab; this README deliberately does not quote figures, because they can change. If you set a spending limit on a run, the Actor stops fetching once the limit is reached and keeps everything already paid for.

Performance

A profile lookup is one small request. Requests are paced per proxy address to Reddit's published logged-out budget, and each worker uses its own address, so maxConcurrency sets throughput. Activity costs one request per 25 items per user. The first profile row lands within seconds of the run starting.

No login, and the proxy posture

This Actor reads only Reddit's public, logged-out pages and never asks for a Reddit login, password, cookie, session or API key. It identifies itself plainly to Reddit rather than imitating a browser.

When Reddit's public pages refuse a request, the Actor retries on a fresh address and then uses a third-party data source for that request. The row's provider field says which source served it.

🚦 Proxy policy

Use Apify Datacenter proxy (the default) or no proxy — both work for Reddit profile lookups at this Actor's per-address pacing.

Apify Residential proxy is not supported. The run fails at start if apifyProxyGroups includes RESIDENTIAL. Reason: in pay-per-event Actors, residential bandwidth is billed to the developer, not the run user, so a bandwidth-heavy run could cost more than it earns.

If you genuinely need residential routing, supply your own provider via the proxy editor's Custom proxy URLs field — that traffic goes through your provider, not Apify, and is unaffected:

http://user:pass@proxy.iproyal.com:12321
http://user:pass@proxy.brightdata.com:22225
http://user:pass@proxy.oxylabs.io:7777

Privacy and responsible use

Reddit usernames are pseudonymous public identifiers. This Actor returns only what Reddit shows publicly and does not infer or expose real-world identity, email addresses, or sensitive traits (health, politics, sexuality or similar), reconstruct deleted or private activity, or match accounts across platforms. The community summary counts public activity per community — it draws no conclusions about the person. You are responsible for using the data lawfully, including under GDPR and Reddit's terms.

API and integrations

Run it from the Apify API, a schedule, or any integration (Make, Zapier, n8n, webhooks). Results are in the default dataset; the key-value store holds:

  • RUN_SUMMARY — counts by status, requests per endpoint, latency, stop reason, and charged events;
  • COMMUNITY_SUMMARY — per-user top communities and UTC hour-of-day / weekday activity counts (when activity is on);
  • RETRY_INPUT — users that could not be read, as a ready-to-run input.

It pairs with the Coregent Reddit Posts Search Scraper and Reddit Comments Scraper: collect authors there, then enrich them here by passing the usernames as users.

FAQ

Why is a user not_found_or_suspended when I know they exist? Reddit shows a suspended account exactly like a non-existent one to logged-out visitors. If the account was active recently, it has probably been suspended.

Why is isEmployee or isModerator null? The public profile card does not show them. They become true when the evidence is public (see Output: profiles), and are never guessed.

Can I get a user's full history? No. Reddit's profile listings stop at roughly 1,000 items per listing. This Actor does not claim more.

Does it need my Reddit account? No. It never asks for one.

Changelog

  • 1.0.5 (2026-09-28) — the whole-run activity budget is filled more reliably: a user who runs out of share before its own limits gets budget that not-found or quiet users left unused.
  • 1.0.4 (2026-09-28) — post rows carry isSubredditNsfw (the community is marked NSFW), and the NSFW filter drops posts in NSFW communities too. Blocked profile lookups that keep resolving to deleted or missing users stop falling back to the paid source after a run-level limit and end rate_limited (listed in RETRY_INPUT).
  • 1.0 (2026-09) — initial release: bulk profile lookup, optional posts and comments, CSV and records input with external IDs, status rows for every input, fair activity caps, community summary, incremental skip lists, pay-per-event pricing with a spending-limit stop.