Reddit Search API. Posts matching your search.
Posts by keyword, with Reddit's search operators. We handle the proxies, blocks and platform changes.
Reddit Search API at a glance
Searches public Reddit posts by keyword, across Reddit or in one subreddit, sorted by best match, newest, top or most comments. Each has its link, title, time, exact score and comment count, author, subreddit, NSFW and spoiler marks, preview image and every image of a gallery. Set media to get only image, video or gallery posts, and include_body for each post's text. Reddit's operators work as on Reddit: exact phrases, subreddit:, author:, site: and title:.
GET /v1/reddit/search_posts
- 1 credit per page, $0.75–$1.97 per 1,000 pages
- 22 typed fields null when unknown
- 7 posts per page, Reddit's relevance order (its search ranking)
queryis all it needs, e.g.golang generics
Send one request. Get up to 7 posts back.
Copy the request in your language, or hand it to your agent. Sign up for an API key and your first 100 credits are free.
$ npm install socialtapquery = golang genericsconst params = new URLSearchParams({
query: "golang",
since: "2026-01-01",
sort: "popular",
});
const res = await fetch(`https://socialtap.dev/v1/reddit/search_posts?${params}`, {
headers: { "x-api-key": process.env.SOCIALTAP_API_KEY ?? "" },
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
const { data, page, meta } = body;
console.log(data, meta.credits_charged);import os
import requests
res = requests.get(
"https://socialtap.dev/v1/reddit/search_posts",
params={"query": "golang", "since": "2026-01-01", "sort": "popular"},
headers={"x-api-key": os.environ["SOCIALTAP_API_KEY"]},
)
body = res.json()
if not res.ok:
raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
data, page, meta = body["data"], body["page"], body["meta"]
print(data, meta["credits_charged"])require "json"
require "net/http"
uri = URI("https://socialtap.dev/v1/reddit/search_posts")
uri.query = URI.encode_www_form('query' => 'golang', 'since' => '2026-01-01', 'sort' => 'popular')
req = Net::HTTP::Get.new(uri)
req["x-api-key"] = ENV.fetch("SOCIALTAP_API_KEY")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(req) }
body = JSON.parse(res.body)
raise "#{body["error"]["code"]}: #{body["error"]["message"]}" unless res.is_a?(Net::HTTPSuccess)
pp body["data"]
puts body["meta"]["credits_charged"]<?php
$query = http_build_query([
'query' => 'golang',
'since' => '2026-01-01',
'sort' => 'popular',
]);
$ch = curl_init('https://socialtap.dev/v1/reddit/search_posts?' . $query);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['x-api-key: ' . getenv('SOCIALTAP_API_KEY')],
]);
$body = json_decode(curl_exec($ch), true);
if (curl_getinfo($ch, CURLINFO_RESPONSE_CODE) >= 400) {
throw new RuntimeException($body['error']['code'] . ': ' . $body['error']['message']);
}
print_r($body['data']);
echo $body['meta']['credits_charged'], PHP_EOL;package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"os"
)
func main() {
q := url.Values{}
q.Set("query", "golang")
q.Set("since", "2026-01-01")
q.Set("sort", "popular")
req, err := http.NewRequest("GET", "https://socialtap.dev/v1/reddit/search_posts?"+q.Encode(), nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("x-api-key", os.Getenv("SOCIALTAP_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
var body struct {
Data json.RawMessage `json:"data"`
Page json.RawMessage `json:"page"`
Meta map[string]any `json:"meta"`
Error *struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
log.Fatal(err)
}
if body.Error != nil {
log.Fatalf("%s: %s", body.Error.Code, body.Error.Message)
}
fmt.Println(string(body.Data), body.Meta["credits_charged"])
}curl 'https://socialtap.dev/v1/reddit/search_posts?query=golang&since=2026-01-01&sort=popular' \
-H "x-api-key: $SOCIALTAP_API_KEY"{
"data": [
{
"approximate_fields": [
"type"
],
"author": {
"avatar_url": null,
"display_name": null,
"id": "t2_xdr3c",
"is_verified": null,
"url": "https://www.reddit.com/user/PremiumMeats/",
"username": "PremiumMeats"
},
"coauthors": [],
"duration_ms": null,
"hashtags": [],
"id": "t3_1qspau9",
"is_nsfw": false,
"is_pinned": null,
"is_sponsored": null,
"language": null,
"media": [],
"mentions": [],
"metrics": {
"comment_count": 100,
"like_count": 8656,
"quote_count": null,
"repost_count": null,
"save_count": null,
"share_count": null,
"view_count": null
},
"platform": "reddit",
"platform_specific": {
"reddit": {
"award_count": null,
"crosspost_of": null,
"domain": null,
"flair": null,
"is_archived": null,
"is_locked": null,
"is_spoiler": false,
"link_url": null,
"score": 8656,
"subreddit": {
"id": "t5_2sg5b",
"name": "Terraria",
"url": "https://www.reddit.com/r/Terraria/"
},
"upvote_ratio": null
}
},
"platform_type": null,
"published_at": "2026-02-01T05:07:18Z",
"text": null,
"thumbnail_url": "https://a.thumbs.redditmedia.com/9uF17zO2j_PCGq9IlJvjb2cmICxdG7y-6W2oc7z_ei0.jpg",
"title": "welcome back, 100% pickaxe power reaver shark",
"type": "link",
"unknown_fields": [
"mentions",
"media"
],
"url": "https://www.reddit.com/r/Terraria/comments/1qspau9/welcome_back_100_pickaxe_power_reaver_shark/"
},
{
"approximate_fields": [],
"author": {
"avatar_url": null,
"display_name": null,
"id": "t2_242ljnbakp",
"is_verified": null,
"url": "https://www.reddit.com/user/rpakyas/",
"username": "rpakyas"
},
"coauthors": [],
"duration_ms": null,
"hashtags": [],
"id": "t3_1ubtk8w",
"is_nsfw": false,
"is_pinned": null,
"is_sponsored": null,
"language": null,
"media": [
{
"alt_text": null,
"duration_ms": null,
"expires_at": null,
"height": null,
"thumbnail_url": "https://preview.redd.it/xedwoinqpn8h1.jpeg?width=140&height=140&crop=1%3A1%2Csmart&auto=webp&s=b85a467bdce6a4eb57e7c24bca3db7d7b4c17e2d",
"type": "image",
"url": "https://i.redd.it/xedwoinqpn8h1.jpeg",
"width": null
}
],
"mentions": [],
"metrics": {
"comment_count": 345,
"like_count": 2559,
"quote_count": null,
"repost_count": null,
"save_count": null,
"share_count": null,
"view_count": null
},
"platform": "reddit",
"platform_specific": {
"reddit": {
"award_count": null,
"crosspost_of": null,
"domain": null,
"flair": null,
"is_archived": null,
"is_locked": null,
"is_spoiler": false,
"link_url": null,
"score": 2559,
"subreddit": {
"id": "t5_40th7s",
"name": "buhaydigital",
"url": "https://www.reddit.com/r/buhaydigital/"
},
"upvote_ratio": null
}
},
"platform_type": null,
"published_at": "2026-06-21T15:55:36Z",
"text": null,
"thumbnail_url": "https://preview.redd.it/xedwoinqpn8h1.jpeg?width=140&height=140&crop=1%3A1%2Csmart&auto=webp&s=b85a467bdce6a4eb57e7c24bca3db7d7b4c17e2d",
"title": "from $4/hr to $10k/month after 13 years of WFH, my journey",
"type": "image",
"unknown_fields": [
"mentions"
],
"url": "https://www.reddit.com/r/buhaydigital/comments/1ubtk8w/from_4hr_to_10kmonth_after_13_years_of_wfh_my/"
},
{
"approximate_fields": [],
"author": {
"avatar_url": null,
"display_name": null,
"id": "t2_w6crhcklm",
"is_verified": null,
"url": "https://www.reddit.com/user/ZookeepergameMost817/",
"username": "ZookeepergameMost817"
},
"coauthors": [],
"duration_ms": null,
"hashtags": [],
"id": "t3_1wgu40p",
"is_nsfw": false,
"is_pinned": null,
"is_sponsored": null,
"language": null,
"media": [
{
"alt_text": null,
"duration_ms": null,
"expires_at": null,
"height": null,
"thumbnail_url": "https://preview.redd.it/tp97rbcz5nph1.jpeg?width=140&height=140&crop=1%3A1%2Csmart&auto=webp&s=1a0b1993df7ce5a9bab03dbd1ae823904ee5a406",
"type": "image",
"url": "https://i.redd.it/tp97rbcz5nph1.jpeg",
"width": null
}
],
"mentions": [],
"metrics": {
"comment_count": 101,
"like_count": 2372,
"quote_count": null,
"repost_count": null,
"save_count": null,
"share_count": null,
"view_count": null
},
"platform": "reddit",
"platform_specific": {
"reddit": {
"award_count": null,
"crosspost_of": null,
"domain": null,
"flair": null,
"is_archived": null,
"is_locked": null,
"is_spoiler": false,
"link_url": null,
"score": 2372,
"subreddit": {
"id": "t5_fvy1km",
"name": "SATNA_PROJECT",
"url": "https://www.reddit.com/r/SATNA_PROJECT/"
},
"upvote_ratio": null
}
},
"platform_type": null,
"published_at": "2026-09-15T08:06:21Z",
"text": null,
"thumbnail_url": "https://preview.redd.it/tp97rbcz5nph1.jpeg?width=140&height=140&crop=1%3A1%2Csmart&auto=webp&s=1a0b1993df7ce5a9bab03dbd1ae823904ee5a406",
"title": "Anthropic hackathon winner just open-sourced his entire Claude Code setup 🔥",
"type": "image",
"unknown_fields": [
"mentions"
],
"url": "https://www.reddit.com/r/SATNA_PROJECT/comments/1wgu40p/anthropic_hackathon_winner_just_opensourced_his/"
}
],
"page": {
"has_more": true,
"next_cursor": "c1.EXAMPLE_CURSOR",
"next_cursor_expires_at": "2026-10-26T12:00:00Z",
"end_reason": null
},
"meta": {
"request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
"platform": "reddit",
"source": "page",
"is_cached": false,
"credits_charged": 1,
"latency_ms": 603,
"fetched_at": "2026-10-25T12:00:00Z",
"input": null,
"credits_remaining": 9999,
"client_request_id": null,
"warnings": []
}
}import { SocialTap } from "socialtap";
const client = new SocialTap(); // apiKey defaults to process.env.SOCIALTAP_API_KEY
const res = await client.reddit.searchPosts.list({ query: "golang", sort: "popular", since: "2026-01-01" });
console.log(res.data);
console.log(res.credits.charged, res.meta.request_id);import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
public class Main {
public static void main(String[] args) throws Exception {
String query = "query=" + encode("golang")
+ "&since=" + encode("2026-01-01")
+ "&sort=" + encode("popular");
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://socialtap.dev/v1/reddit/search_posts?" + query))
.header("x-api-key", System.getenv("SOCIALTAP_API_KEY"))
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
// An error is {"error": {"code", "message", ...}}; success is {data, meta}, meta.credits_charged its price.
if (response.statusCode() >= 400) throw new RuntimeException(response.body());
System.out.println(response.body());
}
static String encode(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8);
}
}using System.Text.Json;
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("x-api-key", Environment.GetEnvironmentVariable("SOCIALTAP_API_KEY"));
var query = string.Join("&",
"query=" + Uri.EscapeDataString("golang"),
"since=" + Uri.EscapeDataString("2026-01-01"),
"sort=" + Uri.EscapeDataString("popular"));
var res = await http.GetAsync("https://socialtap.dev/v1/reddit/search_posts?" + query);
using var body = JsonDocument.Parse(await res.Content.ReadAsStringAsync());
if (!res.IsSuccessStatusCode)
{
var error = body.RootElement.GetProperty("error");
throw new Exception($"{error.GetProperty("code")}: {error.GetProperty("message")}");
}
Console.WriteLine(body.RootElement.GetProperty("data"));
Console.WriteLine(body.RootElement.GetProperty("meta").GetProperty("credits_charged"));// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }, serde_json = "1"
use std::env;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let res = reqwest::blocking::Client::new()
.get("https://socialtap.dev/v1/reddit/search_posts")
.query(&[("query", "golang"), ("since", "2026-01-01"), ("sort", "popular")])
.header("x-api-key", env::var("SOCIALTAP_API_KEY")?)
.send()?;
let ok = res.status().is_success();
let body: serde_json::Value = res.json()?;
if !ok {
return Err(format!("{}: {}", body["error"]["code"], body["error"]["message"]).into());
}
println!("{} {}", body["data"], body["meta"]["credits_charged"]);
Ok(())
}200 OK · GET https://socialtap.dev/v1/reddit/search_postsLong arrays and strings are shortened here. Real responses are complete.Docs One schema on 21 platforms.
The response reference lists every field, its type and when it is null. See the full schema.
Null means unknown
A field Reddit doesn't show is null, never zero or an empty string, so a real zero always means zero.
What it accepts
Words or a phrase, matched by Reddit's search against post titles and text.
Write one parser
Reddit, TikTok, Instagram and 18 more platforms answer in these fields, so the code that reads one reads them all.
platformstring- Platform ID (tiktok, youtube, …).
idstring- Platform-native post ID (string; Instagram shortcode, Reddit with its t3_ prefix).
urlstring- Canonical post URL.
typestring- Normalized content shape. New values may be added; treat unknown values as other.
platform_typestring- The platform's own product label, lowercase (reel, short, story, live, tweet, …).
titlestring- Headline (YouTube title, Reddit title); null on caption-only platforms.
textstring- Caption, description or body as plain text.
languagestring- BCP-47 language of text, when the platform states it.
Live data from 33 platforms.
What teams build with the Reddit Search API.
Monitor new posts about a product
Find the most discussed posts on a topic
Watch a keyword in one subreddit
Find image and video posts about a topic
Gather discussions for market research
Good to know before you build.
- Reddit's search results show no post body, so text is null and mentions is listed in unknown_fields. include_body reads the bodies from Reddit's feed of the page's posts with a second upstream request per page, on every sort. A post the feed doesn't list keeps a null text, and the Reddit Post API returns the full post.
- type is read from the result's preview: carousel for a gallery, video for a Reddit video's poster, image for an uploaded image and link for an external page's preview. A result without a preview reads as text and an old post's legacy thumbnail as link, both listed in approximate_fields. With include_body, type is exact.
- media finds posts whose image, video or gallery was uploaded to Reddit, and with image or video the type is exact. A post that links to media on another site, such as YouTube or Imgur, is not included: search those with site: in query instead.
- With media=carousel, a result that shows its gallery is an exact carousel with every image in media. One that shows none is carousel in approximate_fields, with media in unknown_fields.
- With media, most results on popular and most_comments show only a small thumbnail: the post's media item then has a null url, and with any its type is image, listed in approximate_fields with media. A video's url is always null in search results. The Reddit Post API returns the media file.
- Scores are exact, but Reddit shows a score at or below zero as 0, so a 0 score is null.
- Logged out, Reddit's search leaves out NSFW posts and posts of quarantined subreddits.
- A subreddit that doesn't exist, or that Reddit hides (banned, private), returns an empty page.
1 credit per page. Failed requests are free.
Buy credits once and spend them on any endpoint, on any platform.
| Source | Price per successful page | Per 1,000 pages |
|---|---|---|
Public page page | 1 credit | $0.75–$1.97 |
- Cache hits are free.
- Credits from packs and top-ups never expire.
- A monthly plan's credits are spent first, and what is left of them ends at each renewal.
- Prices exclude tax: sales tax is added at checkout where it applies.
- Outside the US, plans and packs are sold to businesses: checkout asks for your VAT, GST or other business tax ID.
Questions about the Reddit Search API.
More in the API reference.
How much does the Reddit Search API cost?
How do I get the next page?
Try it with your own search.
Type it in the playground, or copy the request into your code.
- No credit card
- Failed requests are free
- Works on all 218 endpoints