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 a single unified scrape entry point for Instagram, TikTok, Facebook, and X posts and profiles, YouTube video metrics, recent YouTube comments, and YouTube channel data. Your request body tells the API what resource you want, and the gateway routes it to the correct scraper internally.

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 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/

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.

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 and links-only recent videos, with multi-page profile pagination for deeper post discovery.

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: Profile and channel responses return account metadata plus links-only recent media references when requested. Per-post engagement belongs to post/video endpoints; YouTube's channelVideos resource is the upload-list exception that includes per-video 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 lightweight recent public media references. Per-post engagement is omitted; fetch the returned post URL for metrics.
recentPostsLimitoptinteger12 / 3 for FacebookCompatibility alias for profile pagination. It maps to the platform page size: ceil(limit / 12) for Instagram, TikTok, and 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, TikTok, and X return up to 12 references per page; 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. Instagram image/carousel views are automatically treated as not applicable. Accepted: views, likes, comments, shares, saves.

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 — they still succeed with views: null and metricAvailability.views: "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 requests return public creator metadata and links-only recent post references with multi-page pagination.

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. Enable recent posts to receive the public videos TikTok exposes without login. By default a request returns the first page (up to ~12 recent videos). To scrape more, set pages to the number of pages you want — each page returns up to 12 posts and counts as one successful scrape (so pages: 3 is billed as 3 scrapes at $0.90 per 1,000; a page that returns nothing is free). Recent posts are returned as lightweight references (link, publish time, caption, thumbnail) without per-post engagement; for views, likes, comments, shares, and saves on a specific video, use the Video scraper. For compatibility, the same public video selection can appear under both recentPosts and recentVideos.

{
  "type": "profile",
  "platform": "tiktok",
  "username": "nba",
  "includeRecentPosts": true,
  "pages": 3
}
{
  "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,
      "publishedAt": "2026-06-06T03:43:06.000Z",
      "caption": "Game 7 highlights"
    }
  ],
  "recentVideos": [
    {
      "id": "7648122936318020894",
      "url": "https://www.tiktok.com/@nba/video/7648122936318020894",
      "type": "video",
      "isVideo": true,
      "publishedAt": "2026-06-06T03:43:06.000Z",
      "caption": "Game 7 highlights"
    }
  ]
}

Field reference

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

ObjectFields
mediatypethumbnailUrlvideoUrldurationSecondswidthheightratioformatbitrateimages
profileShared profile schema plus talkingAbout and wereHere when present. A top-level scrapedAt is returned on the profile result.

Facebook

Post / Reel Profile POSTapi.refetcher.com/

Scrape public Facebook Reels, videos, posts, photos, and carousels, plus public profile metadata. Video/Reel results include public view counts when available; image, photo, carousel, and text posts return views: null with metricAvailability.views: "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/Reel URLs to the canonical owner URL in post.normalizedUrl.

{
  "url": "https://www.facebook.com/reel/2781078362247521/"
}
{
  "url": "https://www.facebook.com/reel/2781078362247521/",
  "platform": "facebook",
  "success": true,
  "metrics": {
    "views": 3400,
    "likes": 31,
    "comments": 1,
    "shares": 28,
    "saves": null
  },
  "metricAvailability": {
    "views": "available",
    "likes": "available",
    "comments": "available",
    "shares": "available",
    "saves": "unavailable"
  },
  "post": {
    "id": "2781078362247521",
    "shortcode": null,
    "normalizedUrl": "https://www.facebook.com/100086691939822/videos/2781078362247521/",
    "publishedAt": null,
    "caption": "Public caption",
    "type": "video",
    "productType": "video",
    "hashtags": [],
    "mentions": [],
    "location": null,
    "commentsDisabled": null,
    "isPinned": null,
    "isSponsored": null
  },
  "author": {
    "id": null,
    "handle": "Meta",
    "name": "Meta",
    "followers": null,
    "isVerified": null,
    "profilePicUrl": null
  },
  "media": {
    "thumbnailUrl": "https://...",
    "videoUrl": "https://...",
    "durationSeconds": 30,
    "width": null,
    "height": null,
    "altText": null,
    "children": []
  },
  "scrapedAt": "2026-06-10T10:15:30.000Z"
}

Supported URL shapes

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

Profile

Send a Facebook username or profile URL. Use pages to request 1–25 pages of recent public post links, up to 3 post links per page, and 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",
  "pages": 2
}
{
  "url": "https://www.facebook.com/Meta/",
  "platform": "facebook",
  "type": "profile",
  "success": true,
  "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"
}

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
postidshortcodenormalizedUrlpublishedAtcaptiontypeproductTypehashtagsmentionsregionlanguagelocationcommentsDisabledisPinnedisSponsored
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. Enable recent posts to return a list of recent public posts exposed by the profile timeline.

{
  "type": "profile",
  "platform": "x",
  "username": "SpaceX",
  "includeRecentPosts": true,
  "recentPostsLimit": 12
}
{
  "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,
    "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
  },
  "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"
    }
  ],
  "recentVideos": [
    {
      "id": "2064099405758906727",
      "url": "https://x.com/SpaceX/status/2064099405758906727",
      "type": "video",
      "isVideo": true,
      "publishedAt": "2026-06-01T00:00:00.000Z"
    }
  ],
  "pageInfo": {
    "recentPosts": {
      "hasNextPage": true,
      "endCursor": "...",
      "requestedLimit": 12,
      "returnedCount": 12,
      "pagesRequested": null,
      "pagesFetched": null,
      "incomplete": false
    },
    "recentVideos": {
      "hasNextPage": true,
      "endCursor": "...",
      "requestedLimit": 12,
      "returnedCount": 3,
      "pagesRequested": null,
      "pagesFetched": null,
      "incomplete": false
    }
  },
  "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.
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, and age to disambiguate common names. A bare name string ("queries": ["Jordan Avery"]) is also accepted. Every match includes a lightweight summary and a detailUrl you can hand to the detail endpoint for the full record.

curl -X POST https://api.refetcher.com/people-search \
  -H "X-API-Key: pc_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" },
      "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" },
      "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.
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).
addressstringReverse-address lookup. Free-form street address.
citystringNarrows a name search to a city.
statestringTwo-letter US state code, e.g. TX. Case-insensitive on input.
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.

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.
matchCountnumberNumber of matches returned for this query.
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: pc_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/…" },
      "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 with five keys — each value is "available", "unavailable", or "not_applicable". 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.
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. 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.