Reddit User Profile Bulk Scraper
Pricing
Pay per event
Reddit User Profile Bulk Scraper
Bulk-enrich public Reddit usernames into one profile row each with karma, account age, bio, follower count, assets, account flags, and explicit outcome statuses.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Stas Persiianenko
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
Turn Reddit usernames and profile URLs into one clean account record per user.
This Actor extracts public Reddit profile metadata: account ID, creation date and age, karma breakdown, follower count, bio, profile assets, account badges, moderation flags, NSFW status, visibility, and canonical URL. It deliberately excludes posts and comments, so the output stays compact and predictable for enrichment workflows.
What this Actor does
Provide a list of Reddit usernames, profile URLs, or both. The Actor:
- validates and deduplicates targets case-insensitively;
- opens an anonymous public Reddit session through an Apify residential proxy;
- completes Reddit's automatic JavaScript verification when presented;
- reads the public account profile payload;
- emits exactly one typed row per unique requested username;
- distinguishes missing, suspended, private, blocked, and failed targets.
A Reddit login, Reddit API key, user cookies, and manual CAPTCHA solving are not required.
Who is it for?
- Audience research teams enriching creator or community-member lists.
- Moderation teams reviewing account age, karma, and public account flags.
- Trust and safety teams refreshing public account watchlists.
- OSINT researchers normalizing public account metadata into datasets.
- Creator and lead-enrichment teams attaching public Reddit signals to records.
- Data engineers scheduling profile snapshots for downstream comparison.
Why use a profile-only scraper
General Reddit scrapers are designed around posts, comments, communities, and search results. This Actor is optimized for a different job: converting a known username list into one account-level row per target.
That means:
- no activity-content explosion;
- simple joins on
usernameorredditUserId; - predictable one-target-to-one-row output;
- explicit outcome rows instead of silent missing records;
- charges only for successfully resolved public profiles, not status rows.
Data extracted
| Field | Meaning |
|---|---|
username | Canonical Reddit username |
redditUserId | Reddit account ID without t2_ |
status | success, not_found, suspended, private, blocked, or failed |
statusMessage | Explanation for non-success outcomes |
createdAt | ISO 8601 account creation time |
accountAgeDays | Whole account age in days at scrape time |
totalKarma | Total Reddit karma |
linkKarma | Link/post karma |
commentKarma | Comment karma |
awardeeKarma | Karma received from awards |
awarderKarma | Karma earned from giving awards |
followersCount | Public profile follower/subscriber count when exposed |
bio | Public profile bio |
profileTitle | Public profile title |
profileDescription | Long public profile description |
avatarUrl | Public icon or Snoovatar URL |
bannerUrl | Public profile banner URL |
canonicalUrl | Canonical Reddit profile URL |
verified | Reddit verification flag |
hasVerifiedEmail | Public verified-email flag when exposed |
isEmployee | Reddit employee/admin flag |
isGold | Reddit Premium/Gold flag |
isMod | Moderator flag |
isNsfw | NSFW profile flag |
isSuspended | Suspended-account flag |
profileVisibility | Public profile visibility/type value |
scrapedAt | ISO 8601 scrape timestamp |
Source fields can be absent. Nullable output fields remain null rather than being guessed.
Pricing
The Actor uses pay-per-event pricing:
- $0.005 for one
startevent per run; - one
profileevent per successfully resolved public profile.
| Apify plan tier | Price per successful profile |
|---|---|
| Free | $0.0031794 |
| Bronze | $0.0027647 |
| Silver | $0.0021565 |
| Gold | $0.0016588 |
| Platinum | $0.0011059 |
| Diamond | $0.00077412 |
not_found, suspended, private, blocked, and failed status rows are not charged as resolved profiles. The live Apify pricing tab remains the source of truth.
For a run with N successful public profiles, use:
estimated charge = $0.005 + (N × profile event price for your plan tier)
Examples:
| Successful profiles | Free plan | Bronze plan |
|---|---|---|
| 1 | $0.00818 | $0.00776 |
| 5 | $0.02090 | $0.01882 |
| 25 | $0.08449 | $0.07412 |
| 100 | $0.32294 | $0.28147 |
Residential proxy transfer and browser runtime are handled inside the Actor. Large lists are usually more economical than many one-profile runs because the start event is paid once and healthy sessions are reused.
Getting started
- Open the Actor in Apify Console.
- Add Reddit usernames under Reddit usernames.
- Optionally add existing Reddit profile links under Reddit profile URLs.
- Keep Use residential proxy enabled for reliable Reddit access.
- Start with concurrency
1or2. - Click Start.
- Open the Profiles dataset output.
- Export the rows as JSON, CSV, Excel, XML, or RSS.
Example input:
{"usernames": ["spez", "reddit", "AutoModerator"],"maxItems": 3,"maxConcurrency": 2,"maxRetries": 2,"useResidentialProxy": true,"proxyCountryCode": "US"}
Input parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
usernames | string array | [] | Reddit usernames without u/ |
startUrls | request list | [] | reddit.com/user/... or reddit.com/u/... profile URLs |
maxItems | integer | 20 | Maximum unique profiles after deduplication |
maxConcurrency | integer | 2 | Parallel profile workers; allowed range 1–5 |
maxRetries | integer | 2 | Session-rotating retries for transient failures; allowed range 0–4 |
useResidentialProxy | boolean | true | Use Apify residential proxy sessions |
proxyCountryCode | string | US | Two-letter ISO proxy country code |
At least one valid username or profile URL is required. Malformed usernames, unsupported URLs, invalid country codes, and out-of-range limits fail the run before scraping.
Output example
A current public profile produces a row shaped like this:
{"username": "exampleuser","redditUserId": "abc123","status": "success","statusMessage": null,"createdAt": "2020-01-15T12:00:00.000Z","accountAgeDays": 1825,"totalKarma": 15420,"linkKarma": 4210,"commentKarma": 10980,"awardeeKarma": 180,"awarderKarma": 50,"followersCount": 230,"bio": "Example public profile bio.","profileTitle": "Example Profile","profileDescription": null,"avatarUrl": "https://styles.redditmedia.com/example-avatar.png","bannerUrl": null,"canonicalUrl": "https://www.reddit.com/user/exampleuser/","verified": false,"hasVerifiedEmail": true,"isEmployee": false,"isGold": false,"isMod": true,"isNsfw": false,"isSuspended": false,"profileVisibility": "user","scrapedAt": "2025-01-15T12:00:00.000Z"}
The example is anonymized. Actual values come from the requested public Reddit account.
Status and failure behavior
The Actor never turns a Reddit block into a false missing account.
success: a recognizable public account payload was resolved.not_found: Reddit explicitly returned HTTP 404 or a 404 JSON response.suspended: Reddit identified the account as suspended.private: the returned profile visibility is private.blocked: Reddit returned a challenge/interstitial or exhausted 403/418/429 responses.failed: another upstream, browser, network, or payload-shape error exhausted retries.
Every accepted unique target receives one row, even when the profile cannot be resolved. This makes bulk joins and watchlist audits deterministic.
Tips for reliable runs
- Leave residential proxy enabled; Reddit commonly blocks datacenter traffic.
- Start with concurrency
1for small, high-value lists. - Use concurrency
2for normal bulk refreshes. - Increase concurrency only when the observed block rate remains low.
- Keep retries at
2unless a workflow has strict latency requirements. - Split very large watchlists into scheduled batches.
- Use the
statusfield to route retryable and terminal outcomes separately. - Deduplicate upstream when you want stable billing estimates; the Actor also deduplicates input.
Limits
- Only anonymous public profile metadata is extracted.
- Posts, comments, messages, and private account data are excluded.
- Reddit can change fields, verification behavior, and rate limits.
- Some flags or profile assets are not exposed for every account and remain
null. - Follower counts depend on what Reddit exposes in the public profile payload.
- Account age is computed at scrape time and changes between runs.
- Deleted and suspended account response shapes can vary.
- Residential proxy access must be available in the Apify account running the Actor.
Integration workflows
Moderation intake
Send usernames from a moderation queue, then use account age, karma, and status fields as inputs to a human-reviewed risk workflow. Do not use a single field as an automatic enforcement decision.
Audience list enrichment
Join exported rows back to a CRM, spreadsheet, or warehouse on lowercase username. Preserve redditUserId for stable account-level tracking.
Scheduled watchlist refresh
Create an Apify schedule that runs daily or weekly. Store each run's scrapedAt, karma, follower, and flag fields for downstream comparisons.
Trust-and-safety routing
Route blocked and failed rows to a later retry. Treat not_found separately because it requires an explicit Reddit 404.
Run with the Apify API using cURL
Replace YOUR_TOKEN with an Apify API token:
curl -X POST \"https://api.apify.com/v2/acts/automation-lab~reddit-user-profile-bulk-scraper/runs?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"usernames": ["spez", "reddit"],"maxItems": 2,"maxConcurrency": 1,"useResidentialProxy": true}'
To wait for results synchronously:
curl -X POST \"https://api.apify.com/v2/acts/automation-lab~reddit-user-profile-bulk-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"usernames":["spez"],"maxItems":1}'
Run with JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/reddit-user-profile-bulk-scraper').call({usernames: ['spez', 'reddit'],maxItems: 2,maxConcurrency: 1,useResidentialProxy: true,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Install the client with:
$npm install apify-client
Run with Python
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("automation-lab/reddit-user-profile-bulk-scraper").call(run_input={"usernames": ["spez", "reddit"],"maxItems": 2,"maxConcurrency": 1,"useResidentialProxy": True,})items = client.dataset(run["defaultDatasetId"]).list_items().itemsprint(items)
Install the client with:
$pip install apify-client
Use with MCP and AI agents
Add the Actor to Claude Code through Apify MCP:
claude mcp add --transport http apify \"https://mcp.apify.com?tools=automation-lab/reddit-user-profile-bulk-scraper"
Claude Desktop
Add the following remote MCP server JSON to Claude Desktop's MCP configuration.
Cursor
Use Settings → Tools & MCP → Add MCP server and supply the same remote URL.
VS Code
Add the same remote server object to your workspace or user MCP configuration.
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=automation-lab/reddit-user-profile-bulk-scraper"}}}
Example prompts:
- “Enrich these 50 Reddit usernames and return account age, karma, and moderator status.”
- “Check this Reddit profile watchlist and separate missing, suspended, blocked, and successful accounts.”
- “Create a CSV-ready table of public bios, follower counts, karma, and profile URLs.”
Responsible use and legality
This Actor accesses anonymous public Reddit profile metadata. Use it only for lawful purposes and in accordance with applicable laws, Reddit's terms, Apify's terms, and your organization's policies.
Do not use the output to harass users, bypass access controls, infer private traits, or make high-impact automated decisions without appropriate review. Minimize stored personal data, set retention limits, secure exports, and honor valid deletion or access requests where applicable.
You are responsible for determining the lawful basis for your processing and for complying with privacy, employment, consumer-protection, and other relevant rules.
Troubleshooting
Why did I receive blocked instead of not_found?
Reddit returned a challenge, rate limit, or blocked response rather than an explicit 404. The Actor reports that uncertainty honestly. Retry later with residential proxy enabled and conservative concurrency.
Why are some values null?
Reddit does not expose every field for every account. The Actor preserves missing values as null rather than fabricating defaults.
Why did the run fail before producing rows?
Check for malformed usernames, non-Reddit URLs, an invalid proxy country, or out-of-range numeric inputs. Input validation intentionally fails closed.
Can I scrape posts and comments too?
Not with this profile-only Actor. Use the related Reddit Scraper for activity, community, and search workflows.
Can I disable the proxy?
Yes, for diagnostics, but Reddit frequently blocks datacenter and direct traffic. The default residential route is recommended for real workloads.
FAQ
Does the Actor require a Reddit account?
No. It uses anonymous public surfaces and does not accept Reddit credentials or cookies.
Does one input always produce one output row?
Each unique, valid username accepted after deduplication produces exactly one row. Duplicate username and URL forms collapse to one case-insensitive target.
Are unresolved rows charged as profiles?
No. Only success rows emit the per-profile charge event.
Can I schedule it?
Yes. Use Apify Schedules to refresh a watchlist daily, weekly, or at another interval.
What export formats are available?
Apify datasets support JSON, JSONL, CSV, Excel, XML, and RSS exports.
Related automation-lab Actors
- Reddit Scraper — scrape Reddit posts, comments, communities, and search results when you need activity content rather than one profile row per username.
Support
If Reddit changes its public profile response or a valid input repeatedly returns an unexpected status, open an issue from the Actor's Apify Console page. Include a minimal reproducible input, run ID, and expected outcome. Do not include private credentials or personal data that is not already public.