Refetcher API · operational
Live status at /status
Developer docs

Refetcher API

One clean HTTP endpoint for real-time Instagram, TikTok, Facebook, X and YouTube data — normalized, pay-as-you-go, and built for developers.

Primary endpoint
POST https://api.refetcher.com/
Batching 10 default · 50 hard limit
Billing Failed targets are never charged

Refetch(er) provides one unified scrape entry point for posts, profiles, and YouTube resources. X profile feeds return posts only, while an individual X post's metrics.comments value is the numeric reply count.

To scrape a target you provide a Refetch(er) API key plus a public URL, username, profile URL, channel URL, or batch array. Refetch(er) never asks for social account logins, platform cookies, session tokens, proxy settings, regions, or infrastructure URLs. Successful media results return normalized metrics, post, author, and media fields when public. Profile and channel results return normalized public account metadata plus optional lightweight recent media.

When a platform does not expose a field publicly, the API returns null, false, or an explicit metricAvailability state instead of guessing.

New to Refetch(er)? All new accounts receive $10 of free trial credit instantly on signup. Prepay only for what you run — and failed requests are never billed.

Authentication

All scrape and balance requests require an API key generated from your dashboard. Public status and health routes are readable without a key. Pass your key in either of these HTTP headers:

HeaderValue formatDescription
X-API-Keypc_live_...The preferred header format for custom requests.
AuthorizationBearer pc_live_...Alternative standard authentication header.
Keep your key secure. Never expose API keys in frontend client code (browsers, client-side scripts). Always proxy requests to Refetch(er) through your own backend server.

Endpoints

Refetch(er) serves all live scrape requests from a single endpoint, accepting POST JSON payloads that determine which platform and resource to fetch.

POST https://api.refetcher.com/
GET https://api.refetcher.com/v1/account/balance

The route alias POST https://api.refetcher.com/v1/scrape is fully supported for compatibility, but we recommend calling the root path directly.

GET / and GET /status return the public API status page. GET /health returns a lightweight JSON health response.

Check account balance

Use your existing API key to read the amount currently available for new API requests. This endpoint is read-only: it does not run a scrape, create a request log, reserve credits, or add a billing transaction.

GET https://api.refetcher.com/v1/account/balance
curl https://api.refetcher.com/v1/account/balance \
  -H "Authorization: Bearer pc_live_xxx"

Successful response

{
  "success": true,
  "requestId": "balance-request-id",
  "balance": {
    "currency": "USD",
    "balanceUsd": 9.9991,
    "ledgerBalanceUsd": 10,
    "pendingUsageUsd": 0.0009,
    "reservedBalanceUsd": 0,
    "unitPriceUsd": 0.0009,
    "maxBillableUnits": 11110,
    "asOf": "2026-08-11T18:00:00.000Z"
  }
}
FieldMeaning
balanceUsdThe balance currently available to new API requests, after in-flight and queued usage is accounted for.
ledgerBalanceUsdThe durable balance after completed settlements. It can briefly be higher while a successful request is settling.
pendingUsageUsdCredits already unavailable to new requests but not yet reflected in the durable ledger.
reservedBalanceUsdCredits held by active durable reservations.
unitPriceUsdThe current price of one successful billable unit.
maxBillableUnitsHow many successful units the current balance can fund. Your separate per-request target limit still applies.
asOfThe time at which the snapshot was calculated.
Rate limit: 60 balance checks per minute per API key, plus a broader IP abuse limit. Responses include RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset. A 429 response also includes Retry-After. Balance responses are never cached.

Supported resources

Every resource uses the same endpoint. The API detects a platform from a full url or profileUrl. For a bare Instagram, TikTok, Facebook, or X username, you must include platform; handles alone are ambiguous across networks.

Instagram Post/Reel

Metrics, caption, hashtags, dimensions, duration, thumbnails, and public media source URLs for posts and reels.

url

Instagram Profile

Public profile metadata and optional links-only recent media with browserless cursor pagination.

usernameprofileUrl

TikTok Video

Views, likes, comments, shares, saves, author data, media, music, and optional embedded comments.

url

TikTok Profile

Public creator metadata plus recent posts with available engagement, post/slideshow metadata, sound, media, and author fields.

usernameprofileUrl

Facebook Post/Reel

Public reactions, comments, shares, views for videos/Reels, and photo or carousel media children when exposed.

url

Facebook Profile

Public profile metadata and recent post links with browserless cursor pagination.

usernameprofileUrl

X Post

Views, likes, retweets, replies, and tweet media attachments for public X posts.

url

X Profile

Public profile metadata including followers, following, and tweet counts.

usernameprofileUrl

YouTube Video

Views, likes, comments, video metadata, and optional newest public top-level comments for videos or Shorts.

urlincludeRecentComments

YouTube Channel

Subscribers, total views, video count, thumbnails, and optional links-only recent uploads. Use channelVideos for upload metrics.

channelUrlhandle
Availability notes: Instagram, Facebook, and YouTube channel profile responses return account metadata plus lightweight recent-media references when requested. TikTok profile responses can contain the available per-post engagement, metadata, sound, media, and author fields; YouTube's channelVideos resource includes per-video upload metrics. Facebook can still stop a timeline read early; check pageInfo.recentPosts.incomplete and limitations before treating a requested window as complete.

Request fields

Send a JSON body with one target field (and optional modifiers). Provide exactly one of the URL/username/channel fields per single request, or an array for a batch.

FieldTypeDefaultDescription
urloptstringnullURL of a single Instagram post/profile, TikTok video/profile, Facebook post/profile, YouTube video, or YouTube channel. Provide one target field.
urlsoptstring[][]List of post/profile/video/channel URLs to scrape in parallel. Default limit 10, hard limit 50; your account's configured limit is enforced for every key.
typeoptstringnullUse "channel" for YouTube channel profile data or "channelVideos" for latest uploads. Video/post metrics are inferred from the URL by default.
platformoptstringnullRequired with username or usernames: "instagram", "facebook", "tiktok", "x", or "twitter". A full URL already identifies its platform.
usernameoptstringnullInstagram, TikTok, Facebook, or X username for a profile scrape. Requires platform to prevent an ambiguous handle from scraping the wrong network.
usernamesoptstring[][]Usernames for batch profile scraping. Requires platform; one platform applies to the batch.
profileUrloptstringnullInstagram, TikTok, Facebook, or X profile URL for a single profile scrape.
profileUrlsoptstring[][]Profile URLs for batch profile scraping.
channelUrloptstringnullYouTube channel URL, @handle, legacy /user/ URL, or /channel/ ID URL.
channelUrlsoptstring[][]Batch YouTube channel targets.
channelIdoptstringnullRaw YouTube channel ID such as UC....
handleoptstringnullYouTube @handle when platform is "youtube" or type is "channel"/"channelVideos".
includeRecentPostsoptbooleanfalseWhen scraping Instagram, TikTok, Facebook, or X profiles, include recent public posts. TikTok and X profile posts can contain exposed per-post fields; other profile sources return lightweight references.
sortoptstring"latest"X profile feeds: "latest" for genuinely newest-first posts or "popular" for X's popularity-ranked public selection.
recentPostsLimitoptinteger12 / 5 for X / 3 for FacebookCompatibility alias for profile pagination. It maps to the platform page size: ceil(limit / 12) for Instagram and TikTok; ceil(limit / 5) for X; ceil(limit / 3) for Facebook. Use pages for new integrations.
pagesoptinteger1Instagram, TikTok, Facebook, and X profiles. Number of recent-media pages to request, 1–25. Instagram and TikTok return up to 12 references per page; X returns up to 5 posts per page for both latest and popular and follows X's anonymous bottom cursor when the profile exposes one; Facebook returns up to 3 post links per page. Each returned page counts as one successful scrape at the standard $0.90 per 1,000; failed or empty pages are free. A request can reserve at most 50 billable units total.
afteroptstringnullFacebook profile only. Opaque continuation cursor from pageInfo.recentPosts.endCursor. cursor and endCursor are accepted aliases.
includeRecentCommentsoptbooleanfalseWhen scraping a YouTube video, include newest public top-level comments. For TikTok video, include embedded public comments if present in the page payload.
recentCommentsLimitoptinteger20Max comments to request for YouTube or embedded TikTok comments. Range 1–100.
includeRecentVideosoptbooleantrue for type:"channel"When scraping a YouTube channel profile, include latest uploads as links-only references. Use type:"channelVideos" for per-video metrics.
recentVideosLimitoptinteger12Max YouTube uploads to request. Range 1–50.
requiredFieldsoptstring[]["views","likes","comments"]Enforces validation on applicable returned metrics. Accepted: views, plays, likes, reactions, comments, topLevelComments, shares, and saves. The three extended fields are Facebook-specific; image/carousel views and plays are automatically treated as not applicable.

Normalized profile schema

Instagram, TikTok, Facebook, and X profile results share one normalized profile object. Fields a platform does not expose return null or false. Each platform page lists its own additions on top of this core.

idhandlenamebiographyfollowersfollowingtotalPoststotalVideostotalLikestalkingAboutwereHerehighlightReelCountisPrivateisVerifiedisBusinessAccountisProfessionalAccountcategoryNameexternalUrlprofilePicUrlprofilePicUrlHd

Batch scrape

Query multiple targets concurrently in one call by passing an array under urls, profileUrls, or a compatible URL field. Optionally supply requiredFields to enforce metric presence.

{
  "urls": [
    "https://www.instagram.com/reel/C8xExampleAbc/",
    "https://www.tiktok.com/@creator/video/7398210000000000000",
    "https://www.facebook.com/reel/2781078362247521/",
    "https://x.com/SpaceX/status/2064099405758906727",
    "https://www.youtube.com/watch?v=8jPQjjsBbIc"
  ],
  "requiredFields": ["views", "likes", "comments"]
}
The default batch limit is 10 targets and the service hard limit is 50; your account's configured limit applies to every current and future API key. Instagram images/carousels and Facebook image/photo/carousel/text posts have no aggregate views metric; Facebook also has no play metric for those formats. They still succeed with the corresponding values set to null and availability set to "not_applicable". Include "shares" or "saves" in requiredFields only when every target can return them.

Quickstart code

Copy-paste templates to send your first request. Swap in your API key and a target URL.

curl -X POST https://api.refetcher.com/ \
  -H "X-API-Key: pc_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.instagram.com/reel/C8xExampleAbc/"
  }'
const apiKey = 'pc_live_your_key_here';
const urlToScrape = 'https://www.instagram.com/reel/C8xExampleAbc/';

fetch('https://api.refetcher.com/', {
  method: 'POST',
  headers: {
    'X-API-Key': apiKey,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: urlToScrape
  })
})
  .then(res => res.json())
  .then(data => {
    if (data.success && data.results[0].success) {
      const metrics = data.results[0].metrics;
      console.log(`Views: ${metrics.views}, Likes: ${metrics.likes}`);
    } else {
      console.error('Scrape failed:', data.results[0].error || 'Unknown error');
    }
  })
  .catch(err => console.error('Request error:', err));
import requests
import json

api_key = "pc_live_your_key_here"
url_to_scrape = "https://www.instagram.com/reel/C8xExampleAbc/"

response = requests.post(
    "https://api.refetcher.com/",
    headers={
        "X-API-Key": api_key,
        "Content-Type": "application/json"
    },
    json={
        "url": url_to_scrape
    }
)

if response.status_code == 200:
    data = response.json()
    if data.get("success") and data["results"][0]["success"]:
        metrics = data["results"][0]["metrics"]
        print(f"Views: {metrics['views']}, Likes: {metrics['likes']}")
    else:
        print("Scrape failed:", data["results"][0].get("error", "Unknown error"))
else:
    print(f"Server error: {response.status_code}", response.text)

Instagram

Post / Reel Profile POSTapi.refetcher.com/

Scrape public Instagram posts, Reels, and profiles. Post and Reel requests return normalized metrics, post, author, and a media object; profile requests return account metadata with optional cursor-paginated recent media.

Post & Reel

Send a single url string in the body. The response returns metrics, post, author, and a media object — media fields include thumbnail/video/audio source URLs, duration, dimensions, separate play/view counts, music attribution, and carousel children when Instagram exposes them. Shares and saves remain null when not publicly available.

{
  "url": "https://www.instagram.com/reel/C8xExampleAbc/"
}
{
  "url": "https://www.instagram.com/reel/C8xExampleAbc/",
  "platform": "instagram",
  "success": true,
  "metrics": {
    "views": 1284203,
    "likes": 48211,
    "comments": 1903,
    "shares": null,
    "saves": null
  },
  "metricAvailability": {
    "views": "available",
    "likes": "available",
    "comments": "available",
    "shares": "unavailable",
    "saves": "unavailable"
  },
  "post": {
    "id": "C8xExampleAbc",
    "shortcode": "C8xExampleAbc",
    "normalizedUrl": "https://www.instagram.com/reel/C8xExampleAbc/",
    "publishedAt": "2026-06-01T08:30:00.000Z",
    "caption": "Check out our new release! #refetcher #api",
    "type": "video",
    "productType": "clips",
    "hashtags": ["refetcher", "api"],
    "mentions": [],
    "location": null,
    "commentsDisabled": false,
    "isPinned": false,
    "isSponsored": false
  },
  "author": {
    "id": "123456789",
    "handle": "creators_hub",
    "name": "Creators Hub",
    "followers": 94200,
    "isVerified": false,
    "profilePicUrl": "https://..."
  },
  "media": {
    "thumbnailUrl": "https://...",
    "videoUrl": "https://...",
    "audioUrl": "https://...",
    "durationSeconds": 21.4,
    "width": 1080,
    "height": 1920,
    "playCount": 1284203,
    "viewCount": null,
    "altText": null,
    "music": {
      "id": "987654321",
      "title": "Original audio",
      "artist": "creators_hub",
      "isOriginalAudio": true
    },
    "children": []
  },
  "scrapedAt": "2026-06-05T10:15:30.000Z"
}

Supported URL shapes

/reel//reels//p//tv/

Image and carousel posts return metrics.views: null with metricAvailability.views: "not_applicable". For Reels, metrics.views uses the public play count; when Instagram exposes both values, the raw media object keeps media.playCount and media.viewCount separate. URL normalization can return the canonical shortcode under /reel/ even for some /p/ inputs, so use post.type and metricAvailability to distinguish carousels/images from videos.

Media URL lifetime: Instagram CDN URLs are source URLs and may expire. Store the file in your own infrastructure when you need a durable asset.

Profile

Send a username or a profile URL. Use includeRecentPosts to also return lightweight recent media references. Instagram profile requests use the shared pages model: 1–25 pages, up to 12 references per page, without a browser or login. Results beyond the first page are fetched with Instagram's timeline cursor.

{
  "platform": "instagram",
  "username": "nasa",
  "includeRecentPosts": true,
  "recentPostsLimit": 36
}
{
  "profileUrl": "https://www.instagram.com/nasa/",
  "includeRecentPosts": false
}
{
  "url": "https://www.instagram.com/nasa/",
  "platform": "instagram",
  "type": "profile",
  "success": true,
  "profile": {
    "id": "528817151456180",
    "handle": "nasa",
    "name": "NASA",
    "biography": "Exploring the universe and our home planet.",
    "followers": 97400000,
    "following": 78,
    "totalPosts": 4123,
    "totalVideos": 171,
    "totalLikes": null,
    "highlightReelCount": 42,
    "isPrivate": false,
    "isVerified": true,
    "isBusinessAccount": false,
    "isProfessionalAccount": true,
    "categoryName": "Science, Technology & Engineering",
    "externalUrl": "https://www.nasa.gov/",
    "profilePicUrl": "https://...",
    "profilePicUrlHd": "https://..."
  },
  "recentPosts": [],
  "pageInfo": {
    "recentPosts": {
      "hasNextPage": true,
      "endCursor": "...",
      "requestedLimit": 36,
      "returnedCount": 36
    }
  },
  "scrapedAt": "2026-06-05T10:15:30.000Z"
}

The response returns type: "profile", a profile object, and optional recentPosts or recentVideos arrays when recent media is requested.

Field reference

Successful responses can include these normalized fields when Instagram exposes them. Unavailable fields return null, false, an explicit metricAvailability value, or are omitted when empty.

ObjectFields
postidshortcodenormalizedUrlpublishedAtcaptiontypeproductTypehashtagsmentionsregionlanguagelocationcommentsDisabledisPinnedisSponsored
authoridhandlenamefollowersfollowingtotalLikesvideoCountbioisVerifiedprofilePicUrl
mediathumbnailUrlvideoUrlaudioUrldurationSecondswidthheightplayCountviewCountaltTextmusicchildren
profileShared profile schema plus talkingAbout and wereHere when present.
recentVideos, pageInforecentVideos can contain profile reels. pageInfo.recentVideos mirrors the cursor shape: hasNextPage, endCursor, requestedLimit, returnedCount, pagesRequested, pagesFetched, incomplete.

TikTok

Video Profile POSTapi.refetcher.com/

Scrape public TikTok videos and creator profiles. Video requests return engagement metrics. Profile responses can contain creator metadata, recent posts, per-post engagement, post/slideshow metadata, sound, media, and author fields.

Video

Send the canonical tiktok.com/@creator/video/7398210000000000000 URL in the body. Redirect-only short links such as vm.tiktok.com are not accepted. Responses populate views, likes, comments, shares, and saves when available. recentComments is present only when requested and may be an empty array when TikTok does not include embedded comments in the public page payload.

{
  "url": "https://www.tiktok.com/@creator/video/7398210000000000000",
  "includeRecentComments": true,
  "recentCommentsLimit": 3
}
{
  "url": "https://www.tiktok.com/@creator/video/7398210000000000000",
  "platform": "tiktok",
  "success": true,
  "metrics": {
    "views": 2400000,
    "likes": 98400,
    "comments": 3210,
    "shares": 12200,
    "saves": 18400
  },
  "metricAvailability": {
    "views": "available",
    "likes": "available",
    "comments": "available",
    "shares": "available",
    "saves": "available"
  },
  "post": {
    "id": "7398210000000000000",
    "shortcode": null,
    "normalizedUrl": "https://www.tiktok.com/@creator/video/7398210000000000000",
    "publishedAt": "2026-06-01T08:30:00.000Z",
    "caption": "Example video caption",
    "type": "video",
    "productType": null,
    "hashtags": [],
    "mentions": [],
    "region": "US",
    "language": "en",
    "location": null,
    "commentsDisabled": false,
    "isPinned": false,
    "isSponsored": false
  },
  "author": {
    "id": "123456789",
    "handle": "creator",
    "name": "Creator Name",
    "followers": 312000,
    "following": 128,
    "totalLikes": 9800000,
    "videoCount": 420,
    "bio": "Creator bio",
    "isVerified": false,
    "profilePicUrl": "https://..."
  },
  "media": {
    "type": "video",
    "thumbnailUrl": "https://...",
    "videoUrl": "https://...",
    "durationSeconds": 18,
    "width": 1080,
    "height": 1920,
    "ratio": "720p"
  },
  "music": {
    "id": "music-id",
    "title": "Original sound",
    "authorName": "Creator Name",
    "durationSeconds": 18,
    "original": true,
    "playUrl": "https://...",
    "coverUrl": "https://..."
  },
  "recentComments": [
    {
      "id": "comment-id",
      "text": "Example public comment",
      "likes": 12,
      "replies": 1,
      "publishedAt": "2026-06-01T09:00:00.000Z",
      "author": {
        "id": "comment-author-id",
        "handle": "viewer",
        "name": "Viewer",
        "isVerified": false,
        "profilePicUrl": "https://..."
      }
    }
  ],
  "scrapedAt": "2026-06-09T10:15:30.000Z"
}

Profile

Send a username or profile URL. TikTok profile responses can contain public creator metadata, recent posts, views, likes, comments, shares, saves, publish time, caption, hashtags, ad and pinned flags, slideshow details, duration, aspect ratio, author details, media, and music. Fields that TikTok does not expose return null or unavailable; never interpret isPinned: null as false. recentVideos is the video-only compatibility view, while image slideshows remain in recentPosts.

Repost count: TikTok's logged-out profile and video sources return a zero placeholder rather than a trustworthy repost counter. Refetcher returns reposts: null and metricAvailability.reposts: "unavailable"; shares remains the real public share counter.
{
  "type": "profile",
  "platform": "tiktok",
  "username": "nba",
  "includeRecentPosts": true,
  "pages": 2
}
{
  "url": "https://www.tiktok.com/@nba",
  "platform": "tiktok",
  "type": "profile",
  "success": true,
  "profile": {
    "id": "6749213842887734277",
    "handle": "nba",
    "name": "NBA",
    "biography": "The official NBA account.",
    "followers": 26800000,
    "following": 266,
    "totalPosts": null,
    "totalVideos": 12,
    "totalLikes": 1100000000,
    "highlightReelCount": null,
    "isPrivate": false,
    "isVerified": true,
    "isBusinessAccount": false,
    "isProfessionalAccount": false,
    "categoryName": null,
    "externalUrl": null,
    "profilePicUrl": "https://...",
    "profilePicUrlHd": null
  },
  "recentPosts": [
    {
      "id": "7648122936318020894",
      "url": "https://www.tiktok.com/@nba/video/7648122936318020894",
      "type": "video",
      "isVideo": true,
      "views": 2400000,
      "likes": 98400,
      "comments": 3210,
      "shares": 12200,
      "saves": 18400,
      "reposts": null,
      "metricAvailability": {
        "views": "available",
        "likes": "available",
        "comments": "available",
        "shares": "available",
        "saves": "available",
        "reposts": "unavailable"
      },
      "createTime": 1780717386,
      "publishedAt": "2026-06-06T03:43:06.000Z",
      "caption": "Game 7 highlights #nba",
      "description": "Game 7 highlights #nba",
      "hashtags": ["nba"],
      "isAd": false,
      "isPinned": true,
      "slideshow": { "isImagePost": false, "slideCount": 0 },
      "durationSeconds": 18,
      "aspectRatio": "9:16",
      "dimensions": { "width": 1080, "height": 1920 },
      "author": {
        "id": "6749213842887734277",
        "handle": "nba",
        "name": "NBA",
        "followers": 26800000,
        "following": 266,
        "totalLikes": 1100000000,
        "videoCount": 23500,
        "bio": "The official NBA account.",
        "isVerified": true,
        "profilePicUrl": "https://..."
      },
      "media": {
        "type": "video",
        "thumbnailUrl": "https://...",
        "videoUrl": "https://...",
        "durationSeconds": 18,
        "width": 1080,
        "height": 1920,
        "aspectRatio": "9:16",
        "images": []
      },
      "music": {
        "id": "music-id",
        "title": "Original sound",
        "authorName": "NBA",
        "durationSeconds": 18,
        "original": true,
        "isCopyrighted": false,
        "isCommerce": false,
        "playUrl": "https://...",
        "coverUrl": "https://..."
      }
    }
  ],
  "pageInfo": {
    "recentPosts": {
      "hasNextPage": true,
      "endCursor": null,
      "requestedLimit": 24,
      "returnedCount": 24,
      "pagesRequested": 2,
      "pagesFetched": 2,
      "incomplete": false
    }
  }
}

Field reference

Successful responses can include these normalized fields when TikTok exposes them. Unavailable fields return null or are omitted when empty.

ObjectFields
mediatypethumbnailUrlvideoUrldurationSecondswidthheightratioaspectRatioformatbitrateimages
profileShared profile schema plus talkingAbout and wereHere when present. A top-level scrapedAt is returned on the profile result.
recentPosts[]Profile-feed posts expose engagement (views, likes, comments, shares, saves), Unix and ISO publish time, caption/description, hashtags, ad and pinned flags, slideshow count, duration, dimensions, reduced aspect ratio, repeated author details, media, and music. Actual repost count is unavailable and returned as null.
recentPosts[].musicidtitleauthorNamedurationSecondsoriginalisCopyrightedisCommerceplayUrlcoverUrl
recentPosts[].authoridhandlenamefollowersfollowingtotalLikesvideoCountbioisVerifiedprofilePicUrl

Facebook

Post / Reel Profile POSTapi.refetcher.com/

Scrape public Facebook Reels, videos, posts, photos, and carousels, plus public profile metadata. Reels can return separate exact views and plays, Like-only and total reactions, reaction breakdowns, total and top-level comments, and temporary HD/SD media links. Image, photo, carousel, and text posts return views: null and plays: null with both availability states set to "not_applicable".

Post & Reel

Send the canonical Facebook URL in the body. Carousel and photo items are normalized under media.children. Facebook saves are not publicly exposed and return null. Facebook may resolve share, video, and Reel URLs to the canonical owner URL in post.normalizedUrl. Facebook has no Instagram-style shortcode; use post.identifiers for the content, story, video, feedback, and input pfbid identifiers.

Format notes: Prefer the parent /posts/... URL for photos and carousels. Standalone photo.php?fbid=... pages can return no public payload. Some /videos/... links now resolve to Reels; older /watch/?v=... videos can expose only a subset of metrics and media.
{
  "url": "https://www.facebook.com/reel/1711573346749065/"
}
{
  "url": "https://www.facebook.com/reel/1711573346749065/",
  "platform": "facebook",
  "success": true,
  "metrics": {
    "views": 3407257,
    "plays": 6310936,
    "likes": 166578,
    "reactions": 182332,
    "comments": 569,
    "topLevelComments": 477,
    "shares": 12000,
    "saves": null
  },
  "metricAvailability": {
    "views": "available",
    "plays": "available",
    "likes": "available",
    "reactions": "available",
    "comments": "available",
    "topLevelComments": "available",
    "shares": "available",
    "saves": "unavailable"
  },
  "metricPrecision": {
    "views": "exact",
    "plays": "exact",
    "likes": "exact",
    "reactions": "exact",
    "comments": "exact",
    "topLevelComments": "exact",
    "shares": "rounded",
    "saves": null
  },
  "displayMetrics": {
    "shares": "12K"
  },
  "reactionBreakdown": {
    "like": 166578,
    "love": 13133,
    "care": 1872,
    "haha": 445,
    "wow": 112,
    "sad": 179,
    "angry": 13
  },
  "post": {
    "id": "1711573346749065",
    "shortcode": null,
    "normalizedUrl": "https://www.facebook.com/100053663644278/videos/1711573346749065/",
    "publishedAt": "2026-07-24T19:02:26.000Z",
    "caption": "please stop callin",
    "type": "reel",
    "productType": "reel",
    "hashtags": [],
    "mentions": [],
    "location": null,
    "commentsDisabled": null,
    "isPinned": null,
    "isSponsored": null,
    "identifiers": {
      "contentId": "1711573346749065",
      "storyId": "1562911328840974",
      "videoId": "1711573346749065",
      "feedbackId": "ZmVlZGJhY2s6MTU2MjkxMTMyODg0MDk3NA==",
      "inputToken": null
    }
  },
  "author": {
    "id": null,
    "handle": "Meta",
    "name": "Meta",
    "followers": null,
    "isVerified": null,
    "profilePicUrl": null
  },
  "media": {
    "type": "video",
    "thumbnailUrl": "https://...",
    "videoUrl": "https://...",
    "hdVideoUrl": "https://...",
    "sdVideoUrl": "https://...",
    "captionsUrl": null,
    "durationSeconds": 16,
    "width": 1080,
    "height": 1920,
    "altText": null,
    "audioAvailability": "available",
    "isLooping": true,
    "urlsExpire": true,
    "variants": [
      {
        "quality": "hd",
        "contentType": "video/mp4",
        "url": "https://...",
        "expiresAt": "2026-08-03T20:53:52.000Z"
      },
      {
        "quality": "sd",
        "contentType": "video/mp4",
        "url": "https://...",
        "expiresAt": "2026-08-03T19:54:40.000Z"
      }
    ],
    "children": []
  },
  "scrapedAt": "2026-07-30T12:00:00.000Z"
}

Supported URL shapes

/reel//videos//watch/?v=/posts//share/p/fb.watch

Profile

Send a Facebook username or profile URL. Facebook profile requests return three post links by default. Set recentPostsLimit to request up to 25 links and use pages to bound the read to 0–10 cursor pages. Check pageInfo.recentPosts.incomplete before treating the returned window as complete.

Pagination behavior: Facebook can throttle a public timeline independently of the profile page. The API retries a failed page once, returns links already collected, and marks pageInfo.recentPosts.incomplete when appropriate. When an incomplete result still includes endCursor, resend it as after after a short backoff to resume from the failed page.
{
  "type": "profile",
  "platform": "facebook",
  "username": "Meta",
  "recentPostsLimit": 10,
  "pages": 2
}
{
  "url": "https://www.facebook.com/Meta/",
  "platform": "facebook",
  "type": "profile",
  "success": true,
  "source": "facebook-profile-links",
  "profile": {
    "id": "100080376596424",
    "handle": "Meta",
    "name": "Meta",
    "biography": null,
    "followers": null,
    "following": null,
    "totalPosts": null,
    "totalVideos": null,
    "totalLikes": null,
    "highlightReelCount": null,
    "isPrivate": false,
    "isVerified": true,
    "isBusinessAccount": false,
    "isProfessionalAccount": false,
    "categoryName": null,
    "externalUrl": null,
    "profilePicUrl": "https://...",
    "profilePicUrlHd": "https://..."
  },
  "recentPosts": [
    {
      "id": "1032807172741826",
      "shortcode": "1032807172741826",
      "url": "https://www.facebook.com/Meta/posts/1032807172741826/",
      "type": "carousel",
      "isVideo": false,
      "publishedAt": null,
      "caption": null,
      "displayUrl": null,
      "dimensions": null
    }
  ],
  "recentVideos": [
    {
      "id": "1358040539510776",
      "url": "https://www.facebook.com/reel/1358040539510776/",
      "type": "video",
      "isVideo": true,
      "publishedAt": null
    }
  ],
  "postLinks": [
    "https://www.facebook.com/reel/1358040539510776/"
  ],
  "pageInfo": {
    "recentPosts": {
      "hasNextPage": true,
      "endCursor": "...",
      "requestedLimit": 10,
      "returnedCount": 4,
      "pagesRequested": 2,
      "pagesFetched": 1,
      "incomplete": true
    },
    "recentVideos": null
  },
  "scrapedAt": "2026-06-10T10:15:30.000Z",
  "source": "facebook-profile-links"
}

This route is optimized for post-link discovery. Recent posts are returned as link-only references without per-post engagement (views, likes, comments, shares, saves), and Facebook often does not expose an exact profile.followers count here either. Fetch an individual returned post link with the Facebook Post scraper when metrics are required. Facebook can throttle timeline pagination independently of profile metadata, so a profile result can still be successful while pageInfo.recentPosts.incomplete is true. To continue after a successful response, send its pageInfo.recentPosts.endCursor as after; the continuation returns the next post-link slice rather than the initial links. No Facebook account login, cookie, or customer proxy setup is required.

Field reference

Successful responses can include these normalized fields when Facebook exposes them. Unavailable fields return null or are omitted when empty.

ObjectFields
metricsviewsplayslikesreactionscommentstopLevelCommentssharessaves
metricPrecisionPer-field exact, rounded, or null. When precision is rounded, displayMetrics carries the compact public representation.
reactionBreakdownlikelovecarehahawowsadangry
postidshortcodeidentifiersnormalizedUrlpublishedAtcaptiontypeproductTypehashtagsmentionsregionlanguagelocationcommentsDisabledisPinnedisSponsored
mediatypethumbnailUrlvideoUrlhdVideoUrlsdVideoUrlcaptionsUrldurationSecondswidthheightaudioAvailabilityisLoopingurlsExpirevariantschildren
authoridhandlenamefollowersfollowingtotalLikesvideoCountbioisVerifiedprofilePicUrl
profileShared profile schema plus talkingAbout, wereHere, isBusinessAccount, isProfessionalAccount, and profilePicUrlHd when Facebook exposes them.

X

Post Profile POSTapi.refetcher.com/

Scrape public X posts (tweets) and profiles. All five core metrics are available for X posts: views, likes, comments (replies), shares (retweets), and saves (bookmarks).

Post

Send the post URL in the body. X post scraping returns views, likes, replies, retweets, and any attached media. In the returned metrics, replies map to comments, retweets to shares, and bookmarks to saves.

Supported URL shapes

x.com/SpaceX/status/2064099405758906727twitter.com/SpaceX/status/2064099405758906727

Metric aliasing

  • repliescomments
  • retweetsshares
  • bookmarkssaves
{
  "url": "https://x.com/SpaceX/status/2064099405758906727"
}
{
  "url": "https://x.com/SpaceX/status/2064099405758906727",
  "platform": "x",
  "success": true,
  "metrics": {
    "views": 5350265,
    "likes": 148761,
    "comments": 3441,
    "shares": 21255,
    "saves": 3469
  },
  "metricAvailability": {
    "views": "available",
    "likes": "available",
    "comments": "available",
    "shares": "available",
    "saves": "available"
  },
  "post": {
    "id": "2064099405758906727",
    "shortcode": "2064099405758906727",
    "normalizedUrl": "https://x.com/SpaceX/status/2064099405758906727",
    "publishedAt": "2026-06-10T19:28:28.000Z",
    "caption": "Launch update from the pad",
    "type": "text",
    "productType": "tweet",
    "hashtags": [],
    "mentions": []
  },
  "author": {
    "id": "34713599",
    "handle": "SpaceX",
    "name": null,
    "followers": 41700000,
    "isVerified": true,
    "profilePicUrl": null
  },
  "media": {
    "thumbnailUrl": null,
    "videoUrl": null,
    "durationSeconds": null,
    "width": null,
    "height": null,
    "altText": null,
    "children": []
  },
  "scrapedAt": "2026-06-10T10:15:30.000Z"
}
Quote tweets are returned separately in the raw response but are not included in the normalized metrics object.

Profile

Send an X username or profile URL. With includeRecentPosts: true, the profile endpoint always returns posts and excludes authored replies. The default sort: "latest" starts with X's logged-out public profile, follows its anonymous bottom cursor for additional requested pages when available, deduplicates the merged posts, and sorts them newest-first. Set sort: "popular" only when you want X's lifetime-popularity-ranked public selection.

Standard pages: each requested X customer page contains up to 5 posts for both latest and popular. Many profiles expose a real anonymous bottom cursor, which Refetcher follows for multiple latest pages. Some profiles are placed in X's curated/highlights mode and expose no cursor; those requests return only the real initial window and mark incomplete: true. The API never fabricates later pages or substitutes old popular posts. Each returned item has isPinned, and a pinned item is sorted by its real publish time.
{
  "type": "profile",
  "platform": "x",
  "username": "SpaceX",
  "includeRecentPosts": true,
  "pages": 1,
  "sort": "latest"
}
{
  "url": "https://x.com/SpaceX",
  "platform": "x",
  "type": "profile",
  "success": true,
  "profile": {
    "id": "34713599",
    "handle": "SpaceX",
    "name": "SpaceX",
    "biography": "SpaceX designs, manufactures and launches advanced rockets and spacecraft.",
    "followers": 41700000,
    "following": 123,
    "totalPosts": 11400,
    "pinnedPostId": "2064099405758906727",
    "totalVideos": null,
    "totalLikes": null,
    "talkingAbout": null,
    "wereHere": null,
    "highlightReelCount": null,
    "isPrivate": false,
    "isVerified": true,
    "isBusinessAccount": false,
    "isProfessionalAccount": false,
    "categoryName": null,
    "externalUrl": "https://www.spacex.com/",
    "profilePicUrl": "https://...",
    "profilePicUrlHd": null
  },
  "feed": {
    "sort": "latest",
    "chronological": true,
    "postsPerPage": 5,
    "complete": false
  },
  "recentPosts": [
    {
      "id": "2064099405758906727",
      "url": "https://x.com/SpaceX/status/2064099405758906727",
      "type": "video",
      "isVideo": true,
      "publishedAt": "2026-06-01T00:00:00.000Z",
      "caption": "Starship flight test",
      "isPinned": true,
      "isReply": false,
      "isQuote": false,
      "replyTo": null,
      "conversationId": "2064099405758906727"
    }
  ],
  "recentVideos": [
    {
      "id": "2064099405758906727",
      "url": "https://x.com/SpaceX/status/2064099405758906727",
      "type": "video",
      "isVideo": true,
      "publishedAt": "2026-06-01T00:00:00.000Z"
    }
  ],
  "pageInfo": {
    "recentPosts": {
      "hasNextPage": false,
      "endCursor": null,
      "requestedLimit": 12,
      "returnedCount": 5,
      "pagesRequested": 1,
      "pagesFetched": 1,
      "incomplete": true
    },
    "recentVideos": {
      "hasNextPage": false,
      "endCursor": null,
      "requestedLimit": 12,
      "returnedCount": 3,
      "pagesRequested": 1,
      "pagesFetched": 1,
      "incomplete": true
    }
  },
  "scrapedAt": "2026-06-10T10:15:30.000Z"
}

Field reference

Successful responses can include these normalized fields when X exposes them. Unavailable fields return null or are omitted when empty.

ObjectFields
postidshortcodenormalizedUrlpublishedAtcaptiontypeproductTypehashtagsmentionsregionlanguagelocationcommentsDisabledisPinnedisSponsored
authoridhandlenamefollowersfollowingtotalLikesvideoCountbioisVerifiedprofilePicUrl
profileShared profile schema including totalVideos, totalLikes, talkingAbout, wereHere, highlightReelCount, isBusinessAccount, isProfessionalAccount, categoryName, externalUrl, and profilePicUrlHd.
feed, recentPostsfeed reports the effective sort, 5-post page size, chronological state, and completeness. X feed items include isPinned, isReply, isQuote, conversationId, and the applicable replyTo or quoteOf relationship.
recentVideos, pageInforecentVideos can contain recent video posts. pageInfo.recentPosts and pageInfo.recentVideos use the cursor fields hasNextPage, endCursor, requestedLimit, returnedCount, pagesRequested, pagesFetched, incomplete.
limitationsNot returned for normal X post responses. Optional fields such as limitations are omitted when empty.

YouTube

Video Channel POSTapi.refetcher.com/

Scrape public YouTube videos, Shorts, and channels. YouTube does not expose shares or saves through this API, so those metrics return null.

Video

Send a YouTube URL in the body. Enable includeRecentComments to also return the newest public top-level comments. Supported formats include standard watch URLs, Shorts URLs, embeds, live URLs, and youtu.be links.

{
  "url": "https://www.youtube.com/watch?v=8jPQjjsBbIc",
  "includeRecentComments": true,
  "recentCommentsLimit": 20
}
{
  "url": "https://www.youtube.com/watch?v=8jPQjjsBbIc",
  "platform": "youtube",
  "success": true,
  "metrics": {
    "views": 1650000,
    "likes": 42000,
    "comments": 1800,
    "shares": null,
    "saves": null
  },
  "post": {
    "id": "8jPQjjsBbIc",
    "normalizedUrl": "https://www.youtube.com/watch?v=8jPQjjsBbIc",
    "publishedAt": "2026-06-01T08:30:00.000Z",
    "caption": "Example video title",
    "description": "Example video description"
  },
  "author": {
    "handle": "UCAuUUnT6oDeKwE6v1NGQxug",
    "name": "TED",
    "followers": null
  },
  "media": {
    "thumbnailUrl": "https://i.ytimg.com/vi/8jPQjjsBbIc/hqdefault.jpg",
    "embedUrl": "https://www.youtube.com/embed/8jPQjjsBbIc"
  },
  "recentComments": [
    {
      "id": "comment-id",
      "authorName": "Viewer",
      "authorChannelId": "UC...",
      "authorChannelUrl": "https://www.youtube.com/channel/UC...",
      "text": "Example comment",
      "likes": 12,
      "publishedAt": "2026-06-09T09:00:00.000Z",
      "updatedAt": "2026-06-09T09:00:00.000Z",
      "replyCount": 1
    }
  ],
  "scrapedAt": "2026-06-09T10:15:30.000Z"
}
YouTube video results use a smaller platform-specific post/author schema and currently do not include metricAvailability. The media object provides a stable thumbnail CDN URL and permanent embed URL; direct signed media-download URLs are intentionally not returned because they expire and are not reliable across AWS regions. recentComments is present only when requested; if comment retrieval fails, the response includes an empty array and recentCommentsError.

Channel

Set type to "channel" for channel profile data or "channelVideos" for latest uploads. You can pass a channel URL, raw channel ID, or @handle. Channel profile responses return type: "channel" and a channel object; their bundled recentVideos are links-only references, matching every other profile scraper. Channel-video responses return type: "channelVideos", a lightweight channel object, and results/videos arrays — this is the one resource that includes per-video views, likes, and comments.

{
  "type": "channel",
  "platform": "youtube",
  "channelUrl": "https://www.youtube.com/@TED",
  "includeRecentVideos": true,
  "recentVideosLimit": 12
}
{
  "type": "channelVideos",
  "platform": "youtube",
  "handle": "@TED",
  "recentVideosLimit": 12
}

Field reference

YouTube uses a platform-specific schema. Successful responses can include these fields when YouTube exposes them.

ResourceObjectFields
Video / ShortmediathumbnailUrlembedUrl
ChannelchannelidhandlenamedescriptioncountrypublishedAtsubscribershiddenSubscriberCounttotalViewstotalVideosuploadsPlaylistIdthumbnailUrlurl
Channel videoschannelidhandlenamesubscribershiddenSubscriberCounttotalViewstotalVideos

True People Search

People search US POSTapi.refetcher.com/people-search POSTapi.refetcher.com/people-detail

Resolve a name, phone number, or address into a structured US contact record — current and prior addresses, phone numbers, emails, and known relatives — returned as normalized JSON. There are two endpoints: /people-search finds matching records, and /people-detail returns the full contact record for a match. Each request batches up to 30 independent person queries. Need access? Contact sales.

Search endpoint

POST a queries array (1–30 items) to /people-search to find matching records. Each query searches by name, phone, or address — provide at least one. Add city, state, postalCode, and age to disambiguate common names. A bare name string ("queries": ["Jordan Avery"]) is also accepted. Use depth: "contact" for full contact data, matchMode: "best" for the first provider-ranked match, and fields/filters to return only useful records and fields.

curl -X POST https://api.refetcher.com/people-search \
  -H "X-API-Key: ps_live_••••" \
  -H "Content-Type: application/json" \
  -d '{
    "queries": [
      { "id": "lead-91", "name": "Jordan Avery", "city": "Plano", "state": "TX" },
      { "phone": "(972) 555-0148" }
    ]
  }'
{
  "success": true,
  "requestId": "a1b2c3d4",
  "summary": { "total": 2, "succeeded": 2, "failed": 0 },
  "results": [
    {
      "success": true,
      "platform": "people_search",
      "type": "person_search",
      "provider": "truepeoplesearch",
      "query": { "id": "lead-91", "name": "Jordan Avery", "city": "Plano", "state": "TX" },
      "totalMatches": 1,
      "matchCount": 1,
      "matches": [
        {
          "name": "Jordan M Avery",
          "age": 38,
          "currentCity": "Plano",
          "currentState": "TX",
          "summary": "Jordan M Avery is 38 and lives in Plano, TX. Previously in Frisco, TX.",
          "detailUrl": "https://www.truepeoplesearch.com/find/person/…"
        }
      ],
      "searchedAt": "2026-06-25T17:42:08.110Z",
      "workerMs": 4180
    },
    {
      "success": true,
      "platform": "people_search",
      "type": "person_search",
      "provider": "truepeoplesearch",
      "query": { "id": "q_2", "phone": "9725550148" },
      "totalMatches": 1,
      "matchCount": 1,
      "matches": [
        {
          "name": "Jordan M Avery",
          "age": 38,
          "currentCity": "Plano",
          "currentState": "TX",
          "summary": "Reverse-phone match for (972) 555-0148.",
          "detailUrl": "https://www.truepeoplesearch.com/find/person/…"
        }
      ],
      "searchedAt": "2026-06-25T17:42:08.420Z",
      "workerMs": 3920
    }
  ],
  "totalMs": 4620
}

Request parameters

ParameterTypeDescription
queries (required)object[] · string[]1–30 person queries. Each item is a query object (below) or a plain name string.
maxResultsPerQuerynumberMaximum matches returned per query. Default and maximum 10.
depthstringbasic (default) returns search cards; contact visits detail pages for phones, emails, addresses, and relatives.
matchModestringall (default) or best to keep only the first provider-ranked match.
fieldsstring[]Optional response projection: name, age, currentCity, currentState, locations, phoneNumbers, emails, relatives, detailUrl, and summary.
filtersobjectFilter matches by age, city/state/ZIP, or the presence of phones, emails, addresses, and relatives (below).
maxDetailPagesPerQuerynumberCaps detail-page visits when contact depth is active. Maximum 10.
timeoutMsnumberPer-request worker timeout. Default and maximum 150000.

Search query — provide at least one of name, phone, or address

FieldTypeDescription
namestringFull name to search. Accepts fullName as an alias.
firstName / lastNamestringUsed to build the search name when name is not supplied.
phonestringReverse-phone lookup. Any format; normalized to a 10-digit US number (a leading 1 is stripped).
addressstring · objectReverse-address lookup. Accepts a free-form street address or an object with street, city, state, and postalCode.
citystringNarrows a name search to a city.
statestringTwo-letter US state code, e.g. TX. Case-insensitive on input.
postalCodestringFive-digit ZIP or ZIP+4. zip is accepted as an alias.
agenumberApproximate age (1–124) to disambiguate common names.
idstringYour own correlation id. Echoed back on query.id; defaults to q_1, q_2, … when omitted.

Match filters

FilterTypeDescription
age.min / age.maxnumberInclusive age range. Flat minAge/maxAge aliases are accepted.
states / citiesstring[]Allowed states and cities. Singular state/city aliases accept one value.
postalCodesstring[]Keep matches with an address containing one of these ZIP codes.
hasPhonebooleanRequire or exclude matches with phone numbers.
hasEmailbooleanRequire or exclude matches with email addresses.
hasAddressbooleanRequire or exclude matches with addresses.
hasRelativesbooleanRequire or exclude matches with relatives or associates.

Search response

The top-level success is true only when every query in the batch succeeded — always check each result's own success flag for partial batches. The envelope carries requestId, a summary (total, succeeded, failed), the results array (one entry per query, in request order), and totalMs. The detail endpoint returns this same envelope.

results[] — per query

FieldTypeDescription
successbooleanWhether this individual query resolved.
platformstringAlways people_search.
typestringAlways person_search.
providerstringSource of the record, e.g. truepeoplesearch.
queryobjectThe normalized query that was executed, including your id.
totalMatchesnumberNumber of provider matches before response filters and matchMode.
matchCountnumberNumber of matches returned after filters and matchMode.
matchesobject[]The matched person records (fields below).
searchedAtISO 8601When the lookup ran.
workerMsnumber · nullWorker processing time for this query.
errorobjectPresent on failure, with category and message (see Errors).

matches[] — search fields

FieldTypeDescription
namestringFull name on the record.
agenumber · nullApproximate age when available.
currentCitystringMost recent known city.
currentStatestringMost recent known state.
summarystringShort text summary of the match.
detailUrlstringPass this URL to the /people-detail endpoint for the full record.

Detail endpoint

POST a detailUrl — taken from any /people-search match — to /people-detail to pull the full contact record: every known address, phone number, email, and relative. It takes the same queries array (1–30 items), where each query carries a detailUrl instead of search terms. The response envelope is identical to /people-search; only the matches[] fields are richer.

curl -X POST https://api.refetcher.com/people-detail \
  -H "X-API-Key: ps_live_••••" \
  -H "Content-Type: application/json" \
  -d '{
    "queries": [
      { "detailUrl": "https://www.truepeoplesearch.com/find/person/…" }
    ]
  }'
{
  "success": true,
  "requestId": "e5f6g7h8",
  "summary": { "total": 1, "succeeded": 1, "failed": 0 },
  "results": [
    {
      "success": true,
      "platform": "people_search",
      "type": "person_search",
      "provider": "truepeoplesearch",
      "query": { "id": "q_1", "detailUrl": "https://www.truepeoplesearch.com/find/person/…" },
      "totalMatches": 1,
      "matchCount": 1,
      "matches": [
        {
          "name": "Jordan M Avery",
          "age": 38,
          "currentCity": "Plano",
          "currentState": "TX",
          "locations": [
            "4120 Maple Ave, Plano, TX 75074",
            "88 Birch Ln, Frisco, TX 75035"
          ],
          "phoneNumbers": ["(972) 555-0148", "(214) 555-0102"],
          "emails": ["j.avery@example.com"],
          "relatives": ["Morgan Avery", "Taylor Avery"],
          "detailUrl": "https://www.truepeoplesearch.com/find/person/…"
        }
      ],
      "searchedAt": "2026-06-25T17:42:10.300Z",
      "workerMs": 5210
    }
  ],
  "totalMs": 5320
}

Detail query

FieldTypeDescription
detailUrl (required)stringThe provider URL returned on a /people-search match. Pass one per query to /people-detail.
idstringYour own correlation id, echoed back on query.id. Defaults to q_1, q_2, … when omitted.

Detail response

The envelope and results[] fields are identical to the search endpoint — only the matches[] records are richer. Empty fields are omitted rather than returned as empty strings or arrays, so check for presence before reading nested values.

matches[] — detail fields

FieldTypeDescription
namestringFull name on the record.
agenumber · nullApproximate age when available.
currentCitystringMost recent known city.
currentStatestringMost recent known state.
locationsstring[]Current and prior addresses (up to 8).
phoneNumbersstring[]Associated phone numbers (up to 8).
emailsstring[]Associated email addresses (up to 8).
relativesstring[]Known relatives and associates (up to 12).
detailUrlstringProvider URL for the full underlying record.

Errors & status

A failed query never breaks the batch — it returns with success: false and an error.category. Transient categories are retried internally against a backup region before being returned. The HTTP status is 200 when at least one query succeeds, and 502 only when every query in the batch fails.

Query error categories

CategoryDescription
bad_queryThe query was invalid or unsearchable (e.g. no name, phone, or address).
timeoutThe lookup exceeded the worker timeout.
rate_limitedThe upstream provider throttled the request.
blocked_or_challengeThe provider returned a challenge or CAPTCHA.
challenge_timeoutA provider challenge did not clear in time.
navigation_timeoutThe provider page did not start loading in time.
parse_errorThe provider returned an unreadable result page.
network_errorA transport error reaching the worker.
upstream_errorA temporary provider-side failure.
worker_errorThe lookup worker failed before returning a result.
unknown_errorThe lookup failed for an unclassified reason.

HTTP status codes

StatusMeaning
200At least one query in the batch succeeded. Check the top-level success flag and each result.
400bad_request — malformed body, no valid queries, or more than 30 queries.
401unauthorized — the API key is missing or invalid.
402insufficient_balance — the account cannot cover the requested lookups.
405method_not_allowed — use POST.
502Every query in the batch failed. Inspect each result's error category.
503Authentication or billing was temporarily unavailable.

Permissible use. Refetcher is not a consumer reporting agency and this data is not a consumer report. It may not be used for credit, employment, insurance, housing, tenant screening, or any other purpose regulated by the FCRA.

Reference

Responses & errors

How every response is wrapped, the HTTP statuses you'll see, and the stable error categories returned per target.

Response envelope

A successful request returns 200 OK with per-target records under the results array. Media targets return metrics, post, and author; Instagram, TikTok, Facebook, and X media targets also return media. Profile/channel targets return a type and profile/channel object.

{
  "success": true,
  "requestId": "aws-request-id-12345",
  "summary": {
    "total": 1,
    "succeeded": 1,
    "failed": 0,
    "errors": {}
  },
  "results": [
    {
      "url": "https://www.instagram.com/reel/C8xExampleAbc/",
      "platform": "instagram",
      "success": true,
      "metrics": {
        "views": 1284203,
        "likes": 48211,
        "comments": 1903,
        "shares": null,
        "saves": null
      },
      "metricAvailability": {
        "views": "available",
        "likes": "available",
        "comments": "available",
        "shares": "unavailable",
        "saves": "unavailable"
      },
      "post": { "id": "C8xExampleAbc", "type": "video", "caption": "Check out our new release!" },
      "author": { "handle": "creators_hub", "followers": 94200 },
      "media": { "playCount": 1284203, "durationSeconds": 21.4 },
      "scrapedAt": "2026-06-05T10:15:30.000Z"
    }
  ],
  "totalMs": 1150
}
{
  "success": true,
  "requestId": "aws-request-id-67890",
  "summary": {
    "total": 2,
    "succeeded": 1,
    "failed": 1,
    "errors": {
      "private_or_removed": 1
    }
  },
  "results": [
    {
      "url": "https://www.instagram.com/reel/VALID_URL/",
      "platform": "instagram",
      "success": true,
      "metrics": { "views": 4900, "likes": 210, "comments": 15, "shares": null, "saves": null },
      "post": { "id": "VALID_URL", "publishedAt": null, "caption": null },
      "author": { "handle": "creator_name", "name": null, "followers": null },
      "scrapedAt": "2026-06-05T10:16:00.000Z"
    },
    {
      "url": "https://www.instagram.com/reel/PRIVATE_URL/",
      "platform": "instagram",
      "success": false,
      "error": {
        "category": "private_or_removed",
        "message": "The post could not be accessed. It may be private, removed, or unavailable."
      },
      "scrapedAt": "2026-06-05T10:16:01.000Z"
    }
  ],
  "totalMs": 1420
}
{
  "success": false,
  "requestId": "aws-request-id-99999",
  "summary": {
    "total": 1,
    "succeeded": 0,
    "failed": 1,
    "errors": {
      "missing_metrics": 1
    }
  },
  "results": [
    {
      "url": "https://www.instagram.com/reel/SHORTCODE/",
      "platform": "instagram",
      "success": false,
      "error": {
        "category": "missing_metrics",
        "message": "The scraper could not read the required public metrics for this post."
      },
      "scrapedAt": "2026-06-05T10:17:00.000Z"
    }
  ],
  "totalMs": 1380
}

Batch & billing: the HTTP status is still 200 OK if at least one target succeeds; the top-level success flag is also true for a partial batch, while failed targets are marked inside results[]. Billing is per successful target, or per successful returned page for profile/channel pagination. A request can reserve at most 50 billable units total. If every target is still private, deleted, or unavailable after retries, the API returns 404 Not Found with private_or_removed per-target errors. Other every-target scrape failures return 502 Bad Gateway; unexpected gateway exceptions return 500 with a top-level error object.

Metric availability: Instagram, TikTok, Facebook, and X post results include metricAvailability; each value is "available", "unavailable", or "not_applicable". Facebook adds plays, reactions, and topLevelComments to the five common metric keys. Unavailable metrics return null in metrics; YouTube video results currently omit the availability object.

HTTP status codes

Request-level failures use a top-level error object. Scrape-level failures appear inside results.

StatusCategoryMeaning
200Success / partialAt least one target succeeded. Check summary.failed and each item in results for partial failures.
400bad_requestMalformed JSON, no target, too many targets, or an unsupported target format.
401unauthorizedThe API key is missing or invalid.
402insufficient_balanceThe account cannot reserve enough balance for every target in the request.
404private_or_removedEvery requested target is private, deleted, or otherwise unavailable publicly.
405method_not_allowedThe scrape endpoint was called with a method other than POST.
429rate_limitedA request-specific quota was exceeded. Follow Retry-After when present.
500Gateway errorAn unexpected dispatcher exception prevented a normal per-target response.
502Full failureEvery target failed. Inspect each result's error category.
503billing_unavailableThe service could not reserve account balance before scraping.

Error categories

Per-target scraper failures are normalized into stable category keys:

CategoryDescription
bad_urlThe provided URL format is invalid or cannot be parsed.
unsupported_platformThe target platform is not supported by Refetch(er).
private_or_removedThe target is private, was deleted, or restricted public visibility.
minimum_age_requiredInstagram returned its exact account-level minimum-age restriction or its exact unappealable restricted-audience gate without a more specific reason. This terminal result is not retried through a paid recovery provider and is not billed.
missing_metricsThe scraper accessed the target but could not extract the required public metrics.
timeoutThe worker exceeded its maximum execution time.
rate_limitedThe platform rate limited the request. When failover is available, the dispatcher retries during the same API request.
blocked_or_challengeThe scraper encountered an upstream access challenge or block.
upstream_errorA scraper worker or social platform returned an unusable server response.
configuration_errorA system configuration issue prevented the scrape.
unknown_errorAn unclassified system exception occurred.

Retry & failover

Refetch(er) is built to maximize scrape consistency. When a request arrives, the dispatcher orchestrates multi-region failover behind the scenes:

  1. The dispatcher forwards your query to the primary scraper worker.
  2. If the primary worker returns a retryable failure, the dispatcher can retry only the failed targets on a backup worker during the same request.
  3. If every route fails for a target, the API returns the final normalized error payload for that target.

This entire retry lifecycle is transparent to your client. You make a single request to api.refetcher.com, and we handle the network recovery logic, returning the data inside our standard response shape.