Download Videos with yt-dlp
Download public videos from YouTube, TikTok, Instagram, X, Reddit, Vimeo, Twitch, and other yt-dlp-supported platforms with RenderIO.
Download Videos with yt-dlp
RenderIO can download public videos from YouTube, TikTok, Instagram, X, Reddit, Vimeo, Twitch, Facebook, and other yt-dlp-supported platforms. You send a public URL to the API, RenderIO runs yt-dlp in managed cloud infrastructure, stores the file, and returns a storage_url you can use in your app.
Use this when you need a video file from a public URL without installing yt-dlp, keeping it patched, managing server IP blocks, or running binaries in serverless environments.
Only public content is supported. RenderIO does not bypass DRM, paywalls, private accounts, or content that requires a login. Make sure your use complies with the source platform's terms and applicable law.
Endpoint overview
RenderIO exposes two yt-dlp endpoints:
| Endpoint | Use it for |
|---|---|
POST /api/v1/ytdlp-download | Download and store the source video without post-processing. |
POST /api/v1/run-ytdlp-command | Download the source video, then run FFmpeg on it in the same request. |
Both endpoints are asynchronous:
- Submit the URL and get a
command_id. - Poll
GET /api/v1/commands/:commandIduntil the command reachesSUCCESSorFAILED. - Read the final download URL from
output_files.<key>.storage_url.
Download a YouTube video
Submit the YouTube URL to /api/v1/ytdlp-download:
curl -X POST https://renderio.dev/api/v1/ytdlp-download \
-H "Content-Type: application/json" \
-H "X-API-KEY: ffsk_your_api_key_here" \
-d '{
"input_urls": {
"in_video": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
},
"metadata": {
"source": "youtube"
}
}'import os
import requests
API_KEY = os.environ["RENDERIO_API_KEY"]
BASE_URL = "https://renderio.dev/api/v1"
response = requests.post(
f"{BASE_URL}/ytdlp-download",
headers={
"Content-Type": "application/json",
"X-API-KEY": API_KEY,
},
json={
"input_urls": {
"in_video": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
},
"metadata": {"source": "youtube"},
},
)
response.raise_for_status()
print(response.json()["command_id"])const API_KEY = process.env.RENDERIO_API_KEY;
const BASE_URL = "https://renderio.dev/api/v1";
const response = await fetch(`${BASE_URL}/ytdlp-download`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": API_KEY,
},
body: JSON.stringify({
input_urls: {
in_video: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
},
metadata: { source: "youtube" },
}),
});
const { command_id } = await response.json();
console.log(command_id);The response contains a command ID:
{
"command_id": "cmd_abc123"
}Poll for the download URL
Poll the command endpoint until the status is SUCCESS:
curl https://renderio.dev/api/v1/commands/cmd_abc123 \
-H "X-API-KEY: ffsk_your_api_key_here"When the download completes, the response includes an OutputFileMeta object:
{
"command_id": "cmd_abc123",
"status": "SUCCESS",
"output_files": {
"out_video": {
"file_id": "file_abc123",
"storage_url": "https://media.renderio.dev/downloads/cmd_abc123/out_video.mp4",
"filename": "out_video.mp4",
"size_mbytes": 45.2,
"status": "STORED",
"rendi_store_type": "OUTPUT",
"is_deleted": false
}
}
}Read the final URL from:
result.output_files.out_video.storage_url;The output key mirrors your input key. in_video becomes out_video, in_clip becomes out_clip, and so on.
Download TikToks and other platforms
Use the same endpoint and swap the URL:
{
"input_urls": {
"in_video": "https://www.tiktok.com/@username/video/7123456789"
}
}Other common examples:
| Platform | Example URL |
|---|---|
| YouTube | https://www.youtube.com/watch?v=dQw4w9WgXcQ |
| YouTube Shorts | https://www.youtube.com/shorts/VIDEO_ID |
| TikTok | https://www.tiktok.com/@username/video/7123456789 |
| Instagram Reels | https://www.instagram.com/reel/SHORTCODE/ |
| X / Twitter | https://x.com/username/status/1234567890 |
https://www.reddit.com/r/videos/comments/... | |
| Vimeo | https://vimeo.com/123456789 |
| Twitch clips | https://www.twitch.tv/username/clip/SLUG |
If a URL is private, deleted, geo-restricted beyond what RenderIO can fetch, or requires a login, the command returns FAILED with an error message in the command response.
Download and process in one call
Use /api/v1/run-ytdlp-command when you want to download a public video and immediately transform it with FFmpeg.
For example, download a YouTube video and extract MP3 audio:
curl -X POST https://renderio.dev/api/v1/run-ytdlp-command \
-H "Content-Type: application/json" \
-H "X-API-KEY: ffsk_your_api_key_here" \
-d '{
"input_urls": {
"in_video": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
},
"ffmpeg_command": "-i {{in_video}} -vn -c:a libmp3lame -q:a 2 {{out_audio}}",
"output_files": {
"out_audio": "audio.mp3"
}
}'curl -X POST https://renderio.dev/api/v1/run-ytdlp-command \
-H "Content-Type: application/json" \
-H "X-API-KEY: ffsk_your_api_key_here" \
-d '{
"input_urls": {
"in_video": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
},
"ffmpeg_command": "-i <<in_video>> -vn -c:a libmp3lame -q:a 2 <<out_audio>>",
"output_files": {
"out_audio": "audio.mp3"
}
}'When the command reaches SUCCESS, the MP3 URL is available at:
result.output_files.out_audio.storage_url;Common yt-dlp recipes
Save the raw source video
{
"input_urls": {
"in_video": "https://www.tiktok.com/@username/video/7123456789"
}
}Output URL: result.output_files.out_video.storage_url
Extract audio from a public video
{
"input_urls": {
"in_video": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
},
"ffmpeg_command": "-i {{in_video}} -vn -c:a libmp3lame -q:a 2 {{out_audio}}",
"output_files": {
"out_audio": "audio.mp3"
}
}{
"input_urls": {
"in_video": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
},
"ffmpeg_command": "-i <<in_video>> -vn -c:a libmp3lame -q:a 2 <<out_audio>>",
"output_files": {
"out_audio": "audio.mp3"
}
}Convert a downloaded video to 9:16
{
"input_urls": {
"in_video": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
},
"ffmpeg_command": "-i {{in_video}} -vf scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:-1:-1 {{out_reel}}",
"output_files": {
"out_reel": "reel-9x16.mp4"
}
}{
"input_urls": {
"in_video": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
},
"ffmpeg_command": "-i <<in_video>> -vf scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:-1:-1 <<out_reel>>",
"output_files": {
"out_reel": "reel-9x16.mp4"
}
}Trim the first 30 seconds
{
"input_urls": {
"in_video": "https://www.tiktok.com/@username/video/7123456789"
},
"ffmpeg_command": "-i {{in_video}} -t 30 -c copy {{out_clip}}",
"output_files": {
"out_clip": "first-30-seconds.mp4"
}
}{
"input_urls": {
"in_video": "https://www.tiktok.com/@username/video/7123456789"
},
"ffmpeg_command": "-i <<in_video>> -t 30 -c copy <<out_clip>>",
"output_files": {
"out_clip": "first-30-seconds.mp4"
}
}Payload rules
input_urlskeys must start within_.output_fileskeys must start without_.- FFmpeg placeholders use double braces, like
{{in_video}}and{{out_audio}}. - Command statuses are
QUEUED,PROCESSING,SUCCESS, orFAILED. - Output URLs live on nested file metadata objects, for example
output_files.out_video.storage_url.