Instagram Search API. Reels matching your search.
Reels matching a keyword, with plays and likes. We handle the proxies, blocks and platform changes.
Instagram Search API at a glance
Returns the public Instagram reels for a keyword, as Instagram's logged-out search shows them, a page at a time in its own ranking. Each has its link, caption, hashtags, mentions, publish time, author with verified badge, play, like and comment counts, length, cover and video file.
GET /v1/instagram/search_posts
- 1 credit per page, $0.75–$1.97 per 1,000 pages
- 22 typed fields null when unknown
- 24 reels per page, Instagram's ranking for the keyword (its popular page's order)
queryis all it needs, e.g.vegan pasta recipe
Send one request. Get up to 24 reels 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 = vegan pasta recipeconst params = new URLSearchParams({
query: "vegan pasta recipe",
});
const res = await fetch(`https://socialtap.dev/v1/instagram/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/instagram/search_posts",
params={"query": "vegan pasta recipe"},
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/instagram/search_posts")
uri.query = URI.encode_www_form('query' => 'vegan pasta recipe')
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' => 'vegan pasta recipe',
]);
$ch = curl_init('https://socialtap.dev/v1/instagram/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", "vegan pasta recipe")
req, err := http.NewRequest("GET", "https://socialtap.dev/v1/instagram/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 -G 'https://socialtap.dev/v1/instagram/search_posts' \
--data-urlencode 'query=vegan pasta recipe' \
-H "x-api-key: $SOCIALTAP_API_KEY"{
"data": [
{
"approximate_fields": [],
"author": {
"avatar_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.82787-19/761168339_18330615538259673_8663040992591739350_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=104&ig_cache_key=GNOBXi3ZFqwDmR9BANb5E07iTTl4bmNDAQAB1501500j-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=S…",
"display_name": null,
"id": "7786451672",
"is_verified": false,
"url": "https://www.instagram.com/veganandfeastin/",
"username": "veganandfeastin"
},
"coauthors": [],
"duration_ms": 12900,
"hashtags": [
"veganpasta",
"tofurecipes",
"veganrecipes"
],
"id": "Ddr0TPPSmMm",
"is_nsfw": null,
"is_pinned": null,
"is_sponsored": null,
"language": null,
"media": [
{
"alt_text": null,
"duration_ms": 12900,
"expires_at": "2026-10-25T18:00:00Z",
"height": 1920,
"thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/824422121_2194005971160502_2983956026062404200_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=108&ig_cache_key=Mzk5MzUxNTUxNTA0NTM3MjcxMA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
"type": "video",
"url": "https://scontent-atl3-2.cdninstagram.com/o1/v/t2/f2/m86/AQMLNCgISLW3dxSgrJybwxb-22qxIIioAj01cakwofcPtXdtZgIC_VI-UAa9VRGPEyMkUHLz_LtnQAo19lQCIKnr7713qLTE5q5uHRQ.mp4?_nc_cat=104&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-2.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
"width": 1080
}
],
"mentions": [],
"metrics": {
"comment_count": 160,
"like_count": 17516,
"quote_count": null,
"repost_count": null,
"save_count": null,
"share_count": null,
"view_count": 438314
},
"platform": "instagram",
"platform_specific": {
"instagram": {
"is_ai_generated": null,
"link": null,
"location": null
}
},
"platform_type": "reel",
"published_at": "2026-09-24T21:09:56Z",
"text": "silken tofu makes this linguini ridiculously creamy. an easy high protein vegan pasta that tastes way more indulgent than it actually is\n\n#veganpasta #tofurecipes #veganrecipes #easyveganmeals #veganfood",
"thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/824422121_2194005971160502_2983956026062404200_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=108&ig_cache_key=Mzk5MzUxNTUxNTA0NTM3MjcxMA%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
"title": null,
"type": "video",
"unknown_fields": [
"coauthors",
"mentions"
],
"url": "https://www.instagram.com/reel/Ddr0TPPSmMm/"
},
{
"approximate_fields": [],
"author": {
"avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-19/579635209_17986846517910339_21160113348381217_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=103&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_gid=S…",
"display_name": null,
"id": "57257590338",
"is_verified": false,
"url": "https://www.instagram.com/ourhealthy_kitchen/",
"username": "ourhealthy_kitchen"
},
"coauthors": [],
"duration_ms": 29674,
"hashtags": [],
"id": "DLs0pzUy701",
"is_nsfw": null,
"is_pinned": null,
"is_sponsored": null,
"language": null,
"media": [
{
"alt_text": null,
"duration_ms": 29674,
"expires_at": "2026-10-25T18:00:00Z",
"height": 1920,
"thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/515092177_4103543953235130_6064318765958255274_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=103&ig_cache_key=MzY2OTUzOTM2NzQyNjk2NDc4OQ%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
"type": "video",
"url": "https://scontent-atl3-1.cdninstagram.com/o1/v/t2/f2/m86/AQMlakTQEwte_5YCnwCH8oTlb1zO381trcYHZ-muqkr4Su7QGQCWQ46FHa5okk9zY_sHWTvfaRNPRpo53d-bRZw7y8nI40sDDC6mOfQ.mp4?_nc_cat=110&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
"width": 1080
}
],
"mentions": [
"jovialfoods"
],
"metrics": {
"comment_count": 215,
"like_count": 8552,
"quote_count": null,
"repost_count": null,
"save_count": null,
"share_count": null,
"view_count": 206291
},
"platform": "instagram",
"platform_specific": {
"instagram": {
"is_ai_generated": null,
"link": null,
"location": null
}
},
"platform_type": "reel",
"published_at": "2025-07-04T21:09:34Z",
"text": "Save this Rasta Pasta Recipe Below! 💚Wanna take a class with me?? Use the link below or in my bio to sign up to be the first to know when my next class opens! \n\nhttps://mailchi.mp/56d013b1a8c1/chefvictoriarecipes \n\nVegan + GF Rasta Pasta \nIngredients\n\n \n6 oz dry gluten-free past…",
"thumbnail_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.71878-15/515092177_4103543953235130_6064318765958255274_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=103&ig_cache_key=MzY2OTUzOTM2NzQyNjk2NDc4OQ%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=2…",
"title": null,
"type": "video",
"unknown_fields": [
"coauthors"
],
"url": "https://www.instagram.com/reel/DLs0pzUy701/"
},
{
"approximate_fields": [],
"author": {
"avatar_url": "https://scontent-atl3-1.cdninstagram.com/v/t51.82787-19/753231472_18120289603884290_3428669718987860154_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=110&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=24&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_gid…",
"display_name": null,
"id": "26583988289",
"is_verified": false,
"url": "https://www.instagram.com/lifeofagreedyvegan/",
"username": "lifeofagreedyvegan"
},
"coauthors": [],
"duration_ms": 22475,
"hashtags": [],
"id": "C3dK9xOKpNu",
"is_nsfw": null,
"is_pinned": null,
"is_sponsored": null,
"language": null,
"media": [
{
"alt_text": null,
"duration_ms": 22475,
"expires_at": "2026-10-25T18:00:00Z",
"height": 1280,
"thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.71878-15/503216684_3619178498386054_42034667321398688_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=104&ig_cache_key=MzMwNDg0NTkyNjc2NDAyNDY4Ng%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&…",
"type": "video",
"url": "https://scontent-atl3-1.cdninstagram.com/o1/v/t2/f2/m82/AQPaJ473Q8zbT1RSqNP0R6TS7OxAUqG2Y5oCJz2wISHbGgxqqTx6jeBX-ucjwToegLLcDDSIft_Vb-TSCqGvTfdJgB62Kqxud5tAm9Y.mp4?_nc_cat=103&_nc_sid=SCRUBBED&_nc_ht=scontent-atl3-1.cdninstagram.com&_nc_ohc=SCRUBBED&efg=SCRUBBED&ccb=SCRUBBED&vs=S…",
"width": 720
}
],
"mentions": [],
"metrics": {
"comment_count": 7,
"like_count": null,
"quote_count": null,
"repost_count": null,
"save_count": null,
"share_count": null,
"view_count": null
},
"platform": "instagram",
"platform_specific": {
"instagram": {
"is_ai_generated": null,
"link": null,
"location": null
}
},
"platform_type": "reel",
"published_at": "2024-02-17T16:48:25Z",
"text": "let’s plate up one of my fav meals: homemade ✨carbonara✨\n\nrecipe 🍝🌱\n\nIngredients \n* 25g dairy-free butter (I used flora)\n* 30g all purpose flour\n* 275ml dairy-free milk (I used oat) \n* Add nutritional yeast to taste\n* 1/2 tsp garlic powder\n* 1/2 tsp smoked paprika\n* 1/2 tsp turme…",
"thumbnail_url": "https://scontent-atl3-2.cdninstagram.com/v/t51.71878-15/503216684_3619178498386054_42034667321398688_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=104&ig_cache_key=MzMwNDg0NTkyNjc2NDAyNDY4Ng%3D%3D.3-ccb7-5&ccb=SCRUBBED&_nc_sid=SCRUBBED&efg=SCRUBBED&_nc_ohc=SCRUBBED&_nc_oc=SCRUBBED&_nc_zt=23&…",
"title": null,
"type": "video",
"unknown_fields": [
"coauthors",
"mentions"
],
"url": "https://www.instagram.com/reel/C3dK9xOKpNu/"
}
],
"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": "instagram",
"source": "api",
"is_cached": false,
"credits_charged": 1,
"latency_ms": 1281,
"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.instagram.searchPosts.list({ query: "vegan pasta recipe" });
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("vegan pasta recipe");
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://socialtap.dev/v1/instagram/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("vegan pasta recipe"));
var res = await http.GetAsync("https://socialtap.dev/v1/instagram/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/instagram/search_posts")
.query(&[("query", "vegan pasta recipe")])
.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/instagram/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 Instagram doesn't show is null, never zero or an empty string, so a real zero always means zero.
What it accepts
Keywords, matched as Instagram's public results pages match them (instagram.com/popular/<keywords>/): case, a leading # or @ and hyphens are ignored.
Write one parser
Instagram, TikTok, Facebook 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 Instagram Search API.
Find the most-watched reels on a topic
Monitor reels mentioning a brand or product
Collect reels on a keyword for research
Good to know before you build.
- Results are Instagram's public results page for the keyword (instagram.com/popular/…), the only search it offers logged out, so they are reels in its order.
- Instagram publishes such a page for many keywords but not all, and a keyword without one returns no results, ending with end_reason end.
- Results are ranked, not ordered by time, so since and until filter each page by published_at.
- Share and save counts and the author's display name are null: the page doesn't show them. If play counts fail on a page, it comes without view counts and verified badges, with a partial_data warning.
- Media URLs are Instagram CDN links that expire at media[].expires_at.
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 |
|---|---|---|
Platform API api | 1 credit | $0.75–$1.97 |
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 Instagram Search API.
More in the API reference.
Is this the same as Instagram's popular search?
Does it search hashtags?
How much does the Instagram 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