FetchLayer fetchlayer.dev Sign in

+ Integration Guide

Reddit Scraping API with TypeScript: Complete Guide

How to search Reddit and scrape posts using TypeScript with full type safety. Working examples with typed responses for every FetchLayer endpoint.

  • TypeScript
  • reddit scraping
  • reddit API
  • API integration
  • type safety

This guide shows you how to use the FetchLayer Reddit API with TypeScript. You get full type safety on API responses with zero external dependencies.

If you want the official TypeScript package instead of defining the response types yourself, FetchLayer now ships @fetchlayer/reddit. It includes typed response interfaces for all 15 endpoints and is open source on GitHub. For the package-first version, see Reddit API npm Package for JavaScript & TypeScript.


Setup

  1. Get a free API key (no credit card)
  2. TypeScript 5+ and Node 18+ (or Bun/Deno)

Optional, if you want the official SDK with built-in endpoint types:

npm install @fetchlayer/reddit

Type Definitions

Define the response types for the endpoints you’ll use:

interface RedditPost {
  title: string;
  subreddit: string;
  author: string;
  score: number;
  numComments: number;
  url: string;
  selftext?: string;
  createdUtc: number;
}

interface SearchResponse {
  results: RedditPost[];
}

interface CommunityPostsResponse {
  subreddit: string;
  posts: RedditPost[];
}

interface PostResponse {
  title: string;
  author: string;
  score: number;
  numComments: number;
  selftext: string;
  url: string;
  comments: RedditComment[];
}

interface RedditComment {
  author: string;
  body: string;
  score: number;
  createdUtc: number;
  replies?: RedditComment[];
}

interface UserProfile {
  username: string;
  displayName: string;
  totalKarma: number;
  accountAge: string;
  isVerified: boolean;
}

interface CommunityResult {
  name: string;
  title: string;
  subscribers: number;
  description: string;
}

interface SearchCommunitiesResponse {
  results: CommunityResult[];
}

Typed API Client

const API_KEY = process.env.FETCHLAYER_API_KEY!;
const BASE_URL = 'https://fetchlayer.dev/api/reddit';

async function reddit<T>(endpoint: string, body: Record<string, unknown>): Promise<T> {
  const res = await fetch(`${BASE_URL}/${endpoint}`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });

  if (!res.ok) {
    throw new Error(`FetchLayer ${res.status}: ${await res.text()}`);
  }

  return res.json() as Promise<T>;
}

Search Reddit

const data = await reddit<SearchResponse>('search', {
  query: 'best CI/CD tools',
  sort: 'top',
  limit: 10,
});

// Full type safety — TypeScript knows data.results is RedditPost[]
for (const post of data.results) {
  console.log(`${post.title} — r/${post.subreddit} — ${post.score} pts`);
}

Get Subreddit Posts

const data = await reddit<CommunityPostsResponse>('community-posts', {
  subreddit: 'typescript',
  sort: 'top',
  time: 'month',
  limit: 20,
});

const highScoring = data.posts.filter(p => p.score > 100);
console.log(`${highScoring.length} posts with 100+ upvotes`);

Scrape a Post with Comments

const thread = await reddit<PostResponse>('post', {
  url: 'https://www.reddit.com/r/programming/comments/abc123/some_post/',
  pages: 2,
});

console.log(`${thread.title} — ${thread.comments.length} top-level comments`);

// Recursively count all comments including nested replies
function countComments(comments: RedditComment[]): number {
  return comments.reduce(
    (sum, c) => sum + 1 + (c.replies ? countComments(c.replies) : 0),
    0
  );
}

console.log(`Total comments: ${countComments(thread.comments)}`);

Get User Profile

const profile = await reddit<UserProfile>('user-profile', {
  username: 'spez',
});

console.log(`${profile.username} — ${profile.totalKarma} karma — ${profile.accountAge}`);

Search Subreddits

const communities = await reddit<SearchCommunitiesResponse>('search-communities', {
  query: 'machine learning',
});

const sorted = communities.results.sort((a, b) => b.subscribers - a.subscribers);
for (const sub of sorted) {
  console.log(`r/${sub.name} — ${sub.subscribers.toLocaleString()} subscribers`);
}

Full Example: Typed Reddit Monitoring

interface MonitorConfig {
  keyword: string;
  subreddits: string[];
  minScore: number;
}

async function monitor(config: MonitorConfig): Promise<void> {
  console.log(`Monitoring "${config.keyword}"...\n`);

  for (const sub of config.subreddits) {
    const data = await reddit<SearchResponse>('search', {
      query: config.keyword,
      subreddit: sub,
      sort: 'new',
      limit: 10,
    });

    const relevant = data.results.filter(p => p.score >= config.minScore);

    if (relevant.length > 0) {
      console.log(`--- r/${sub} (${relevant.length} matches) ---`);
      for (const post of relevant) {
        console.log(`  [${post.score}] ${post.title}`);
      }
      console.log();
    }
  }
}

await monitor({
  keyword: 'your-brand',
  subreddits: ['startups', 'SaaS', 'webdev'],
  minScore: 5,
});

What’s Next