B2B Social Video Transcripts
Pricing
from $21.25 / 1,000 video transcripts
B2B Social Video Transcripts
Transcripts from TikTok, Instagram Reels, Facebook Reels, X, Threads, podcasts, and Wistia, with pain points, buying signals, competitor mentions, and icebreakers for outbound. Watch creators for new videos. Your own speech and AI keys.
Pricing
from $21.25 / 1,000 video transcripts
Rating
0.0
(0)
Developer
Mamba Labs
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 hours ago
Last modified
Categories
Features
Share
Give it public video links from TikTok, Instagram Reels, Facebook Reels, X, Threads, podcasts, Wistia, or YouTube, or a watch list of creators and podcast feeds. It returns one row per video with the caption, creator, counts, and the spoken transcript. In outbound mode it also returns the opening hook, company, product, and competitor mentions, pain points, questions, buying signals with a 0 to 100 score, and 2 to 3 icebreakers that quote the speaker with a timestamp. Speech-to-text and AI calls run on your own API keys, so you pay those providers directly. Mamba Labs pays the platform costs of your run.
Features
- 7 sources at launch, no login: TikTok video URLs, Instagram Reels, Facebook Reels, X videos, Threads, podcasts through RSS, and Wistia embeds. YouTube runs on your own YouTube transcript key.
- Native text first: TikTok's own subtitles, Podcasting 2.0 transcript tags, and Wistia captions are used before any speech-to-text call, which saves you the provider cost.
- Your speech-to-text key, with a fallback: OpenAI, Groq, Deepgram, or AssemblyAI. If the first provider refuses or fails, the fallback key runs.
- Outbound fields on your AI key: OpenAI, Anthropic, or Gemini. One structured call per video.
- Watch lists: follow creators, podcast feeds, podcast keywords, and Threads hashtags. Each run transcribes only videos earlier runs have not seen and appends them to one named dataset.
- Filters that save money:
topic_filterskips off topic videos before any speech-to-text call, as a free row.transcript_filterflags rows by what was said. - Webhook: each row at or above your score goes to Slack, Clay, or a CRM as a plain POST.
- TikTok commenters: optional rows with the handle, name, and comment of each commenter on a high scoring video.
How the data is read
Every page is read with plain requests on the Apify proxy, with no login, no account, and no cookie of yours, and no other developer's actor is called.
| Source | What is read | Proxy |
|---|---|---|
| TikTok | The public video page, then TikTok's own subtitle file; else the video file in the same session | Apify default pool |
| Instagram Reels | The public reel embed page and its video file; for watch lists, the public profile page | Default pool for reels; residential for profiles |
| Facebook Reels | The public reel page and its SD video file; for watch lists, the page's reels tab | Default pool |
| X | The public syndication timeline and its video file | Default pool |
| Threads | The public profile page; for hashtags, the public tag search | Default pool |
| Podcasts | The RSS feed, its transcript tag, else the episode audio; the iTunes search API for keywords | Default pool |
| Wistia | The public media JSON: captions, else the smallest encoded video file | Default pool |
| YouTube | Your own key with ScrapeCreators, SearchAPI, or Supadata. The actor makes no request to YouTube for transcripts | None |
The actor downloads each media file itself and uploads it to your speech-to-text provider, because the media links are tied to the page session and a provider cannot fetch them.
Which provider gives timestamps
Icebreakers, pain points, and mentions carry a timestamp only when the transcript has one.
| Source or provider | Timestamps |
|---|---|
| TikTok subtitles, podcast transcript tags, Wistia captions | Yes, when the source file has them |
OpenAI whisper-1 | Yes. The default in outbound mode and with include_segments yes |
OpenAI gpt-4o-mini-transcribe, gpt-4o-transcribe | No, text only. The default in transcript mode, because it is faster and costs less |
| Groq, Deepgram, AssemblyAI | Yes |
Timestamp links open the video at that second on YouTube (?t=) and Wistia (?wtime=). On other platforms the link is the video URL and the time is in the time field.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
mode | string | transcript | transcript (default): transcript, caption, creator, and counts for each video given. outbound: the same plus pain points, buying signals, competitor mentions, and icebreakers on your AI key. watch_list: checks creators, podcast feeds, podcast keywords, and Threads hashtags for videos earlier runs have not seen, and transcribes only those. |
video_urls | array | TikTok video, Instagram reel, Facebook reel, X post, Threads post, podcast episode or RSS feed, Wistia page, or YouTube video URLs. A podcast feed URL reads its latest episodes, up to max_videos_per_creator. | |
creators | array | watch_list mode: profile URLs or platform:handle, for example instagram:hubspot, x:gong_io, facebook:HubSpot, threads:hubspot. TikTok has no creator feed without a login, so TikTok creators are refused with a free row. | |
podcast_feeds | array | Podcast RSS feed URLs. In watch_list mode each feed is watched for new episodes; in the other modes the latest episodes are read. | |
podcast_keywords | array | watch_list mode: search terms for finding podcast feeds through the iTunes search API; each feed found is watched. | |
hashtags | array | watch_list mode: Threads hashtags, without #. Hashtag pages on TikTok, Instagram, X, and Facebook need a login or do not list newest first, so only Threads is read. | |
wistia_ids | array | Wistia media IDs, or company page URLs that embed Wistia videos; the page is scanned for embedded media IDs. | |
include_commenters | string | no | yes or no (default no). On TikTok videos at or above webhook_min_score, adds one row per commenter: handle, name, profile URL, comment, time, likes. |
watch_list_name | string | default | Names the stored watch list. Rows are also appended to a named dataset b2b-social-video-transcripts- |
watch_list_depth | string | transcript | transcript (default) or outbound: what runs on each new video in watch_list mode. |
max_videos_per_creator | string | 10 | Most videos read per creator, feed, keyword result, or hashtag in one run. Default 10, up to 100. |
since_days | string | 30 | Skips videos older than this many days. Default 30. |
topic_filter | array | Keywords. A video whose caption, hashtags, and title match none of them is skipped before any speech-to-text call, as a free skipped_off_topic row. | |
transcript_filter | array | Keywords matched against the spoken words. Rows are kept, with transcript_match true or false. | |
stt_provider | string | openai | openai (default), groq, deepgram, or assemblyai. Used for videos with no native subtitle or transcript. |
stt_api_key | string | Your own key for the provider above. Without a key, only videos with native subtitles or transcripts are transcribed; the rest return a free no_speech_track row. Never stored or logged. | |
stt_model | string | Optional. With openai the default is gpt-4o-mini-transcribe in transcript mode and whisper-1 when timestamps are needed (outbound mode or include_segments yes), because only whisper-1 returns timestamps among OpenAI models. | |
stt_fallback_provider | string | Optional second provider, tried when the first refuses or fails. | |
stt_fallback_api_key | string | Your own key for the fallback provider. | |
ai_provider | string | openai | openai (default), anthropic, or gemini. Used by outbound mode and for translation. |
ai_api_key | string | Your own key for the AI provider. Without it, outbound mode returns transcripts only and charges no outbound-insights. Never stored or logged. | |
ai_model | string | Optional override. Defaults: gpt-4.1-mini (openai), claude-haiku-4-5 (anthropic), gemini-2.5-flash (gemini). | |
my_company | string | Your company name, so pain points and icebreakers fit your offer. | |
my_product | string | What you sell, in one line. | |
competitors | array | Brand names to flag when spoken. Each is matched exactly in the transcript and by the AI call. | |
translate_to_english | string | yes or no. Default yes in outbound mode, no in the other modes. Needs the AI key. | |
include_segments | string | no | yes or no (default no). Adds transcript_segments to each row. Outbound mode always fills them when the source gives timestamps. |
youtube_transcript_provider | string | scrapecreators, searchapi, or supadata. YouTube videos are transcribed only through your own key with one of these services. | |
youtube_transcript_api_key | string | Your own key for the YouTube transcript provider above. Without it, YouTube URLs return a free row. | |
youtube_transcript_fallback_provider | string | Optional second YouTube transcript provider. | |
youtube_transcript_fallback_api_key | string | Your own key for the fallback YouTube provider. | |
webhook_url | string | Optional. Each new video row with buying_signal_score at or above webhook_min_score is sent here as a POST with a Slack compatible text field. | |
webhook_min_score | string | 0 | 0 to 100. Default 0 sends every video row. |
max_charge_usd | string | Optional. The run stops before a charge that would pass this amount. Summary rows are always returned. |
Output
One row per video, creator check, or commenter, with the same fields in the same order. row_type tells them apart: video, creator (watch list checks), commenter, and run_summary (only for a refused input).
| Field | Type | What it holds |
|---|---|---|
row_type | string | One of: video, creator, commenter, run_summary. run_summary is the one free row written when the input is refused. |
platform | string | tiktok, instagram, facebook, x, threads, podcast, wistia, or youtube. |
video_url | string | The post, reel, episode, or media page the row is about. |
video_id | string | The platform id of the video or episode. |
post_type | string | video, reel, post, episode, or media. |
creator_handle | string | The account or show that posted it. |
creator_name | string | Display name of the account or show. |
creator_url | string | Profile, page, or feed URL. |
creator_followers | integer | Follower count when the page shows it. |
posted_at | string | When the video was posted, UTC. |
duration_seconds | number | Length of the video or episode. |
caption | string | Post text, reel caption, or episode description. |
hashtags | array | Hashtags in the caption, without #. |
mentions | array | Accounts mentioned in the caption, without @. |
play_count | integer | Play or view count when the page shows it. |
like_count | integer | Like count when the page shows it. |
comment_count | integer | Comment count when the page shows it. |
share_count | integer | Share count when the page shows it. |
save_count | integer | Save count when the page shows it. |
transcript_text | string | The spoken words, as text. |
transcript_segments | array | Timed pieces of the transcript, each {start, end, text} in seconds. Filled when include_segments is yes, or always in outbound mode. Empty when the source gives no timestamps. |
transcript_source | string | native_subtitle, podcast_transcript_tag, platform_captions, youtube_api: |
language | string | Language of the speech, as the source or provider reports it. |
transcript_english | string | English translation when the speech is not English and translation is on. Null when the speech is English. |
transcript_match | boolean | true when the spoken text contains a transcript_filter keyword; null when no transcript_filter was given. |
opening_hook | object | Outbound mode: the first 1 to 2 sentences spoken, {text, start, time, link}. |
company_mentions | array | Outbound mode: companies named in the speech, each {name, start, time, quote, link}. |
product_mentions | array | Outbound mode: products or tools named in the speech, each {name, start, time, quote, link}. |
competitor_mentions | array | Outbound mode: names from your competitors list said in the speech, each {name, start, time, quote, link}. |
pain_points | array | Outbound mode: problems the speaker describes, each {quote, paraphrase, start, time, link}. |
questions_asked | array | Outbound mode: questions the speaker asks, each {quote, start, time, link}. |
buying_signals | array | Outbound mode: phrases that point to a purchase, each {phrase, type, start, time, link}. Types include switching_tools, hiring_for, evaluating, budget, pain, growth. |
buying_signal_score | integer | Outbound mode: 0 to 100, how strongly the speech points to a purchase. |
icebreakers | array | Outbound mode: 2 to 3 opening lines that quote the speaker, each {line, start, time, link}. |
topics | array | Outbound mode: the main topics, as short phrases. |
watch_list_name | string | The watch list this row belongs to, in watch_list mode. |
first_seen_at | string | When the watch list first saw this video, UTC. |
video_status | string | ok, no_speech_track, skipped_off_topic, not_found, blocked, or input_invalid. |
new_videos | integer | Creator rows: how many videos this check found that earlier runs had not seen. |
commenter_handle | string | Commenter rows: the commenter's handle. |
commenter_name | string | Commenter rows: the commenter's display name. |
commenter_url | string | Commenter rows: the commenter's profile URL. |
comment_text | string | Commenter rows: what they wrote. |
comment_posted_at | string | Commenter rows: when they wrote it, UTC. |
comment_like_count | integer | Commenter rows: likes on the comment. |
row_status | string | ok, or why this row carries no data: no_results, no_change, partial, blocked, or error. |
error_reason | string | Why the row is not ok. A refused input reads input_invalid: followed by what to fix. |
billable_events_json | string | What this row was billed as, for example {"video-transcript":1}. {} means free. |
scraped_at | string | When the row was written, UTC. |
Pricing
Pay per event. Rows with no speech, off topic, not found, or blocked are free, and so is a refused input.
| Event | Free plan | Bronze | Silver | Gold |
|---|---|---|---|---|
video-transcript, one video with a transcript, first 3 minutes included | $0.025 | $0.02375 | $0.0225 | $0.02125 |
transcript-minute, each started minute after the first 3 | $0.008 | $0.0076 | $0.0072 | $0.0068 |
outbound-insights, outbound fields for one video, outbound mode only | $0.02 | $0.019 | $0.018 | $0.017 |
creator-check, one creator, feed, keyword, or hashtag checked | $0.005 | $0.00475 | $0.0045 | $0.00425 |
creator-check-residential, one Instagram profile checked | $0.045 | $0.04275 | $0.0405 | $0.03825 |
commenter-row, one TikTok commenter | $0.002 | $0.0019 | $0.0018 | $0.0017 |
apify-actor-start, once per run (one per GB of memory; the default 1024 MB is one) | $0.0085 | $0.0085 | $0.0085 | $0.0085 |
Per 1,000 rows of video-transcript: $25.00 on the free plan, $21.25 on Gold.
Free plan cap: 1.50 USD of evaluation a month, about 60 rows. Any paid Apify plan removes the cap, and it resets on the 1st. The run stops before a charge that passes your maximum charge per run in Apify or your max_charge_usd input.
Mamba Labs pays the platform costs of your run, Apify proxy traffic included.
Your speech-to-text and AI costs go to your own provider accounts. Examples from the providers' own pages, read 2026-11-12: OpenAI gpt-4o-mini-transcribe 0.003 USD a minute and whisper-1 0.006 USD a minute; Groq whisper-large-v3-turbo 0.04 USD an hour; Deepgram Nova-3 0.0043 USD a minute; AssemblyAI Universal-2 0.15 USD an hour. A 1 minute video in outbound mode costs about 0.004 to 0.007 USD on OpenAI keys, plus the Store events above.
Usage examples
Transcripts of a few videos.
{ "mode": "transcript", "video_urls": ["https://www.tiktok.com/@washingtonpost/video/7198260520103841070"], "stt_api_key": "<your OpenAI key>" }
Outbound fields for a prospect's podcast appearance.
{ "mode": "outbound", "video_urls": ["https://rss.buzzsprout.com/2517440.rss"], "max_videos_per_creator": "1", "stt_api_key": "<your key>", "ai_api_key": "<your key>", "my_company": "Acme", "my_product": "pipeline forecasting for sales teams", "competitors": ["Clari", "Gong"] }
A daily watch list. Save an Apify task with this input and attach an Apify schedule (daily is a good start). The actor needs no scheduler of its own.
{ "mode": "watch_list", "watch_list_name": "saas-founders", "creators": ["instagram:hubspot", "x:gong_io", "threads:hubspot"], "podcast_keywords": ["b2b sales"], "hashtags": ["saas"], "watch_list_depth": "outbound", "stt_api_key": "<your key>", "ai_api_key": "<your key>", "webhook_url": "https://hooks.slack.com/services/...", "webhook_min_score": "60" }
Every run appends its new rows to the named dataset b2b-social-video-transcripts-<watch_list_name> in your account. Seen video IDs are kept in the named key-value store b2b-social-video-transcripts-<watch_list_name>-state. Delete that store to start the list over.
Clay. Number and on or off inputs are text fields, which is what Clay sends. A list input takes a JSON list, so put the column inside a one item list, for example ["<the Video URL column>"]. To read a watch list from Clay, point an HTTP column at the named dataset's items URL.
MCP. The Mamba Labs MCP server @mambalabsdev/mcp-b2b-social-video-transcripts exposes this actor to Claude and other MCP clients.
Error handling
| Case | What you get |
|---|---|
| Missing or unreadable input | One free row, row_type run_summary, error_reason starting input_invalid: with what to fix. The run ends successfully and charges nothing but the run start |
| A video with no subtitle and no speech-to-text key | A free row, video_status no_speech_track |
| Silence, or a provider that returns almost no text | A free no_speech_track row. Speech-to-text models can make up a short line on a silent video, so text under about 20 characters a minute counts as no speech |
| Your speech-to-text key is refused | The fallback key runs; if it also fails, a free no_speech_track row with each provider's error, with your key removed |
| Your AI key is refused | The row keeps its transcript, row_status partial, a note, and no outbound-insights charge |
| A removed, private, or blocked post | A free row, video_status not_found or blocked, with the reason |
| Your maximum charge is reached | The run stops before the next video. A video already transcribed is always delivered; its later events are charged only as far as the cap allows |
| The run is close to its timeout | The actor stops starting new work 90 seconds before the timeout and delivers what it has |
Limitations
- Hashtag watch lists run on Threads only. TikTok, Instagram, and X hashtag pages need a login or signed requests; Facebook hashtag pages do not list newest first.
- TikTok creators cannot be watched. TikTok's creator list needs signed requests. Give TikTok video URLs in transcript or outbound mode.
- TikTok subtitles exist on about 3 of 5 videos. The rest need your speech-to-text key.
- X lists are curated, not newest first, so a new X video can show up a few runs late.
- Threads post URLs are read through the creator's profile feed, because a single post page carries no post data without a login.
- YouTube transcripts need your own key with ScrapeCreators, SearchAPI, or Supadata. Without one, YouTube rows are free
no_speech_trackrows. - Long videos on OpenAI's gpt-4o transcribe models: MP3 audio is split into about 4 minute pieces. A video file cannot be split without transcoding, so a video over about 4 minutes runs on
whisper-1instead, and OpenAI and Groq take files up to 25 MB. Deepgram and AssemblyAI take larger files. - Buyer key routes: no Mamba Labs key is used for Groq, Deepgram, AssemblyAI, Anthropic, Gemini, ScrapeCreators, SearchAPI, or Supadata. Those routes are tested on recorded responses and on the refused key path; your first run with your key is the live test.
- Watch lists fill back in time. Each run takes up to
max_videos_per_creatorunseen videos per creator insidesince_days, newest first. With a widesince_days, later runs keep picking up older videos until the window is used up. Keepsince_daysshort (the default is 30) to transcribe only new videos. - TikTok commenters: up to 200 comments per video, read from TikTok's public comment list. Each commenter row is charged, so set
webhook_min_scoreto limit commenters to high scoring videos. - Threads videos carry no length in the public page, so Threads rows leave
duration_secondsempty and are never charged extra minutes. - A refused page is final. A 403, 429, or challenge page returns a free
blockedrow; the actor does not retry on another network to get around it. X answered 429 on 1 of 6 creator checks in testing. - Speech-to-text keys tested live: OpenAI only (
whisper-1andgpt-4o-mini-transcribe), and the outbound fields on OpenAIgpt-4.1-mini. - Wistia videos are found from your input only. Give media IDs or page URLs that embed Wistia; search engines do not list them.
Mamba Labs actor suite
Built by Mamba Labs.