Changelog

New endpoints, platforms, integrations, and fixes — everything we ship, dated and documented.

Improved

Empty results now cost 0 credits on 36 more endpoints

A call that runs but finds nothing now costs 0 credits on the endpoints below. Before, they charged their normal price for an empty list: a search with no matches, a post with no comments or replies, a page past the last result, a private or empty profile tab. Google Maps business search used to bill an empty page on purpose; it is now free too. Responses are unchanged, and the X-Captapi-Credits header shows 0 on these calls. Calls that return data keep their price.

  • google/business-search: zero businesses 0 credits (was 2)
  • youtube/community-posts: communityStatus no_posts or disabled 0 credits (was 1)
  • youtube/playlist-videos, youtube/comment-replies, youtube/trending-shorts: empty page 0 credits (was 2)
  • youtube/playlist: no title and no video count 0 credits (was 1)
  • history: no stored points 0 credits (was 1)
  • reddit/subreddit-posts, reddit/post-comments, reddit/subreddit-search, reddit/search: empty page 0 credits (was 2)
  • truth-social/user-posts: no posts 0 credits (was 2)
  • pinterest/search: page past the last result 0 credits (was 1)
  • spotify/podcast-episodes, twitch/user-videos, rumble/comments: empty page 0 credits (was 2)
  • amazon-shop/page: empty products page 0 credits (was 1); limit=0 when the seller profile does not load 0 credits (was 1)
  • facebook/comments, facebook/comment-replies, facebook/profile-reels (noPublicReels), facebook/event-search, facebook/profile-events: empty result 0 credits (was 2)
  • facebook/marketplace-search with details=true: empty page 0 credits (was 2)
  • ad-library/facebook/search, ad-library/facebook/company-ads, ad-library/facebook/search-companies: empty result 0 credits (was 2)
  • instagram/highlights: private profile or no highlights 0 credits (was 1); instagram/tagged-posts: no posts 0 credits (was 1)
  • tiktok/comments, tiktok/comment-replies, tiktok/channel-posts, tiktok/music-posts, tiktok/search-suggestions: empty result 0 credits (was 2)
  • tiktok/audience-demographics: no audience locations or languages found 0 credits (was 3, 5 or 8)
  • tiktok-shop/shop-products: shop with an empty catalog 0 credits (was 2)
  • tiktok-shop/user-showcase: sellerStatus no_shop or shop_empty 0 credits (was 1)
Improved

LinkedIn: every endpoint reads only LinkedIn's logged-out public pages

Company, post details, post transcript, the LinkedIn Ad Library endpoints and LinkedIn links in /v1/analytics/post and /v1/analytics/compare now read only what a logged-out visitor sees on linkedin.com. The extended fallback is gone, so source is always native. When LinkedIn serves its sign-in page or a page can't be read, the call is 502 UPSTREAM_UNAVAILABLE (503 on the Ad Library), retryable, at 0 credits. A deleted post is 404. company.funding is null: the logged-out page shows no funding rounds.

  • linkedin/company, post-details, post-transcript: logged-out page only, source native
  • ad-library/linkedin/search-ads and ad-details: native only
  • sign-in page or unreadable page: 502 (Ad Library: 503), retryable, 0 credits
  • deleted post: 404
Improved

YouTube: empty search pages and videos with comments off cost 0 credits

A YouTube search page that finds nothing, and a comments call on a video whose comments are turned off (commentsDisabled: true), used to cost 2 credits. Both now cost 0, in line with the rule that an empty result is free unless the endpoint says otherwise. Responses are unchanged.

  • youtube/search: empty page 0 credits (was 2)
  • youtube/comments and youtube/shorts/comments: commentsDisabled 0 credits (was 2)
Improved

Google Maps business search accepts place names

google/business-search now takes location as a plain place name (Austin, TX; Istanbul, Turkey; Paris, France; Camden, London) and resolves it to a numeric place code before searching. The response echoes the matched place and its locationCode, so you can see exactly where the search ran. Calls that pass locationCode without location are unchanged.

  • location accepts City, Country or City, Region, Country; case, accents, US state codes and country aliases (USA, UK, Turkey) are handled
  • New response field locationCode, next to the matched location name
  • A city name shared by several places (Paris, London) returns 400 INVALID_ARGUMENT with up to 6 suggestions, at 0 credits; add the region or country to pick one
  • London boroughs resolve by their everyday names (Camden, Hackney, Greenwich, Westminster, Kensington and Chelsea), as do areas such as Clapham, London and UK post towns such as Hayling Island
  • A place that is not in our list (for example Shoreditch, London) returns 400 at 0 credits instead of searching a wrong area; use the borough or the city instead
  • locationCode is ignored when location is set
Improved

Facebook Ad Library: more than 30 ads per call

facebook/search and facebook/company-ads used to stop at Meta's first result page, about 30 ads, whatever the limit. A limit above 30 now also loads the next ads the way the Ad Library page does when you scroll, so one call can return about 70 to 80 ads. These calls take about 45 to 60 seconds instead of about 25. The price is unchanged.

  • limit 30 or below: unchanged (one page, ~25s)
  • limit above 30: up to ~70-80 ads per call, ~45-60s
  • if the extra ads cannot be loaded in time, the first page is returned with hasMore null and truncatedReason library-page
Improved

linkedin/profile: always-null section fields removed

Breaking change for linkedin/profile. From 15:38 UTC on 11 Oct until this change shipped, linkedin/profile returned experience, education and skills as null, plus sectionsStatus "unavailable_logged_out" and a sectionsNote. Those keys were always null or always the same value, so they are removed. LinkedIn shows these sections only to signed-in members and Captapi reads public pages as a logged-out visitor, so they are not available.

  • Breaking · linkedin/profile: experience, education and skills are removed from the response
  • Breaking · linkedin/profile: sectionsStatus and sectionsNote are removed from the response
Improved

LinkedIn endpoints now return only what a logged-out visitor sees

Breaking change for linkedin/profile. Captapi's LinkedIn endpoints now read only public pages, exactly as a logged-out visitor sees them. LinkedIn shows experience, education and skills only to signed-in members, so linkedin/profile no longer returns them. If your code reads those fields, treat a missing key as unavailable.

  • Breaking · linkedin/profile: experience, education and skills are no longer returned
  • Breaking · linkedin/profile: similarProfiles, projects, publications, articles, activity, recommendations, certifications, languages and currentCompanyLegalName are no longer returned
  • linkedin/profile keeps name, username, url, headline, location, about (when visible), followers, connections, currentCompany and profileImage, and now costs a flat 1 credit (was 2)
  • linkedin/profile: when LinkedIn serves its sign-in page instead of the public profile, the call fails with 502 UPSTREAM_UNAVAILABLE, reason login_wall, retryable, 0 credits
  • linkedin/search-posts: results come only from public search-engine results for LinkedIn posts. Niche queries can return fewer rows; no public match is a 200 with an empty list, truncatedReason no_public_matches and 0 credits
  • linkedin/company-posts: returns the recent posts a company page shows logged-out visitors (about 10) at a flat 1 credit. The last page carries truncatedReason public_page_limit; there is no deeper pagination
Improved

Provider-neutral values in transcript and path fields

Breaking value change. A handful of response fields now return stable, provider-neutral string values. Field names, types and shapes are unchanged - only the values below changed. If your code compares against an old value, switch the comparison to the new one. Old → new:

  • tiktok/transcript · source: "whisper" → "asr"
  • youtube/audio-transcript · asrProvider: "openai-whisper-1" → "asr-standard"
  • youtube/audio-transcript · asrProvider: "groq-whisper-large-v3-turbo" → "asr-fast"
  • tiktok/audience-demographics · timings.postsVia: "apify" → "extended"
  • tiktok/audience-demographics · timings.path: "apify+native_comments" → "extended+native_comments"
  • timings.path (any endpoint that returns timings): "apify-fallback" → "extended"
  • timings.path (any endpoint that returns timings): "decodo" → "extended"
  • tiktok/popular-hashtags · discoverySource: "apify_hashtag_videos" → "extended_hashtag_videos"
  • soundcloud/artist-tracks · truncatedReason: "apify-window" → "extended-window"
  • Unchanged: source "captions", timings.commentsVia, and every native value
  • Responses served from the 24h cache before this change can show an old value until they expire
Improved

tiktok/profile-region: authoritative region for far more accounts

TikTok's public profile page exposes the account's region field for almost nobody, so profile-region often had to fall back to inference — and for accounts with no usable public cues that honestly answered region null with regionSource "inferred" and confidence "low". The endpoint now also reads the creator country TikTok itself attaches to the account's own video feed before resorting to inference.

  • Accounts that have videos now get their region from TikTok's own account-country record (regionSource "tiktok") even when the profile page omits it
  • Inference remains the fallback for zero-video accounts, unchanged contract: regionSource "inferred" with a confidence grade, null when it genuinely cannot tell
  • Responses stay 2 credits; the extra lookup runs only when the profile page carries no region
Improved

tiktok/channel-posts: extended serves now bill by returned posts

Deep pages served by the extended fetcher were billed the same flat 2 credits as a 20-post native page, which under-priced 200-row answers. Extended serves now scale with what you actually receive; the native path and failures are unchanged.

  • Extended-path pricing: 1 credit per 20 returned posts, minimum 2 — a full 200-post page is 10 credits
  • Billing follows the posts you received, not the depth we fetched internally — a 20-post page from a deep window still costs 2 credits
  • Native serves stay a flat 2 credits, cache hits stay 0, and failures (including timeouts) stay 0 credits
Improved

tiktok/channel-posts: paging no longer re-fetches work the extended fetcher already did

Paging a profile seconds after page 1 could start a second identical extended fetch while the first was still finishing, and profiles with fewer videos than the requested depth were re-fetched on every deep page because the reuse check measured dataset length instead of what the original fetch had asked for.

  • A resume that arrives while an equally-deep fetch for the same profile is still in flight now joins that fetch and serves its result — a duplicate is never started while one is running
  • Reuse now judges coverage by the original fetch's requested depth: a completed fetch that asked for at least as many rows is a complete answer even when the profile has fewer videos than requested
  • Same data, same freshness window (15 minutes), lower cost — nothing about response shape, cursors, or billing changed
Improved

facebook/details + summarize: definitive 404 verdicts are remembered — repeats answer instantly instead of re-scraping for 25-32s

A URL that earned the two-source dead-content verdict (or Facebook's own 404) is deterministic: retrying can never succeed. Each repeat still re-ran two native renders plus an extended-fetcher read — 25-32 seconds per call for the same answer (one wrong-slug URL was called three times in three minutes).

  • The definitive verdict is remembered service-wide for 6 hours: a repeat of the same URL answers the same non-retryable 404 in under a second, at 0 credits, with no scrape and no extended-fetcher run
  • Only definitive verdicts are remembered — a transient retryable 503 always gets a fresh attempt, and a URL that starts working again is never blocked by a stale verdict for long
  • Verified there is no honest rescue for a wrong page slug: Facebook resolves a post URL only under its owner's slug — bare post-ID forms answer 404 on every public surface
Improved

truth-social: 404s now name the missing resource

Lookups for handles that do not exist on Truth Social (its own API answers NOT_FOUND 'Record not found') returned a bare 'Truth Social resource not found' — easy to read as an API fault rather than a wrong handle.

  • A missing account is now a typed ACCOUNT_NOT_FOUND naming the handle and pointing at the profile URL to verify — handles are exact, and guessed ones (e.g. a politician's 'obvious' username) are the usual cause
  • A missing or deleted post is a typed POST_NOT_FOUND with the post id
  • Status code and billing are unchanged: 404, retryable:false, 0 credits
Improved

tiktok/channel-posts: the extended leg now reuses fresh datasets and gives the free native leg a head start

Every first-page request used to start a paid extended fetch at t0 sized at three times the requested page — even when the free native leg was about to answer, and even when an identical fetch had finished seconds earlier. Repeat lookups of the same profile now reuse a recent result set at no extra latency, and the extended fetch only starts if the native leg hasn't answered within its head start.

  • A succeeded extended fetch for the same handle from the last 15 minutes serves page 1 directly when its result set covers the requested window — timings gains reuseAgeMs so a reused answer is visible
  • Page 1 now fetches limit+1 rows (one leftover row is all hasMore needs) instead of a flat 3x over-fetch; cursor pages keep the deeper window the createTime cutoff requires
  • The extended leg waits out a 5s native head start before starting a fetch — a healthy native page lands in 2-5s and no extended fetch is started at all
  • Verified live: two back-to-back calls for the same handle produced one extended fetch (second served from reuse), sized 21 rows for limit=20
Improved

ad-library/linkedin/search-ads: 3-10s answers for limits ≤ 25 — the first page is served without a browser render

The LinkedIn Ad Library search page turns out to be fully server-rendered: a plain proxy fetch returns the first ~25 ads in 3-12 seconds, while the headless browser render we used for every request took 25-80s and carried both remaining failure modes (degraded-pool session misses and the stall that eats the retry window — two more 503s on 24 Sep even after the parallel retry). The browser is now only used to grow the page past 25 cards.

  • limit ≤ 25 (the default): plain fetch first, ~3-10s typical; the parallel headless pair only runs if it misses — three independent chances, no serial-stall gap
  • limit > 25: unchanged grown ladder, plus a new last-resort plain fetch that ships the first ~25 cards as an honest partial page (hasMore=true) instead of a 503
  • A partial rescue that can't reach a requested offset window stays a retryable miss — never a fake isLastPage
  • Verified live: 20 ads in 6.6s, 12 in 9.1s, zero-hit in 2.3s, grown 40-ad page in 30.8s
Improved

facebook/profile-reels & details: managed fallback rescues render failures

Facebook's logged-out pages sometimes serve a degraded snapshot where the Reels grid or post payload never hydrates — profile-reels answered false NO_PUBLIC_REELS for pages with public reels, and details returned FACEBOOK_UNAVAILABLE for live watch URLs. Both endpoints now fall back to a managed scraping pool when the direct read misses: profile-reels lists the same page in seconds instead of burning ~22s re-confirming an empty render, and details rescues post, reel, and watch URLs after its two direct attempts.

  • profile-reels: false NO_PUBLIC_REELS on reel-having pages is rescued by the fallback pool
  • details: watch/post/reel URLs that fail both direct renders get a second chance instead of a 503
  • profile-reels: a page with no publicly visible Reels now answers 200 with an empty list, noPublicReels: true, and a note — not a 5xx (it is not a server failure)
  • The empty verdict is double-confirmed (direct render + fallback pool) before being claimed
  • Rescued responses may report rounded view counts (viewsIsApproximate: true)
Improved

ad-library/tiktok/top-ads: literal hits lead, ranked page fills behind

A keyword with one whole-word hit used to return just that one ad, while a keyword with zero hits returned TikTok's full keyword-ranked page — the better your match, the fewer ads you got. Literal hits now come first and the rest of the keyword-ranked leaderboard page fills in behind them up to limit. Per-ad matchedFrom separates the two ([] = ranked fill) and the envelope gains rankedFill next to literalMatches.

  • Literal whole-word hits ordered first; keyword-ranked fill follows up to limit
  • matchedFrom is always stamped when q is set — [] marks ranked fill
  • New envelope key rankedFill (null when q is omitted)
Improved

ad-library/tiktok: unsupported countries are a clear 400, not a retry loop

TikTok's Commercial Content Library exists to satisfy the EU Digital Services Act — it only covers the EU/EEA, the UK and Switzerland (32 countries). Searches with any other country (SA, US, AE, …) used to walk the full native fetch for ~37s and answer 503 'temporarily unavailable, retry shortly', sending callers into a retry loop for data TikTok will never have. /tiktok/search and /tiktok/ad-details now reject unsupported codes instantly with 400 UNSUPPORTED_REGION, retryable: false and the supported-country list in the response. Ad Library error bodies were also flattened: code/retryAfterSeconds now sit directly under error instead of a nested error.error.

  • Unsupported country → instant 400 UNSUPPORTED_REGION with supportedCountries[] (never billed)
  • retryable: false — this is a TikTok coverage limit, not an outage
  • Error envelope flattened: error.code, not error.error.code
Improved

facebook/profile-reels: errors now say why

Every miss used to be the same 'unavailable — retry shortly' 502, even when retrying could never help. The endpoint now separates the two cases: NO_PUBLIC_REELS (Facebook rendered the profile but shows no Reels to a logged-out viewer — login-walled profile or simply no Reels; retryable: false) and FACEBOOK_RENDER_FAILED (the render itself failed this time — transient, retryable: true with retryAfterSeconds). Stop-or-retry decisions no longer require guessing.

  • NO_PUBLIC_REELS — profile rendered, Reels not publicly visible, retrying won't help
  • FACEBOOK_RENDER_FAILED — transient fetch miss, retry shortly
  • both carry a machine-readable code and retryable flag
Improved

facebook/details: transient misses retry a fresh render

A single slow or walled proxy render used to surface straight to you as a 503 FACEBOOK_UNAVAILABLE — sometimes after a 140-second wait — even though the same URL often succeeds seconds later. The fetch now runs as two shorter attempts: a transient miss (timeout, wall render, missing story data) gets one fresh render before we answer, and the worst-case wait dropped from ~140s to ~120s. A Facebook 404 is still answered immediately without a retry.

  • transient render misses retry once automatically before a 503
  • worst-case latency capped lower (two 40s attempts, not one 120s wait)
  • 404 stays definitive — no retry, no extra wait
Improved

Ad libraries: advertiser unify, FB cursor/platforms, TikTok relevance + 2 credits

Facebook Ad Library search collapses the same page id to one advertiser name (no Facebook vs Facebook App split), adds platforms filter + nextCursor paging through the HTML batch, and documents status/date/media filters for live campaigns. TikTok Ad Library search relevance-filters so query tokens must appear in advertiser/copy (empty beats spam), keeps FB-parity null keys for headline/cta/landingUrl/spend/advertiser.id, ISO firstShown dates, and bills flat 2 credits native (Apify capped at 5 - never the old ~70 trap). DSA still withholds Meta-style spend; use Creative Center Top Ads for CTR/brand ranking.

  • FB: same advertiser id -> one canonical name/url/logo per response
  • FB: platforms + cursor/nextCursor; status/date/media already wired
  • TT: relevance filter + stable null schema + ISO dates
  • TT pricing: 2 native / 5 Apify cap (documented vs old ~70)
Improved

LinkedIn profile: experience/education/similarProfiles + restricted masking

LinkedIn /profile no longer short-circuits on a thin native shell — when HTML omits experience/education it enriches from Apify (detail, then full-sections) so B2B core fields actually arrive. Additive sections: experience[], education[], similarProfiles[], projects, publications, articles, activity, recommendations, certifications, languages. Guest-masked asterisk copy is returned as description:null with restricted:true instead of star spam. connections remaining null is documented as a LinkedIn logged-out platform limit.

  • Native->Apify enrich when experience/education missing
  • similarProfiles[] + richer section pass-through
  • Masked ******* -> null + restricted:true
  • connections null = LinkedIn guest limit (not a bug)
Improved

trending-feed: Creative Center orderBy/period/countryCode + Instagram profile pass-throughs

trending-feed stays the rich For You feed by default, and now accepts SC-style filters — orderBy (hot|like|comment|repost), period (7|30|120), countryCode, and page — to read TikTok Creative Center popular videos (same chart as videos/popular) with pagination.totalCount (~500) while still hydrating engagement/author when possible. Instagram basic-profile / channel-details / profile-search now surface categoryName, fbid, relatedProfiles[] (edge_related_profiles), businessAddress, and likeAndViewCountsDisabled from the existing web_profile_info payload — no new scrape, niche discovery + IG↔FB join without a creator-search endpoint.

  • trending-feed: orderBy / period / countryCode / page + pagination.totalCount
  • Instagram profiles: relatedProfiles[] + likeAndViewCountsDisabled
  • categoryName + fbid + businessAddress parity across profile endpoints
  • Post mappers: likeAndViewCountsDisabled (0 ≠ hidden likes)
Improved

YouTube search: viewCountText/Int + lives/shelves arrays

YouTube search already returned typed results and filters (type, sortBy, uploadDate, duration, region). Each hit now also exposes viewCountText (e.g. 750K) plus viewCountInt (750000) so compact UI labels stay honest. Response adds lives[] / shelves[], and continuationToken as an alias of nextCursor. Docs note: duration filters apply to long-form videos, not Shorts.

  • viewCountText + viewCountInt on search hits
  • lives[] / shelves[] partitioned arrays
  • continuationToken alias for nextCursor
Improved

Instagram Reels: views != plays, location{}, Highlights, commercial flags

engagement.views is video_view_count (reach-style) when Instagram exposes it; engagement.plays is total play count including replays — the gap can be ~2x. viewsInstagram remains Instagram-only plays (excludes Facebook cross-post); viewsFacebook is the FB share. location{} now includes slug, hasPublicPage, addressJson / address{}. New GET /v1/instagram/highlights and /highlights-details for persistent Story Highlight albums (not live Stories). isAd / isAffiliate / isPaidPartnership and previewComments.authorId are filled on feed and search paths when Instagram exposes them.

  • views vs plays vs viewsInstagram / viewsFacebook documented and emitted
  • location{id,name,slug,address…} on post/reel mappers
  • GET /highlights + /highlights-details (flat 1 credit each)
  • isAd / isAffiliate / isPaidPartnership on enriched search/feed rows
Improved

Account APIs: camelCase field names

GET /v1/account/balance (and sibling usage/history/daily-usage/most-used-routes/limits) now use camelCase keys — monthlyQuota, subscriptionCredits, topupCredits, totalCredits, subscriptionRenewsAt, creditsUsed, createdAt, etc. — matching the rest of the Captapi surface. Same data; naming only.

  • balance: monthlyQuota, subscriptionCredits, topupCredits, totalCredits, subscriptionRenewsAt
  • usage/history/routes: creditsUsed, cacheHit, statusCode, createdAt, …
Improved

Truth Social profile: bot/isPrivate flags, static media, 1 credit

GET /v1/truth-social/profile drops from 5 → 1 credit and adds bot, isPrivate (locked), group, discoverable, location, avatarStatic/headerStatic, emojis[], plus acceptingMessages/chatsOnboarded/tvAccount when present. Bio stays HTML-stripped. Docs warn that as of late 2025 Truth Social typically only exposes public profiles for prominent accounts without login — auth-gated accounts return a clear 404. Native lookup retries via Decodo when datacenter IPs hit Cloudflare.

  • 1 credit (was 5)
  • bot, isPrivate, group, location, avatarStatic/headerStatic, emojis
  • Docs + 404 copy for auth-gated / non-prominent accounts
Improved

Amazon seller storefront: badges, scrapedAt, pagination; drop raw leak

GET /v1/amazon-shop/page now returns seller name, scrapedAt, stable product shapes (price/currency/priceFormatted always present), isPrime/isBestSeller/isSponsored, canonical /dp/{ASIN} URLs, display priceFormatted ($1,234.56), and cursor pagination (nextCursor/hasMore). Removes rawFirstItem leakage. Docs clarify scope: seller storefronts (/sp?seller=), not influencer /shop/<handle> vitrines. Influencer shop URLs return 400 with a clear message. List price aligned to 1 credit per ~16-product page.

  • scrapedAt + isPrime/isBestSeller/isSponsored on products
  • seller.name, canonical /dp URLs, stable price fields, cursor pagination
  • Removed rawFirstItem; scope note vs influencer /shop/
Improved

Linktree page: email, GROUP children, verticals, 1 credit

GET /v1/linktree/page drops from 4 → 1 credit. Returns email when the creator publishes a mailto social, plus verticals and linkPlatforms. GROUP folders now nest child links under links[] (parentId on nested rows); typed links (SPOTIFY_*, SOUNDCLOUD_*, …) kept. socialAccounts includes soundcloud; socials remains the icon list. Browser-like fetch headers avoid Linktree 403s on datacenter UAs.

  • 1 credit (was 4)
  • email + verticals + linkPlatforms
  • GROUP.links nesting + parentId; soundcloud in socialAccounts
Improved

YouTube comments: author channel ID, publishedTime, heart fix

YouTube comments responses now include authorChannelId and publishedTime (ISO when InnerTube provides it) alongside the existing author string and publishedTimeText. hasCreatorHeart no longer false-positives on inactive heart tooltips. Billing stays a flat 2 credits per call.

  • authorChannelId for stable commenter joins
  • publishedTime ISO when available; publishedTimeText unchanged
  • hasCreatorHeart only true when the creator actually hearted the comment
Improved

Transcript source in the JSON body (non-breaking)

YouTube and TikTok transcript responses now include source in the body so RAG and analytics can weight caption quality vs Whisper. Existing transcript, transcriptSegments, wordCount, segments, and language fields are unchanged. YouTube also adds isAutoGenerated, isTranslated, and availableLanguages when captions are used.

  • source: "captions" | "whisper" (TikTok) | "fallback" (YouTube secondary path)
  • YouTube: isAutoGenerated, isTranslated, availableLanguages[]
  • No rename of segment fields; float seconds and ISO language codes unchanged
Improved

Billing metadata in every successful JSON response

Successful API responses now include cached, creditsUsed, requestId, fetchedAt, and cachedAt in the JSON body (in addition to the existing x-captapi-* headers). Use fetchedAt for time-series snapshots and requestId when contacting support.

  • Body fields: cached, creditsUsed, requestId, fetchedAt, cachedAt
  • New response header: x-captapi-request-id
  • cachedAt is set when the response was served from cache; otherwise null
Improved

Cheaper pricing on native list and search endpoints

Native-only list and search endpoints now bill a flat 2 credits per call instead of scaling per result. This covers YouTube comments, comment replies, channel videos, search, and channel playlists; TikTok top search and trending feed; Instagram hashtag search; Twitter/X user tweets and search; and Reddit subreddit posts, comments, transcript, search, and subreddit search. Apify-backed endpoints are unchanged.

  • YouTube comments, replies, channel videos, search, and playlists -> flat 2 credits
  • TikTok top search and trending feed -> flat 2 credits
  • Instagram hashtag search -> flat 2 credits
  • Twitter/X user tweets and search -> flat 2 credits
  • Reddit list, comments, transcript, and search endpoints -> flat 2 credits
Improved

Instagram Music Posts API retired

The Instagram Music Posts API has been removed - it was a duplicate of the Instagram Reels By Audio ID API (same scraper, same data) at a higher price. Use Reels By Audio ID instead; it accepts both audio IDs and full audio page URLs.

  • GET /v1/instagram/music-posts no longer exists (returns 404)
  • Migrate to GET /v1/instagram/reels-by-audio-id - pass your audio page URL or the numeric audio ID as audio_id
  • Old docs links redirect to the Reels By Audio ID page automatically
Improved

cache=false parameter on every endpoint

Every data endpoint now accepts an optional cache=false query parameter to bypass the cache and always fetch fresh data. Previously only transcript, summarizer, and Spotify endpoints supported it.

  • Add cache=false to any request when you need live numbers instead of the cached copy (fresh calls are billed as usual; the result still refreshes the cache)
  • Documented on all 179 API pages and available in the playground, MCP server, SDKs, CLI, and n8n node
  • Account endpoints (balance, usage) are always live and unaffected
Improved

More Instagram URL formats accepted

Instagram post endpoints accept every permalink shape Instagram generates.

  • Plural /reels/CODE/ links (as copied from the Reels feed) now work
  • Profile-scoped links like instagram.com/username/reel/CODE/ now work
Improved

TikTok & Instagram transcripts moved to a native pipeline

Transcript and summarize endpoints for TikTok and Instagram now resolve media directly from the platform and transcribe speech with our own pipeline; third-party actors remain only as a fallback.

  • Instagram Reel media resolves via Instagram's GraphQL in ~1-2 s; TikTok media downloads natively over our proxies
  • Typical TikTok transcript latency dropped from ~35-80 s to ~15-20 s
  • Transcripts contain only spoken words - post captions and descriptions are never returned as speech
Improved

Richer response data across 11 platforms

Closed field gaps against competitors with dedicated upstream sources.

  • Reddit: comment upvotes + threading (residential routing, optional OAuth app support)
  • Twitch: clip/profile metadata and streamer schedules via a dedicated actor
  • TikTok Shop: product reviews via a dedicated actor
  • Also enriched: link-in-bio socials/email, Rumble embeds/streams/comments, Pinterest pin details, SoundCloud artist fields, Bluesky embeds, Truth Social website, GitHub repo/license/topics, X profile counts
Improved

Real response examples for all 179 endpoints

Every endpoint page now shows a real captured response, refreshed in batches across the whole catalog.

  • Batches covered Twitter/LinkedIn/Reddit, TikTok Shop/Threads/Snapchat/ad libraries, GitHub/Facebook Marketplace/Events/Pinterest/Spotify, and Rumble/Twitch/Bluesky/SoundCloud/Kwai
  • Dozens of mapper fixes along the way: timestamped transcript segments, YouTube comment author metadata, duration parsing, Instagram actor replacement and more

Try what's new

Start with 100 free credits — no credit card required.