RenderIO
API referenceCommands

Download Video (yt-dlp)

API reference for downloading a publicly accessible video from YouTube, TikTok, Instagram, X/Twitter, Reddit, Vimeo, Twitch, Facebook, and other yt-dlp-supported platforms.

Download Video (yt-dlp)

POST /api/v1/ytdlp-download

Download a publicly accessible video using yt-dlp. RenderIO fetches the video from the source platform, stores it in managed R2 storage, and returns a signed URL. The endpoint returns immediately with a command_id that you poll for the result.

Only public content is supported — no DRM bypass, no private accounts, no paywalled content.

Authentication

Requires API key via X-API-KEY header.

Video downloads are available during trials and on the Growth plan or higher.

Request

Headers

HeaderTypeRequiredDescription
Content-TypestringYesMust be application/json
X-API-KEYstringYesYour API key with ffsk_ prefix

Body

interface YtDlpDownloadRequest {
  input_urls: Record<string, string>;  // in_* aliases mapped to public video URLs
  format_selector?: string;            // Quality preset (default: "best")
  metadata?: Record<string, string | number | boolean>; // Max 10 keys
}
FieldTypeRequiredDescription
input_urlsRecord<string, string>YesMap of alias names (must start with in_) to public video URLs. Each URL is downloaded independently.
format_selectorstringNoQuality preset for the download. Defaults to "best" (highest available quality). See table below for all presets.
metadataRecord<string, string | number | boolean>NoArbitrary key-value metadata attached to the command. Maximum 10 keys.

Format selector presets

PresetDescription
"best"Best available quality (default)
"2160p"Max 4K resolution
"1440p"Max 1440p resolution
"1080p"Max 1080p (Full HD)
"720p"Max 720p (HD)
"480p"Max 480p (SD)
"360p"Max 360p
"audio_only"Audio only, no video
"worst"Lowest available quality (smallest file)

If a video is not available at the requested resolution, yt-dlp downloads the closest available quality below the cap.

This endpoint does not accept ffmpeg_command or output_files. To post-process the downloaded video, use POST /api/v1/run-ytdlp-command instead.

Response

200 OK

{
  command_id: string;
}
FieldTypeDescription
command_idstringUnique identifier for the command. Use this to poll for status.

Getting the downloaded file URL

Poll GET /api/v1/commands/:commandId until status is SUCCESS, then access the file at:

result.output_files.out_<suffix>.storage_url

The downloaded file is keyed as out_<suffix> where <suffix> matches your in_<suffix> input key. For example, in_videooutput_files.out_video.storage_url.

Error responses

StatusErrorDescription
401UNAUTHORIZEDMissing or invalid API key.
403FORBIDDENVideo downloads are not enabled for the current plan.
422VALIDATION_ERRORMissing input_urls, invalid in_ key prefix, invalid URL, metadata exceeds 10 keys, or ffmpeg_command/output_files included on this download-only endpoint.
429RATE_LIMITEDToo many requests. Retry after the period indicated in the Retry-After header.
501NOT_IMPLEMENTEDyt-dlp backend unavailable. Retry after a short delay.

Examples

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"
    },
    "format_selector": "720p",
    "metadata": {
      "source": "youtube",
      "project": "archive"
    }
  }'
import os, time, requests

API_KEY = os.environ["RENDERIO_API_KEY"]
BASE = "https://renderio.dev"

# Submit download
res = requests.post(
    f"{BASE}/api/v1/ytdlp-download",
    headers={"X-API-KEY": API_KEY, "Content-Type": "application/json"},
    json={
        "input_urls": {"in_video": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"},
        "metadata": {"source": "youtube"},
    },
)
res.raise_for_status()
command_id = res.json()["command_id"]

# Poll until done
while True:
    time.sleep(2)
    result = requests.get(
        f"{BASE}/api/v1/commands/{command_id}",
        headers={"X-API-KEY": API_KEY},
    ).json()
    if result["status"] == "SUCCESS":
        # input key in_video → output key out_video
        print(result["output_files"]["out_video"]["storage_url"])
        break
    if result["status"] == "FAILED":
        raise RuntimeError(result.get("error"))
const API_KEY = process.env.RENDERIO_API_KEY!;
const BASE = "https://renderio.dev";

interface CommandResult {
  command_id: string;
  status: "QUEUED" | "PROCESSING" | "SUCCESS" | "FAILED";
  output_files: Record<string, { storage_url: string | null; status: string }>;
  error?: string;
}

async function downloadVideo(url: string): Promise<string> {
  const submitRes = await fetch(`${BASE}/api/v1/ytdlp-download`, {
    method: "POST",
    headers: { "X-API-KEY": API_KEY, "Content-Type": "application/json" },
    body: JSON.stringify({ input_urls: { in_video: url } }),
  });

  if (!submitRes.ok) throw new Error(`Submit failed: ${await submitRes.text()}`);
  const { command_id } = await submitRes.json();

  while (true) {
    await new Promise((r) => setTimeout(r, 2000));
    const pollRes = await fetch(`${BASE}/api/v1/commands/${command_id}`, {
      headers: { "X-API-KEY": API_KEY },
    });
    const result: CommandResult = await pollRes.json();
    // input key in_video → output key out_video
    if (result.status === "SUCCESS") return result.output_files.out_video.storage_url!;
    if (result.status === "FAILED") throw new Error(result.error);
  }
}

const storageUrl = await downloadVideo("https://www.youtube.com/watch?v=dQw4w9WgXcQ");
console.log("Downloaded:", storageUrl);
const API_KEY = process.env.RENDERIO_API_KEY;
const BASE = "https://renderio.dev";

async function downloadVideo(url) {
  const submitRes = await fetch(`${BASE}/api/v1/ytdlp-download`, {
    method: "POST",
    headers: { "X-API-KEY": API_KEY, "Content-Type": "application/json" },
    body: JSON.stringify({ input_urls: { in_video: url } }),
  });

  const { command_id } = await submitRes.json();

  while (true) {
    await new Promise((r) => setTimeout(r, 2000));
    const result = await fetch(`${BASE}/api/v1/commands/${command_id}`, {
      headers: { "X-API-KEY": API_KEY },
    }).then((r) => r.json());

    // input key in_video → output key out_video
    if (result.status === "SUCCESS") return result.output_files.out_video.storage_url;
    if (result.status === "FAILED") throw new Error(result.error);
  }
}

const url = await downloadVideo("https://www.tiktok.com/@username/video/7123456789");
console.log("Downloaded:", url);

Supported platforms

RenderIO uses yt-dlp, which supports thousands of extractors including YouTube, TikTok, Instagram, X/Twitter, Reddit, Vimeo, Twitch, Facebook, and more. See the yt-dlp supported sites list for the current catalog.

Platforms update their APIs frequently, and the yt-dlp project notes that listed sites are not guaranteed to work forever because websites change. RenderIO patches yt-dlp server-side, so your endpoint and code remain stable when extractor fixes ship.

On this page