Universal Media Extractor avatar

Universal Media Extractor

Pricing

from $1.00 / 1,000 results

Go to Apify Store
Universal Media Extractor

Universal Media Extractor

Extract videos, audio, and metadata from 1000+ websites including YouTube, TikTok, Twitter/X, Instagram, Vimeo, Facebook, Twitch, and many more. Stream directly to your cloud storage or get direct download URLs for your pipelines.

Pricing

from $1.00 / 1,000 results

Rating

5.0

(1)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

47

Total users

7

Monthly active users

5 days ago

Last modified

Share

Universal Media Extractor: Video, Audio and Metadata from Any Link

This actor turns a video or audio link from YouTube, TikTok, Twitter/X, Instagram, Vimeo and 1000+ other sites into structured metadata, direct format URLs, or a downloaded file in your own storage. Extract mode reads the page and returns titles, descriptions, stats and direct links without downloading anything. Download mode saves the file to Apify storage or your own bucket. Stream mode sends the file straight to your S3 or Google Cloud Storage bucket without saving it in Apify storage. Export what you get to JSON, CSV or Excel, or read it through the API.

Why This Scraper?

  • One input field, 1000+ sites. Paste almost any video or audio page link, no separate setup for each platform.
  • Three modes for three jobs. Pull metadata and direct URLs only, save the file to Apify storage, or send it straight to your own S3 or Google Cloud Storage bucket.
  • Format control. Pick the best available quality, audio only, or a resolution cap, with a plain format string.
  • Playlist and channel aware for listings. Flatten a playlist or channel link into its video URLs in one call, without opening every video.
  • Metadata before you commit to storage. Extract mode returns titles, descriptions, view counts and direct format URLs without downloading the file, so you can decide what is worth saving.
  • Optional proxy routing. Route requests through Apify Proxy for sites that block direct connections, or run without a proxy by default.
  • Built for automation. Call it from your own code, a schedule, or a no-code tool through the Apify API.

Use Cases

  • Content archiving: save a copy of a video or audio file to your own S3 or Google Cloud Storage bucket for backup or compliance records.
  • Media processing pipelines: get direct format URLs and metadata to feed into transcription, captioning or machine learning workflows without storing the file yourself.
  • Catalog and research: collect titles, descriptions, view counts and other metadata across many links for analysis or reporting, without downloading anything.
  • App and bot integrations: pull thumbnails, durations and direct URLs to reference media inside your own product.
  • Playlist triage: flatten a playlist or channel link into its video URLs first, then process only the ones you need.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
id"sample123abc"
title"Sample Video Title"
description"A short sample description of the video."
duration212
view_count1500000
like_count42000
upload_date"20240115"
uploader"Sample Channel"
channel"Sample Channel"
thumbnail"https://example.com/thumbnail.jpg"
thumbnailslist of thumbnail URLs at different sizes
webpage_url"https://www.youtube.com/watch?v=sample123abc"
ext"mp4"
extractor"youtube" (name of the site handler that read the link)
tags["music", "sample"]
is_livefalse
formatslist of available formats, each with a format id, extension, resolution and direct URL
storage_urllink to the saved file (download and stream modes only)
storage_type"apify", "s3", or "gcs" (download and stream modes only)
filename"sample123abc.mp4" (download and stream modes only)

Extract mode returns the fields above at the top level of the record, with no storage_url, storage_type or filename since nothing is downloaded. Download and stream mode records carry storage_url, filename and storage_type at the top level, with the rest of the metadata nested under an info object.

How to Use

  1. Paste one link into url, or several into urls. Supported link shapes: a watch link (youtube.com/watch?v=), a short link (youtu.be/), a Shorts link (/shorts/), an embed link (/embed/), a playlist link (/playlist?list=) and a channel link (/@handle/videos). If you leave both url and urls empty, the actor runs one example of each of those six shapes and delivers up to 6 result rows (one per distinct video): the four example video links each point to a different video, plus one listing row for the first video of the example playlist and one for the first video of the example channel. If the playlist's or the channel's first video is the same video as one already returned, it is returned once, so a default run never delivers more than 6 rows. In every mode (also download and stream) the playlist and channel examples are only listed, never downloaded, so a default run saves at most four files. If you set url, only your link is processed.
  2. Pick a mode: extract for metadata and direct links only, download to save the file to Apify storage or your bucket, or stream to send the file straight to your S3 or GCS bucket.
  3. Set format to control quality (left on best, download mode takes the best video plus audio and stream mode prefers a single file), and fill storage_type plus storage_config when you choose download or stream to your own bucket.
  4. Click Start, then read the result from the dataset, or open the link it contains to get the stored file.

Extract metadata only:

{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"mode": "extract"
}

Download up to 1080p to Apify storage:

{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"mode": "download",
"format": "best[height<=1080]"
}

Stream audio only to Google Cloud Storage:

{
"url": "https://soundcloud.com/artist/track",
"mode": "stream",
"format": "bestaudio",
"storage_type": "gcs",
"storage_config": {
"bucket": "my-audio-bucket",
"credentials_json": "{...service account JSON...}"
}
}

Flatten a playlist into its video URLs, routed through Apify Proxy:

{
"url": "https://www.youtube.com/playlist?list=PLsample0000000000",
"mode": "extract",
"extract_flat": true,
"proxy": { "useApifyProxy": true }
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/universal-media-extractor").call(run_input={"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "mode": "extract"})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["title"], item["duration"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/universal-media-extractor').call({ url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', mode: 'extract' });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

About playlists and channels

The actor processes every link from url and urls (identical links removed), one after another. A video is returned once per run, however many links reach it (for example watch?v=ID, youtu.be/ID and embed/ID, or a single link plus a playlist that contains it): the later links add no row, no charge and no download, in every mode and whether or not incremental mode is on. The OUTPUT record counts them under duplicateLinksSkippedCount. A video link adds one result row. A playlist or channel link adds one result row per video (each billed as a normal result row, delivered rows only), up to max_items_per_url videos (default 10), after playlist_items (for example 1,3,5-7) is applied. Results stop at that cap: when a playlist or channel has more videos, the run log shows a warning and the OUTPUT record lists the link under truncated (link, rows delivered, cap). Raising max_items_per_url returns, and bills, one result row for every extra video. In extract mode with extract_flat on, each row is the playlist's own listing entry; otherwise every video is read on its own, and in download or stream mode every video is saved on its own. A link or video that fails adds no row and is not billed (a bot check from the site is retried on up to two fresh Apify Proxy connections first; if it persists the reason reads "The site asked for a bot check on this connection"); the reason is saved under the ERROR key of the run's key-value store, and the run fails only when nothing succeeded. Several links in one run share a single run start.

Quality, format and file names. preferredQuality (144p to 2160p) caps the video height, preferredFormat picks a container (mp4, mkv, webm ...) or converts to audio (mp3, m4a, wav ...), and filenameTemplateParts (title, uploader, timestamp) names saved files. A custom format always wins over preferredQuality. In stream mode, choosing an audio format, a container or subtitles makes the run save the file in download mode first, because those need a local file. username and password are applied when set.

Subtitles. With write_subtitles on (and subtitle_langs to pick languages), download mode saves each subtitle file to the same storage as the video and lists them in the row under subtitleFiles (language, link and storage key). stream mode then switches to download mode. extract mode saves no files: its rows already include the subtitle tracks the site offers, with their links.

Extra output fields. Every row also carries input (the link it came from); download rows add downloadedFileUrl (same as storage_url) and fileKey (the real storage key of the file: the Key-Value Store key, or the S3 key or GCS object name including your prefix); saved file names always end with the video ID, so two videos with the same title never overwrite each other; audioOnlyUrl and videoOnlyUrl appear when the source offers separate audio-only or video-only streams.

Recurring runs: incremental mode and resume

Set incrementalMode to remember videos between runs (default none: nothing is remembered and every run returns every video, exactly as before).

  • new-only: the first run returns every video; later runs return only videos not seen before.
  • changed-only: later runs return new videos plus videos whose details changed.

Videos are remembered by site and video ID, in a named Key-Value Store of your account, per set of links (or per stateKey when you set one). Rows carry changeType (NEW or UPDATED), changedFields, firstSeenAt and lastSeenAt. A video that is not returned is not pushed, not billed, and in download or stream mode not downloaded again (its metadata is read first to decide). Videos that disappear from a playlist or channel are never reported. A video counts as changed when its own details change (title, description, tags, duration, availability and similar). view_count and like_count never count, and you can add more names in ignoreFieldsForChanges (dotted paths such as chapters.title work). Signed stream links, thumbnails, subtitle lists, storage links and file names are never compared, but are still returned. The remembered state is only saved for videos that were delivered or found unchanged, so a failed video is tried again next run.

resumeFromRunId continues one earlier run: links and playlist or channel videos already in that run's dataset are skipped, so only the rest is returned and billed. Resume and incremental mode can be combined.

Send results into your apps (MCP connectors)

Optionally pipe the delivered result rows into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra step after the run: the Apify dataset is never changed, and a connector error never fails the run.

  1. Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the mcpConnectors field ("Pipe results into your apps").
  3. For Notion, also set notionParentPageUrl to the page where entries should be created.
  4. maxNotifyListings caps how many rows are written to each connector per run (default 50, maximum 1000).

Each row is written as a short plain-text summary; the complete record stays in the dataset. Leave mcpConnectors empty to skip.

Input Parameters

ParameterTypeDefaultDescription
urlstring(none)Video, audio, playlist or channel URL to process. The Console prefills a sample YouTube link.
urlsarray of stringsone example of each of the six shapesMore links, merged with url; identical links, and links that reach the same video, are returned once. When both url and urls are empty, one example per link shape is processed.
modestringextractextract (metadata only), download (save to storage), or stream (send straight to cloud storage).
formatstringbestFormat selection string, for example bestaudio, bestvideo+bestaudio, or best[height<=720]. Left on best, download mode uses the best video plus audio. A custom value wins over preferredQuality.
preferredQualitystring(none)Maximum video height, 144p to 2160p.
preferredFormatstring(none)Container (mp4, mkv, webm ...) or audio format (mp3, m4a, wav ...) for saved files. Download and stream modes.
filenameTemplatePartsarray(none)Parts used to name saved files: title, uploader, timestamp.
storage_typestringapifyWhere to save the file for download and stream modes: apify, s3, or gcs.
storage_configobject(none)Cloud storage settings. For S3: bucket, region, aws_access_key, aws_secret_key, prefix, acl. For GCS: bucket, credentials_json, prefix, make_public. acl and make_public apply in stream mode only; download mode returns a signed link valid for 7 days.
proxyobject(none, direct connection)Apify Proxy configuration. Leave empty to connect directly; the Console suggests turning on Apify Proxy as a starting point.
extract_flatbooleanfalseFor playlists and channels in extract mode, return each video's listing entry without reading its full metadata.
max_items_per_urlinteger10Maximum videos taken from one playlist or channel link; the list stops there and the run says so. Each extra video is one more billed row.
resumeFromRunIdstring(none)Run or dataset ID of an earlier run; links and playlist videos already delivered there are skipped (not returned, not billed).
incrementalModestringnonenone returns everything every run. new-only and changed-only remember delivered videos between runs. See the incremental section above.
stateKeystring(derived from your links)Names the remembered set of videos (incremental mode only).
ignoreFieldsForChangesarrayview_count, like_countFields that never count as a change (incremental mode only).
mcpConnectorsarray[]Optional MCP connectors that receive a summary of the delivered rows. See the MCP section above.
notionParentPageUrlstringnoneNotion page under which entries are created (Notion connector only).
maxNotifyListingsinteger50Cap on rows written to each connector per run; does not affect the dataset.
playlist_itemsstring(none)Pick playlist items, for example 1,3,5-7.
write_subtitlesbooleanfalseSave subtitle files in download mode (listed under subtitleFiles). Extract rows carry the subtitle tracks the site offers.
subtitle_langsarray(none)Subtitle languages to save.
geo_bypassbooleantrueTry to read videos that are restricted to certain countries.
ignore_errorsbooleanfalsePassed to the downloader. A link that fails adds no row either way and the problem is saved under ERROR.
usernamestring(none)Account name for login-protected content.
passwordstring(none)Account password for login-protected content.

Output Example

Sample shape: values are illustrative placeholders, not from a live record.

{
"id": "sample123abc",
"title": "Sample Video Title",
"description": "A short sample description of the video.",
"duration": 212,
"view_count": 1500000,
"like_count": 42000,
"upload_date": "20240115",
"uploader": "Sample Channel",
"channel": "Sample Channel",
"thumbnail": "https://example.com/thumbnail.jpg",
"thumbnails": [
{ "url": "https://example.com/thumbnail_small.jpg", "width": 120, "height": 90 }
],
"webpage_url": "https://www.youtube.com/watch?v=sample123abc",
"ext": "mp4",
"extractor": "youtube",
"tags": ["music", "sample"],
"is_live": false,
"formats": [
{ "format_id": "22", "ext": "mp4", "resolution": "1280x720", "url": "https://example.com/stream/720p.mp4" }
]
}

Plan Requirement

Runs on any Apify plan. The proxy field is empty by default, so requests go out directly. In our check, a plain YouTube watch page loaded from a datacenter connection without a proxy, so YouTube extract mode needs no extra setup. We did not measure the stream and download endpoints, or other sites, so if a site refuses the direct connection, switch on Apify Proxy under Connection (a residential group is the usual fix, and proxy traffic is billed to your account separately).

Pricing. This actor is pay per event. Two events are charged: apify-actor-start, once per run (several links in one run share one start), and result, once per row delivered to the dataset. Failed links add no row and are never billed for a result. Playlist and channel links add one billed row per video. The Pricing tab shows the current rates for your plan.

FAQ

How much does it cost?

Per run you pay the start event once, plus the result event for each row in the dataset. Extract, download and stream modes bill the same events: one row per delivered link or video. A failed link adds no row, so no result charge. In incremental mode, videos that are not returned (already seen, or unchanged) add no row and no charge. A video reached through several links in one run is one row and one charge. A run with no url or urls delivers at most six rows (four example videos, plus the first video of the example playlist and of the example channel). Compute and any proxy traffic are separate platform usage, and the Pricing tab lists the current rates.

This actor reads and downloads media the same way a browser or media player would, from the link you give it, and it does not remove copy protection or DRM. Whether you may keep, use or redistribute a downloaded file depends on the content owner's rights, the source platform's terms of service, and the copyright law that applies to you. Many places allow a personal, private copy but restrict redistribution or commercial use of someone else's work. Get your own legal advice before redistributing anything, and stick to content you own, have permission for, or that carries a license allowing reuse.

Can I schedule this to catch new uploads automatically?

Yes. Schedule the actor from the Schedules tab and set incrementalMode to new-only (only videos not seen before) or changed-only (new videos plus videos whose details changed) on a playlist or channel link. The default, none, tracks nothing and returns every video every run. See the incremental section above; resumeFromRunId continues one interrupted run.

Download and stream mode save the file to storage and give you a link (storage_url) plus metadata, not the raw file bytes inside the dataset record. Open the link to get the actual video or audio file. Also, stream mode only sends data straight to S3 or GCS; with storage_type set to apify, a stream mode run automatically uses download mode instead, since direct streaming isn't offered for that storage. A format that combines separate video and audio streams, such as bestvideo+bestaudio, also makes a stream run use download mode.

Why did my run fail instead of returning an empty result?

If none of the links can be read, for example a link is invalid, the content was removed or made private, or the site refuses the connection or asks for a bot check on every attempt, the run fails. Older versions added an error row to the dataset; this version does not, so a failed link is never billed for a result row. The problem is shown in the run status message and saved under the ERROR key of the run's key-value store, and the OUTPUT key holds a run summary (links requested, rows delivered, failures). Try again after checking the link, or add a proxy under Connection if the site is blocking the default connection.

Can I use this with AI agents or MCP?

Yes. Call it like any other Apify actor from an AI agent, an MCP client that exposes Apify actors as tools, or your own automation, through the Apify API. This actor does not push results into a third-party app on its own; the dataset records and the direct URLs they contain are what you feed into your agent or workflow.

🔗 Want more social media data?

Pair this actor with these related scrapers from the same team:

📱 Tiktok Live Recorder
Record TikTok live streams to MP4 with full metadata, all stream quality URLs, and...
📱 Lemon8 Media Scraper
Lightweight Lemon8 scraper for extracting image and video URLs from posts, with optional...
🎬 Twitch Scraper
Scrape Twitch data at scale, including channels, live streams, clips, VODs, and top...
📱 TikTok Profile, Hashtag, Search, Video & Trending Scraper
Scrape TikTok without login. Extract profiles, bios, follower stats and videos; search by...
📱 ViewStats Scraper
Scrape YouTube channel analytics from ViewStats. Look up channels by handle, URL, or...
🎬 YouTube Transcript & Subtitle Scraper
Extract transcripts and subtitles from YouTube videos in bulk using video, playlist...

👉 Browse all abotapi scrapers

💬 Support

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.