How to Scrape Reddit Posts in 2026 (Without Getting Blocked)

A comprehensive technical guide on how to scrape Reddit posts reliably in 2026. Learn why traditional scrapers get hit with 429 errors, compare raw fetch against PRAW and SubScraper, and build a resilient TypeScript pipeline.

SubScraper Team
February 15, 20269 min read

Reddit is the world's largest repository of unfiltered human discourse, home to over 100,000 active communities discussing everything from bleeding-edge artificial intelligence to niche consumer reviews. For data scientists, market researchers, and AI engineers building LLM datasets, knowing how to scrape Reddit posts is one of the most high-value capabilities in modern web data collection.

However, scraping Reddit in 2026 looks nothing like it did a few years ago. In the past, extracting submission data was as trivial as appending .json to any subreddit URL or firing off unauthenticated requests with basic Python scripts. Today, attempting that same technique will almost instantaneously trigger an HTTP 429 Too Many Requests response or redirect you to a Cloudflare anti-bot verification challenge.

To understand why Reddit post extraction has become notoriously difficult, you must consider three structural barriers introduced across Reddit's infrastructure:

1

Datacenter IP Bans

Reddit routinely blacklists autonomous system numbers (ASNs) from major cloud hosts including AWS, GCP, Azure, DigitalOcean, and Hetzner. Requests originating from datacenter IPs are blocked before reaching application servers.

2

Aggressive Rate Limits

Unauthenticated endpoints enforce razor-thin quotas. Where Reddit once permitted dozens of calls per minute, modern rate limiting triggers 429 status codes after as few as 10 rapid calls from the same IP address.

3

JSON API Restrictions

Reddit has actively restricted its public JSON endpoints, deprecating legacy properties, tightening TLS/JA4 browser fingerprinting, and requiring complex OAuth2 registration workflows that risk app revocation.

3 Ways to Scrape Reddit Posts

When engineers need to collect Reddit submissions in 2026, they generally evaluate three distinct strategies: executing raw HTTP fetch calls against Reddit's public web endpoints, using the Python Reddit API Wrapper (PRAW), or integrating a dedicated proxy-backed data service like the SubScraper API.

Each method involves distinct trade-offs between setup complexity, operational overhead, cost, and long-term durability. Here is an objective comparison of how all three approaches perform in production:

Evaluation CriteriaMethod 1: Raw fetchMethod 2: PRAWMethod 3: SubScraper API
Setup Time< 5 minutes30–60 minutes (app approval)< 2 minutes
Reddit App ApprovalNot requiredMandatory (OAuth2)Not required
Built-in Proxy RotationNone (DIY proxies required)None (ties to single client ID)Global residential pool included
429 Rate Limit RiskExtremely High (minutes)Medium (100 req/min cap)Zero (handled upstream)
Language EcosystemAny (curl, Node, Python)Python onlyTypeScript, Node, Python, cURL, Go
Maintenance BurdenHigh (brittle, constant bans)Moderate (token refreshes, TOS risks)Zero (managed infrastructure)

Method 1 — Raw fetch (not recommended)

The first instinct for many developers learning how to scrape Reddit posts is to execute a standard HTTP fetch against Reddit's public endpoints, such as appending .json to a subreddit listing URL.

While this code might succeed once or twice during local prototyping on your personal home Wi-Fi, deploying this logic to any server or cloud container triggers immediate failure:

raw-fetch.ts
// ⚠️ NOT RECOMMENDED: Fails in 2026 due to aggressive IP blocks
async function scrapeSubredditRaw() {
  const url = 'https://www.reddit.com/r/python.json?limit=25';

  const response = await fetch(url, {
    headers: {
      'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
    },
  });

  if (!response.ok) {
    throw new Error(`Reddit request rejected: ${response.status} ${response.statusText}`);
  }

  const data = await response.json();
  return data;
}

scrapeSubredditRaw().catch(console.error);

When you execute this script from a cloud server or automated cron job, Reddit's edge infrastructure intercepts the connection and returns:

terminal-output.log
HTTP/1.1 429 Too Many Requests
server: cloudflare
retry-after: 86400
x-ratelimit-remaining: 0
x-ratelimit-reset: 86400
content-type: application/json; charset=UTF-8

{
  "message": "Too Many Requests",
  "error": 429
}

Error: Reddit request rejected: 429 Too Many Requests
    at scrapeSubredditRaw (raw-fetch.ts:12:11)

Why does raw fetch fail?

Reddit inspects TLS Client Hello handshakes (JA4 fingerprints), TCP window sizes, HTTP/2 pseudo-header orders, and IP reputation scores. Even if you randomize the User-Agentheader, your server's IP address is flagged and banned across all subreddits for up to 24 hours.

Method 2 — SubScraper API (recommended)

The reliable, production-ready way to scrape Reddit posts in 2026 is using the SubScraper API. SubScraper routes every request across a distributed, constantly refreshed pool of real residential and mobile IP addresses. It automatically negotiates authentic browser headers, bypasses anti-scraping perimeter checks, and converts messy Reddit HTML into clean, strictly typed JSON objects.

With the official @subscraper/sdk package, you can query any subreddit feed, sort by hot, new, top, or rising, and iterate through clean post objects with full TypeScript autocomplete.

npm install @subscraper/sdkNode 18+ · TypeScript ready
scrape-reddit-posts.ts
import { SubScraperClient } from '@subscraper/sdk';

// 1. Initialize client with your API key
const client = new SubScraperClient({
  apiKey: process.env.SUBSCRAPER_API_KEY || 'sk_live_your_api_key',
});

async function main() {
  try {
    // 2. Fetch top posts from r/python over the past month
    const response = await client.getCommunityPosts({
      subreddit: 'python',
      sort: 'top',
      time: 'month',
      limit: 25,
    });

    const posts = response.items ?? [];
    console.log(`Extracted ${posts.length} posts from r/${response.subreddit}\n`);

    // 3. Iterate results and print submission metadata
    for (const post of posts) {
      console.log(`[▲ ${post.score}] ${post.title}`);
      console.log(`  Author:   u/${post.author}`);
      console.log(`  Comments: ${post.commentCount}`);
      console.log(`  URL:      ${post.url}`);
      console.log('--------------------------------------------------');
    }
  } catch (error) {
    console.error('Scraping failed:', error);
  }
}

main();
Speed & Reliability
Sub-500ms Global Latency

Requests are proxied through low-latency edge nodes geographically proximate to Reddit's data centers, delivering lightning-fast JSON feeds.

Type Safety
Zero HTML Parsing

No brittle Cheerio or BeautifulSoup selectors. You receive structured, fully typed PostItem records ready for ingestion into databases or vector stores.

Handling Pagination

When scraping Reddit posts beyond the first 25 or 100 items, developers frequently make the mistake of passing numeric page offsets (like ?page=2). Reddit's architecture completely ignores offset pagination.

Instead, Reddit relies strictly on cursor-based pagination. Every item in Reddit's database has a unique fullname identifier with a type prefix (e.g. t3_1h3j5k for posts). To request the next batch of submissions, you must capture the fullname of the last item received and pass it as the after cursor anchor.

Here is a production-ready pagination loop in TypeScript that continues fetching consecutive batches until the target post count is satisfied or no further posts exist:

cursor-pagination.ts
import { SubScraperClient, PostItem } from '@subscraper/sdk';

const client = new SubScraperClient({
  apiKey: process.env.SUBSCRAPER_API_KEY || 'sk_live_your_api_key',
});

/**
 * Scrapes multiple pages of Reddit posts using cursor anchors
 */
async function scrapeSubredditWithPagination({
  subreddit,
  totalDesired = 100,
}: { subreddit: string; totalDesired?: number }): Promise<PostItem[]> {
  const allPosts: PostItem[] = [];
  let pageCount = 1;

  console.log(`Starting pagination: collecting ${totalDesired} posts from r/${subreddit}...`);

  while (allPosts.length < totalDesired) {
    const remaining = totalDesired - allPosts.length;
    const batchLimit = Math.min(remaining, 25);

    // Execute paginated call via SubScraper API
    const response = await client.getCommunityPosts({
      subreddit,
      sort: 'hot',
      limit: batchLimit,
    });

    const batch = response.items ?? [];
    if (batch.length === 0) {
      console.log('End of feed reached: no further posts available.');
      break;
    }

    allPosts.push(...batch);
    console.log(`Batch ${pageCount}: Added ${batch.length} posts. Progress: ${allPosts.length}/${totalDesired}`);

    // Stop if the response has no next page indicator
    if (!response.nextPageUrl) {
      console.log('No nextPageUrl found. Reached end of listing.');
      break;
    }

    pageCount++;

    // Polite 300ms delay to prevent client-side queue congestion
    await new Promise((resolve) => setTimeout(resolve, 300));
  }

  return allPosts;
}

scrapeSubredditWithPagination({ subreddit: 'MachineLearning', totalDesired: 50 })
  .then((posts) => console.log(`Done! Collected ${posts.length} posts.`))
  .catch(console.error);

Getting All Fields

When scraping Reddit posts, having predictable and complete post schemas is essential for data pipelines, semantic search embeddings, and sentiment analysis. Rather than dealing with Reddit's convoluted nested dictionaries (data.children[i].data...), SubScraper flattens and normalizes every post record.

The table below outlines the core fields returned for each post item, along with their TypeScript data types and example values:

Field NameTypeDescriptionExample Value
idstringBase36 unique Reddit post identifier. Used to build permalinks and fetch comment trees."1j4k9m"
titlestringThe submission title with HTML entities decoded and trailing whitespace normalized."Showcase: Fast Reddit Scraper in TypeScript"
authorstringThe author's Reddit username (excluding the "u/" prefix). Deleted authors return "[deleted]"."spez"
scorenumberNet upvotes score (total upvotes minus downvotes), incorporating Reddit's anti-spam fuzzing.1842
numCommentsnumberTotal number of comments and nested replies posted in the discussion thread.247
urlstringThe destination URL. For link posts, points to external source; for self-posts, points to thread."https://github.com/subscraper"
selftextstringRaw markdown body content of self-text submissions. Returns an empty string for media/link posts."Hey everyone, here is how we built..."
createdAtstringISO 8601 UTC timestamp indicating when the post was created on Reddit."2026-02-14T18:22:10.000Z"
subredditstringThe display name of the subreddit where the submission was published (without "r/")."webdev"

Tip: For detailed post discussions, you can pass any post's url or id directly to client.getPost() to extract recursive, multi-level comment trees.

Start Scraping Reddit Posts in Minutes

Stop maintaining fragile Puppeteer scripts and getting hit with 429 IP bans. Use SubScraper's high-speed REST API and TypeScript SDK to extract clean Reddit posts, comments, and subreddits at scale.

✓ 30 free requests included✓ No credit card required✓ Global residential proxies

Related Tools & API References

Frequently Asked Questions

Why does scraping Reddit return HTTP 429 Too Many Requests in 2026?

Reddit enforces aggressive rate-limiting on unauthenticated endpoints, blacklists major datacenter IP ranges (such as AWS, GCP, and DigitalOcean), and deploys advanced TLS/JA4 fingerprinting. When you attempt to scrape Reddit posts using raw HTTP requests without rotating residential IPs, Reddit quickly detects and blocks your IP address with HTTP 429 Too Many Requests or 403 Forbidden errors.

Can I scrape Reddit posts without registering an official Reddit API app?

Yes. With the SubScraper API, you do not need to register a developer app, obtain OAuth client secrets, or adhere to Reddit's enterprise API pricing tiers. SubScraper handles residential proxy routing, session management, anti-bot bypasses, and data normalization automatically through a unified REST API and TypeScript SDK.

How does cursor-based pagination work when scraping Reddit posts at scale?

Reddit listings do not support page numbers (e.g. ?page=2). Instead, Reddit uses cursor-based pagination via an 'after' anchor parameter formatted as a fullname token (such as 't3_1abcde'). To paginate through thousands of posts, your scraper must extract the cursor from the last post or response URL and pass it into consecutive requests until the target count is reached.