# Universal Video Downloader and Converter (`hgservices/video-downloader-converter`) Actor

Download videos from 1000s of sites or your own URLs, then convert, compress, trim, resize, extract audio (MP3/M4A), grab thumbnails, or make GIFs — all in one run. Fast, reliable media processing with flexible output. Perfect for content creators, archivers, and automation workflows.

- **URL**: https://apify.com/hgservices/video-downloader-converter.md
- **Developed by:** [Harish Garg](https://apify.com/hgservices) (community)
- **Categories:** Videos, AI, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-usage

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

### What does Universal Video Downloader and Converter do?

**Universal Video Downloader and Converter** downloads videos from **YouTube, TikTok, Vimeo, X/Twitter, Facebook, Instagram, SoundCloud, podcast feeds, and 1000+ other sites** — or from any **direct media file URL** you already have — and then, in the **same run**, can convert the format, compress, trim, resize, extract audio (MP3/M4A and more), grab a thumbnail, or turn a segment into a GIF. Give it a **list of URLs** and it processes them all with the settings you choose, saving every output file to storage with a direct download link.

It's built on **FFmpeg** for fast, reliable media processing and **yt-dlp** for broad site coverage. Powered by the Apify platform, you get API access, scheduling, webhook integrations, proxy rotation, and data export — all without managing any infrastructure.

> **YouTube and TikTok are downloaded through dedicated downloaders.** Their anti-bot and login walls make direct extraction unreliable, so YouTube links go through the maintained [streamers/youtube-video-downloader](https://apify.com/streamers/youtube-video-downloader) Actor and TikTok through [clockworks/tiktok-scraper](https://apify.com/clockworks/tiktok-scraper), with a built-in fallback to in-process yt-dlp. This affects pricing for those two sources — see [Pricing](#pricing--cost-estimation).

### Why use Universal Video Downloader and Converter?

- **One tool, whole pipeline** — Download and convert/compress/trim/resize/clip in a single run instead of stitching together separate tools.
- **Bulk downloading** — Hand it a list of URLs and collect every file from one dataset.
- **Content repurposing** — Pull a clip, make a GIF for social, or extract the audio for a podcast feed.
- **Archiving** — Save public videos in a consistent format (e.g. everything as MP4 720p) for long-term storage.
- **Automation workflows** — Call it from the API, run it on a schedule, or chain it after your own scraper via webhooks and feed it the media URLs it produced.
- **Storage savings** — Compress or downscale on the way in so you only keep what you need.

### Supported sources at a glance

| Source | How to pass it | Notes |
|--------|----------------|-------|
| **YouTube** | Watch/Shorts URL | Downloading is delegated to a maintained downloader for reliability; the per-MB download fee is waived (see [Pricing](#pricing--cost-estimation)). |
| **TikTok** | Video URL | Delegated downloader returns the no-watermark video, plus full metadata (title, author, views). |
| **Vimeo, X/Twitter, SoundCloud, Dailymotion, Reddit, podcast RSS, + 1000+ yt-dlp sites** | Public page/episode URL | Must be public — login/age-walled posts can't be fetched anonymously. |
| **Facebook / Instagram** | The **page** URL (`facebook.com` / `instagram.com`) | Prefer the post page URL so the Actor resolves a fresh stream. A raw `fbcdn.net` / `cdninstagram.com` link works only if it's a progressive `.mp4` and hasn't expired. |
| **Skool lessons** | The lesson page URL (`skool.com/...?md=...`) | Resolves embedded Loom/YouTube/Vimeo players and self-hosted Mux videos. |
| **Your own hosted files** (S3, Google Drive, Dropbox, your CDN, Apify Key-Value Store) | Direct public file link | `mp4`, `mkv`, `webm`, `mov`, `mp3`, `m4a`, `wav`, `flac`, … — downloaded as-is, then processed. |

**Rule of thumb:** paste a **web page URL** for a platform, or a **direct file link** for your own media. You can mix both in one `startUrls` list.

### How to download and convert videos

1. **Open the Actor** and click **Try for free**.
2. **Add your URLs** to **Source URLs** — one per line, page URLs or direct file links, in any mix.
3. **Pick what you want** (all optional): a download quality, an output format (or keep the original), and any transforms — resize, compress, trim, extract audio, thumbnail, or GIF.
4. **Run the Actor** and wait for it to finish.
5. **Download your files** from the **Storage → Key-value store** tab, or get direct links and metadata from the **Dataset (Output)** tab.

No external API keys required.

#### Run it via API or on a schedule

Most production usage drives this Actor through the **Apify API**. Start a run with a single POST:

```bash
curl -X POST "https://api.apify.com/v2/acts/hgservices~video-downloader-converter/runs?token=<APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
        "startUrls": [{ "url": "https://www.youtube.com/watch?v=aqz-KE-bpKQ" }],
        "format": "mp4",
        "videoQuality": "720p"
      }'
````

Or with the Apify client (the Actor slug is `hgservices/video-downloader-converter`):

```python
run = client.actor("hgservices/video-downloader-converter").call(run_input={
    "startUrls": [{"url": "https://www.youtube.com/watch?v=aqz-KE-bpKQ"}],
    "format": "mp4",
    "extractAudio": True,
    "audioFormat": "mp3",
})
```

To run it unattended, point a [Schedule](https://docs.apify.com/platform/schedules) at it, or fire it from your own scraper's success event with [webhooks](https://docs.apify.com/platform/integrations/webhooks) and feed the scraped media URLs into `startUrls`.

### Input

The only required input is **`startUrls`**. Everything else is optional and applies to every URL in the run.

| Field | Type | Description |
|-------|------|-------------|
| `startUrls` | array | URLs to download — platform page URLs or direct media file links (any mix) |
| `videoQuality` | enum | Max download resolution for platforms: `best` (default), `2160p`, `1440p`, `1080p`, `720p`, `480p`, `360p` |
| `format` | enum | Output container: `original` (default, no re-encode), `mp4`, `mkv`, `webm`, `mov`, `avi` |
| `resize` | enum | Re-encode down to a height: `none` (default), `1440p`, `1080p`, `720p`, `480p`, `360p`, `240p` |
| `compress` | enum | Re-encode smaller: `none` (default), `low`, `medium`, `high` |
| `trimStart` / `trimEnd` | string | Keep only this segment (seconds or `HH:MM:SS`); applies to video + extracted audio |
| `extractAudio` | boolean | Also save an audio-only file (default `false`) |
| `audioFormat` | enum | `mp3` (default), `m4a`, `aac`, `opus`, `ogg`, `wav`, `flac` |
| `thumbnail` | boolean | Also save a still frame as JPEG (default `false`) |
| `thumbnailTime` | string | When to grab it (seconds or `HH:MM:SS`); empty = middle of the video |
| `gif` | boolean | Also create a looping GIF (default `false`) |
| `gifStart` / `gifDuration` / `gifFps` / `gifWidth` | string/int | GIF segment start, length (s), frame rate, and width |
| `maxDurationMinutes` | integer | Skip sources longer than this, before download (default `180`; `0` = no limit) |
| `maxFileSizeMb` | integer | Cap on a single direct-file download (default `2048`) |
| `proxyConfiguration` | object | Optional Apify Proxy (off by default) |

`format: "original"` is the fastest and is lossless — use it when you just want the file. Any of `format` (other than original), `resize`, `compress`, or `trim` causes a re-encode of the video.

### Output

Every produced file is stored in the run's **key-value store** with a direct download URL, and a summary row is pushed to the **dataset** (the **Output** tab) for each source URL:

```json
{
    "url": "https://www.youtube.com/watch?v=aqz-KE-bpKQ",
    "sourceType": "platform",
    "platform": "youtube",
    "videoId": "aqz-KE-bpKQ",
    "title": "Big Buck Bunny",
    "channel": "Blender",
    "uploadDate": "2008-05-20",
    "viewCount": 12345678,
    "sourceThumbnailUrl": "https://i.ytimg.com/vi/aqz-KE-bpKQ/maxresdefault.jpg",
    "durationSeconds": 635.0,
    "width": 1280,
    "height": 720,
    "videoFormat": "mp4",
    "isAudioOnly": false,
    "downloadDelegated": true,
    "status": "ok",
    "videoFileUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/01-big-buck-bunny-video.mp4",
    "audioFileUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/01-big-buck-bunny-audio.mp3",
    "thumbnailFileUrl": null,
    "gifFileUrl": null,
    "outputs": [
        { "type": "video", "key": "01-big-buck-bunny-video.mp4", "format": "mp4", "sizeBytes": 41231234, "url": "https://api.apify.com/v2/..." },
        { "type": "audio", "key": "01-big-buck-bunny-audio.mp3", "format": "mp3", "sizeBytes": 10231234, "url": "https://api.apify.com/v2/..." }
    ]
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel, and the media files individually from the key-value store.

#### Output data fields

| Field | Type | Description |
|-------|------|-------------|
| `url` | string | The source URL you submitted |
| `sourceType` | string | `"platform"` (yt-dlp/delegated) or `"directUrl"` |
| `platform` | string | Coarse platform bucket (`youtube`, `tiktok`, `vimeo`, …) |
| `videoId`, `title`, `channel`, `channelUrl`, `uploadDate`, `viewCount` | mixed | Source metadata (null for direct file URLs) |
| `sourceThumbnailUrl` | string | The platform's own thumbnail image (null for direct file URLs) |
| `durationSeconds` | number | Source duration |
| `width`, `height`, `fps` | number | Dimensions of the saved video output |
| `videoFormat` | string | Container of the saved video |
| `isAudioOnly` | boolean | True when the source had no video stream (saved as audio) |
| `downloadDelegated` | boolean | True when a YouTube/TikTok downloader Actor was used |
| `status` | string | `"ok"` or a failure category (see Troubleshooting) |
| `statusMessage` | string | Human-readable note when something needs attention |
| `videoFileUrl`, `audioFileUrl`, `thumbnailFileUrl`, `gifFileUrl` | string | Direct download links to each produced file |
| `outputs` | array | All produced files with key, format, and size in bytes |

### Use it as a download/convert step in your pipeline

Already scraping pages with your own Actor or tool? You don't need this one to *find* the media — hand it the **direct media URLs** in `startUrls` and it becomes the download-and-convert stage at the end of your pipeline. Wire it up code-free with Apify [task chaining / webhooks](https://docs.apify.com/platform/integrations/webhooks): fire it on your scraper's `SUCCEEDED` event and map the scraped URLs into `startUrls`.

**Operational note for signed CDN links** (Facebook, Instagram, X): these expire within hours and are often IP-bound, so download promptly and prefer the original page URL when you can. Pass a freshly minted, broadly fetchable link.

### Pricing / cost estimation

This Actor uses **pay-per-event** pricing — you pay only for what it produces, with no separate compute units or proxy bandwidth to track. Charges scale with how much work each source actually takes: the download is billed by size, and processing is billed by the length of the output it creates.

| Event | Price (USD) | When charged |
|-------|-------------|--------------|
| **Video downloaded** | $0.0005 / MB | Per megabyte of source media downloaded, rounded up (min 1 MB). **Waived for YouTube and TikTok** (see below) |
| **Video processed** | $0.004 / min | Per minute of the produced video, rounded up (min 1 min), when it's re-encoded. Format conversion, compression, resizing, and trimming are done in one pass and billed once |
| **Audio extracted** | $0.001 / min | Per minute of extracted audio, rounded up (min 1 min) |
| **Thumbnail captured** | $0.005 | Once per thumbnail image grabbed |
| **GIF created** | $0.01 | Once per animated GIF produced |

A **plain download in its original format** costs only the per-MB download — there's no processing charge unless you ask for a transform. Combining several video transforms (e.g. resize + compress) is a single re-encode and bills once under **Video processed**; extra outputs like audio, thumbnails, and GIFs each add their own charge on top.

**Example costs:**

| What you do | Approx. cost |
|-------------|-------------:|
| Download a 50 MB clip, original format | $0.025 |
| Download 50 MB + convert/compress a 5-min video | $0.025 + $0.020 = $0.045 |
| Download 50 MB + compress + resize a 5-min video (one pass) | $0.025 + $0.020 = $0.045 |
| 5-min video: process + extract 5-min MP3 + thumbnail | $0.020 + $0.005 + $0.005 = $0.030 (+ download) |
| 5-min video: process + MP3 + thumbnail + GIF | $0.020 + $0.005 + $0.005 + $0.010 = $0.040 (+ download) |

**YouTube and TikTok sources:** the per-MB download fee is **waived**, but the dedicated downloader Actor ([streamers/youtube-video-downloader](https://apify.com/streamers/youtube-video-downloader) / [clockworks/tiktok-scraper](https://apify.com/clockworks/tiktok-scraper)) **bills your Apify account directly** at its own small rate. Any FFmpeg processing you request on top is still billed at the rates above.

The `maxDurationMinutes` cap (default 180) skips overly long sources **before** download so a marathon livestream can't run up a surprise bill. **New Apify accounts** include free monthly platform credits to try it out.

### Tips and advanced options

- **Just want the file? Leave `format` as `original`.** It's the fastest path (no re-encode) and cheapest (no processing event).
- **Smaller downloads:** set `videoQuality` to `720p` or lower for platform sources — it downloads a smaller stream directly, no re-encode needed.
- **`resize` vs `videoQuality`:** `videoQuality` picks a smaller source stream (cheap, platforms only); `resize` re-encodes to an exact height (works on any source, including your own files).
- **Clip + GIF in one go:** set `trimStart`/`trimEnd` for the video and audio, and `gifStart`/`gifDuration` independently for the GIF.
- **Large files:** outputs are buffered in memory before upload — raise the run's **Memory** if you're processing big 1080p/4K videos, and lower `maxFileSizeMb` to guard against runaway direct downloads.
- **Blocked source?** Enable `proxyConfiguration` with the `RESIDENTIAL` group and, if needed, a specific country for geo-restricted content.

### Troubleshooting: common statuses and what to do

Each source URL gets its own dataset row. A URL that couldn't be delivered still finishes as part of a **Succeeded** run — its row carries an empty file set, a `status` category, and a `statusMessage` explaining the cause and fix.

| Status / message | What it means | What to do |
|------------------|---------------|------------|
| **`bot_wall`** — "blocked this request as automated traffic" | YouTube's bot wall (in-process fallback). | Enable Apify proxy or retry later. |
| **`auth_wall`** — "requires a logged-in account" | Login/age wall (TikTok, Instagram, Facebook, Reddit). | Use publicly accessible content; the Actor downloads anonymously. |
| **`geo_blocked`** | Not available from the Actor's region. | Enable Apify proxy with a different country. |
| **`rate_limited`** (HTTP 429) | Too many requests to the platform. | Retry later or enable Apify proxy. |
| **`http_error` 403/404** (direct URL) | Link is wrong, expired, private, or IP-bound. | Re-fetch a fresh, public, direct file link and submit promptly. |
| **`not_media_file`** | The URL served an HTML page, not a file. | Point at the file itself, not a webpage. |
| **`invalid_media`** | The download was corrupt or truncated. | Retry with a fresh URL. |
| **`processing_failed`** | An FFmpeg step failed; the original download was delivered when possible. | Check the message; try a different format, or `original`. |
| **`over_cap`** | Source is longer than `maxDurationMinutes`. **No charge.** | Raise `maxDurationMinutes`. |
| **`no_media`** | The post has no video (e.g. a photo/carousel). | Submit a post that contains a video. |

**Still stuck?** Email the creator directly at **<harish@harishgarg.com>** — include the URL and the status message, and we'll help you sort it out.

### FAQ, disclaimers, and support

**Which sites are supported?** Any of the 1000+ sites [yt-dlp supports](https://github.com/yt-dlp/yt-dlp/blob/master/supported-sites.md), plus any direct public link to a media file.

**Can I download multiple videos at once?** Yes — put as many URLs in `startUrls` as you like. They're processed one after another, each with its own dataset row and files.

**Can I download private or unlisted content?** Only if you can provide a direct, publicly reachable file URL (e.g. an S3 presigned link). The Actor downloads anonymously and can't sign in to platforms.

**Why is the file WebM/MKV instead of MP4?** With `format: "original"` you get exactly what the source provides, which on YouTube is often VP9/WebM. Set `format: "mp4"` to convert.

**Is this Actor legal to use?** You are responsible for complying with the Terms of Service of any source platform and with applicable copyright law. Only download content you have the rights to, or that is available for your intended use.

For issues, feature requests, or feedback, use the **Issues** tab on this Actor's page. For custom solutions or enterprise needs, contact Apify support.

# Actor input Schema

## `startUrls` (type: `array`):

One or more URLs to download. Each can be a page on YouTube, Vimeo, TikTok, X/Twitter, Facebook, Instagram, SoundCloud, an RSS podcast episode, or any of the 1000+ sites yt-dlp supports — or a direct public link to a media file (mp4, mkv, webm, mov, mp3, m4a, …). Every URL is downloaded and processed with the same settings below.

## `videoQuality` (type: `string`):

Maximum video resolution to download from a platform (it picks the best stream at or below this). Use a lower value to download faster and smaller. Applies to platform pages; direct file URLs are downloaded as-is (use Resize to downscale those).

## `format` (type: `string`):

Container/format of the saved video. 'Original' keeps exactly what the source provides (no re-encoding — fastest and lossless). Any other value converts the file: it is remuxed losslessly when the codecs already fit the new container, otherwise re-encoded. Re-encoding to MP4/MOV/MKV uses H.264 + AAC, WebM uses VP9 + Opus.

## `resize` (type: `string`):

Re-encode the video down to this height (width is auto-scaled to keep the aspect ratio). Works on any source, including direct file URLs. Leave as 'No resize' to keep the original dimensions. Note: resizing forces a re-encode and counts as one processed output.

## `compress` (type: `string`):

Reduce file size by re-encoding at a higher compression level (H.264 CRF). Higher compression = smaller file, lower quality. Leave off to keep quality.

## `trimStart` (type: `string`):

Start time of the clip to keep, as seconds (e.g. 12) or HH:MM:SS (e.g. 00:01:30). Applies to the video and extracted-audio outputs. Leave empty to start at the beginning.

## `trimEnd` (type: `string`):

End time of the clip to keep, as seconds or HH:MM:SS. Must be greater than Trim start. Leave empty to run to the end.

## `extractAudio` (type: `boolean`):

Also save an audio-only file extracted from the video.

## `audioFormat` (type: `string`):

Format for the extracted audio (only used when 'Extract audio' is on).

## `thumbnail` (type: `boolean`):

Also save a single still frame from the video as a JPEG.

## `thumbnailTime` (type: `string`):

When to grab the thumbnail, as seconds or HH:MM:SS. Leave empty to use the middle of the video.

## `gif` (type: `boolean`):

Also create a looping GIF from a segment of the video.

## `gifStart` (type: `string`):

Start time of the GIF segment, as seconds or HH:MM:SS (only used when 'Make GIF' is on).

## `gifDuration` (type: `integer`):

Length of the GIF in seconds.

## `gifFps` (type: `integer`):

Frames per second for the GIF. Lower = smaller file.

## `gifWidth` (type: `integer`):

Width of the GIF in pixels; height is auto-scaled to keep the aspect ratio.

## `maxDurationMinutes` (type: `integer`):

Skip any source longer than this many minutes, before it is downloaded (no charge for skipped sources). Protects you from accidentally processing a marathon livestream. Set to 0 for no limit.

## `maxFileSizeMb` (type: `integer`):

Hard cap on the size of a single direct file URL download. Sources over this are rejected before/while streaming. Does not apply to platform downloads.

## `proxyConfiguration` (type: `object`):

Optional Apify Proxy. Off by default — most public media URLs and platforms download fine and faster without a proxy. Direct file URLs are always fetched directly first and only fall back to this proxy if the direct attempt fails. Enable it (e.g. the RESIDENTIAL group) only when a source is geo-restricted or blocks server IPs. YouTube and TikTok are handled by dedicated downloader Actors and ignore this setting.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.youtube.com/watch?v=aqz-KE-bpKQ"
    }
  ],
  "videoQuality": "best",
  "format": "original",
  "resize": "none",
  "compress": "none",
  "trimStart": "",
  "trimEnd": "",
  "extractAudio": false,
  "audioFormat": "mp3",
  "thumbnail": false,
  "thumbnailTime": "",
  "gif": false,
  "gifStart": "00:00:00",
  "gifDuration": 3,
  "gifFps": 12,
  "gifWidth": 480,
  "maxDurationMinutes": 180,
  "maxFileSizeMb": 2048,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `files` (type: `string`):

No description

## `dataset` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        {
            "url": "https://www.youtube.com/watch?v=aqz-KE-bpKQ"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("hgservices/video-downloader-converter").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "startUrls": [{ "url": "https://www.youtube.com/watch?v=aqz-KE-bpKQ" }],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("hgservices/video-downloader-converter").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://www.youtube.com/watch?v=aqz-KE-bpKQ"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call hgservices/video-downloader-converter --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=hgservices/video-downloader-converter",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Universal Video Downloader and Converter",
        "description": "Download videos from 1000s of sites or your own URLs, then convert, compress, trim, resize, extract audio (MP3/M4A), grab thumbnails, or make GIFs — all in one run. Fast, reliable media processing with flexible output. Perfect for content creators, archivers, and automation workflows.",
        "version": "1.0",
        "x-build-id": "gXCgRemqskOLNyZ55"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/hgservices~video-downloader-converter/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-hgservices-video-downloader-converter",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/hgservices~video-downloader-converter/runs": {
            "post": {
                "operationId": "runs-sync-hgservices-video-downloader-converter",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/hgservices~video-downloader-converter/run-sync": {
            "post": {
                "operationId": "run-sync-hgservices-video-downloader-converter",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "startUrls": {
                        "title": "Source URLs",
                        "type": "array",
                        "description": "One or more URLs to download. Each can be a page on YouTube, Vimeo, TikTok, X/Twitter, Facebook, Instagram, SoundCloud, an RSS podcast episode, or any of the 1000+ sites yt-dlp supports — or a direct public link to a media file (mp4, mkv, webm, mov, mp3, m4a, …). Every URL is downloaded and processed with the same settings below.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "videoQuality": {
                        "title": "Download quality",
                        "enum": [
                            "best",
                            "2160p",
                            "1440p",
                            "1080p",
                            "720p",
                            "480p",
                            "360p"
                        ],
                        "type": "string",
                        "description": "Maximum video resolution to download from a platform (it picks the best stream at or below this). Use a lower value to download faster and smaller. Applies to platform pages; direct file URLs are downloaded as-is (use Resize to downscale those).",
                        "default": "best"
                    },
                    "format": {
                        "title": "Output format",
                        "enum": [
                            "original",
                            "mp4",
                            "mkv",
                            "webm",
                            "mov",
                            "avi"
                        ],
                        "type": "string",
                        "description": "Container/format of the saved video. 'Original' keeps exactly what the source provides (no re-encoding — fastest and lossless). Any other value converts the file: it is remuxed losslessly when the codecs already fit the new container, otherwise re-encoded. Re-encoding to MP4/MOV/MKV uses H.264 + AAC, WebM uses VP9 + Opus.",
                        "default": "original"
                    },
                    "resize": {
                        "title": "Resize / scale",
                        "enum": [
                            "none",
                            "1440p",
                            "1080p",
                            "720p",
                            "480p",
                            "360p",
                            "240p"
                        ],
                        "type": "string",
                        "description": "Re-encode the video down to this height (width is auto-scaled to keep the aspect ratio). Works on any source, including direct file URLs. Leave as 'No resize' to keep the original dimensions. Note: resizing forces a re-encode and counts as one processed output.",
                        "default": "none"
                    },
                    "compress": {
                        "title": "Compress",
                        "enum": [
                            "none",
                            "low",
                            "medium",
                            "high"
                        ],
                        "type": "string",
                        "description": "Reduce file size by re-encoding at a higher compression level (H.264 CRF). Higher compression = smaller file, lower quality. Leave off to keep quality.",
                        "default": "none"
                    },
                    "trimStart": {
                        "title": "Trim start",
                        "type": "string",
                        "description": "Start time of the clip to keep, as seconds (e.g. 12) or HH:MM:SS (e.g. 00:01:30). Applies to the video and extracted-audio outputs. Leave empty to start at the beginning.",
                        "default": ""
                    },
                    "trimEnd": {
                        "title": "Trim end",
                        "type": "string",
                        "description": "End time of the clip to keep, as seconds or HH:MM:SS. Must be greater than Trim start. Leave empty to run to the end.",
                        "default": ""
                    },
                    "extractAudio": {
                        "title": "Extract audio",
                        "type": "boolean",
                        "description": "Also save an audio-only file extracted from the video.",
                        "default": false
                    },
                    "audioFormat": {
                        "title": "Audio format",
                        "enum": [
                            "mp3",
                            "m4a",
                            "aac",
                            "opus",
                            "ogg",
                            "wav",
                            "flac"
                        ],
                        "type": "string",
                        "description": "Format for the extracted audio (only used when 'Extract audio' is on).",
                        "default": "mp3"
                    },
                    "thumbnail": {
                        "title": "Grab thumbnail",
                        "type": "boolean",
                        "description": "Also save a single still frame from the video as a JPEG.",
                        "default": false
                    },
                    "thumbnailTime": {
                        "title": "Thumbnail timestamp",
                        "type": "string",
                        "description": "When to grab the thumbnail, as seconds or HH:MM:SS. Leave empty to use the middle of the video.",
                        "default": ""
                    },
                    "gif": {
                        "title": "Make GIF",
                        "type": "boolean",
                        "description": "Also create a looping GIF from a segment of the video.",
                        "default": false
                    },
                    "gifStart": {
                        "title": "GIF start",
                        "type": "string",
                        "description": "Start time of the GIF segment, as seconds or HH:MM:SS (only used when 'Make GIF' is on).",
                        "default": "00:00:00"
                    },
                    "gifDuration": {
                        "title": "GIF duration (seconds)",
                        "minimum": 1,
                        "maximum": 60,
                        "type": "integer",
                        "description": "Length of the GIF in seconds.",
                        "default": 3
                    },
                    "gifFps": {
                        "title": "GIF frame rate",
                        "minimum": 1,
                        "maximum": 30,
                        "type": "integer",
                        "description": "Frames per second for the GIF. Lower = smaller file.",
                        "default": 12
                    },
                    "gifWidth": {
                        "title": "GIF width (px)",
                        "minimum": 64,
                        "maximum": 1280,
                        "type": "integer",
                        "description": "Width of the GIF in pixels; height is auto-scaled to keep the aspect ratio.",
                        "default": 480
                    },
                    "maxDurationMinutes": {
                        "title": "Max source duration (minutes)",
                        "minimum": 0,
                        "maximum": 1440,
                        "type": "integer",
                        "description": "Skip any source longer than this many minutes, before it is downloaded (no charge for skipped sources). Protects you from accidentally processing a marathon livestream. Set to 0 for no limit.",
                        "default": 180
                    },
                    "maxFileSizeMb": {
                        "title": "Max direct-download size (MB)",
                        "minimum": 1,
                        "maximum": 6144,
                        "type": "integer",
                        "description": "Hard cap on the size of a single direct file URL download. Sources over this are rejected before/while streaming. Does not apply to platform downloads.",
                        "default": 2048
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Optional Apify Proxy. Off by default — most public media URLs and platforms download fine and faster without a proxy. Direct file URLs are always fetched directly first and only fall back to this proxy if the direct attempt fails. Enable it (e.g. the RESIDENTIAL group) only when a source is geo-restricted or blocks server IPs. YouTube and TikTok are handled by dedicated downloader Actors and ignore this setting.",
                        "default": {
                            "useApifyProxy": false
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
