> For the complete documentation index, see [llms.txt](https://developers.oxylabs.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.oxylabs.io/api-reference/dedicated-scrapers/media-scrapers.md).

# Media Scrapers

Reference for dedicated Web API media scraper endpoints, parameters and delivery modes for every endpoint.

<table><thead><tr><th width="110">Scraper</th><th>Endpoints</th></tr></thead><tbody><tr><td><a href="#general">General</a></td><td><code>/media</code></td></tr><tr><td><a href="#youtube">YouTube</a></td><td><code>/media/youtube/metadata</code>, <code>/media/youtube/subtitles</code>, <code>/media/youtube/download</code>, <code>/media/youtube/channel</code>, <code>/media/youtube/search</code>, <code>/media/youtube/search/max</code>, <code>/media/youtube/autocomplete</code>, <code>/media/youtube/video/trainability</code></td></tr></tbody></table>

{% hint style="info" %}
Videos that can't be downloaded fail with a media-specific error code (`11201`–`11304`). See [Media error codes](/api-reference/errors-and-status-codes.md#media-specific-errors).
{% endhint %}

{% hint style="info" %}
Storage URLs are validated for `s3`, `s3_gzip`, `s3_compatible`, and `tos`. An invalid value returns `400` before the request is created.
{% endhint %}

### General

#### `POST /v1/async/scrape/media`

Downloads a video from a URL (TikTok, BiliBili, etc.) and uploads it to your storage bucket. Max video length – `12` hours. Maximum download time – `1` hour.

**Modes:** `async`, `batch`

<table><thead><tr><th width="142">Name</th><th width="80.5">Type</th><th width="84.5">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>url</code></td><td>string</td><td>yes</td><td>Video URL.<br>TikTok: <code>tiktok.com/@{user}/video/{id}</code>, <code>tiktok.com/embed/{id}</code>, <code>vm.tiktok.com/{id}</code>, <code>vt.tiktok.com/{id}</code>.<br>BiliBili: <code>bilibili.com/video/{id}</code>, <code>bilibili.com/bangumi/play/{id}</code>.<br><code>http://</code>, <code>https://</code>, <code>www.</code> prefixes and query strings are accepted</td></tr><tr><td><code>storage</code></td><td>object</td><td>yes</td><td>Delivers the result to a storage bucket: <code>{"type": string, "url": string}</code>. <code>type</code> is <code>s3</code>, <code>s3_gzip</code>, <code>s3_compatible</code>, <code>gcs</code>, or <code>tos</code>. Async only. <code>url</code> is not validated</td></tr><tr><td><code>video_quality</code></td><td>string</td><td>no</td><td><code>best</code>, <code>worst</code>, or a resolution: <code>144</code>, <code>360</code>, <code>480</code>, <code>720</code>, <code>1080</code>, <code>1440</code>, <code>2160</code> (4K), <code>4320</code> (8K).<br>Default: TikTok – <code>720</code>, BiliBili – <code>480</code>.</td></tr><tr><td><code>callback_url</code></td><td>string</td><td>no</td><td>Webhook URL for the finished job. Malformed URLs are rejected with <code>400</code></td></tr></tbody></table>

### YouTube

#### **`POST /v1/scrape/media/youtube/metadata`**

Returns a video’s title, channel, description, duration, view, like and comment counts, upload date, categories, tags, chapters, thumbnails and available subtitle languages.

**Modes:** `sync`, `async`, `batch`

<table><thead><tr><th width="131">Name</th><th width="89">Type</th><th width="83">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>query</code></td><td>string</td><td>yes</td><td>Video ID, e.g. <code>tIgIF5lve8U</code>. Not a URL. In batch, an array of IDs</td></tr><tr><td><code>output</code></td><td>array of strings</td><td>no</td><td><code>["json"]</code> (default) returns the parsed metadata. <code>["json", "html"]</code> also returns the page source</td></tr><tr><td><code>callback_url</code></td><td>string</td><td>no</td><td>Async only. Webhook URL the finished job is posted to. Malformed URLs are rejected with <code>400</code></td></tr><tr><td><code>storage</code></td><td>object</td><td>no</td><td>Delivers the result to a bucket instead of the response: <code>{"type": string, "url": string}</code>. <code>type</code> is <code>s3</code>, <code>s3_gzip</code>, <code>s3_compatible</code>, <code>gcs</code>, or <code>tos</code>. Async only. <code>url</code> is not validated</td></tr></tbody></table>

A deleted, private or restricted video returns `state: "done"` with empty `results`. The reason is in `results[0].metadata.statuses.video_download`, e.g. `11202` (unavailable) or `11206` (age-restricted).

#### **`POST /v1/scrape/media/youtube/subtitles`**

Returns a video’s subtitle tracks with text and timings, grouped by origin and language.

**Modes:** `sync`, `async`, `batch`

<table><thead><tr><th width="155">Name</th><th width="84">Type</th><th width="82">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>query</code></td><td>string</td><td>yes</td><td>Video ID, e.g. <code>c4P_YuNnZ7U</code>. Not a URL. In batch, an array of IDs</td></tr><tr><td><code>language_code</code></td><td>string</td><td>no</td><td>Subtitle language, e.g. <code>en</code>. Lowercase; unknown codes are rejected with <code>400</code>. Omit to get all languages</td></tr><tr><td><code>subtitle_origin</code></td><td>string</td><td>no</td><td><code>uploader_provided</code> or <code>auto_generated</code>. Omit to get both</td></tr><tr><td><code>json</code></td><td>object</td><td>no</td><td>Custom extraction: <code>{"prompt": string}</code> or <code>{"schema": object}</code>, never both. Without it, the subtitle tracks are returned as YouTube serves them</td></tr><tr><td><code>callback_url</code></td><td>string</td><td>no</td><td>Async only. Webhook URL the finished job is posted to. Malformed URLs are rejected with <code>400</code></td></tr><tr><td><code>storage</code></td><td>object</td><td>no</td><td>Delivers the result to a bucket instead of the response: <code>{"type": string, "url": string}</code>. <code>type</code> is <code>s3</code>, <code>s3_gzip</code>, <code>s3_compatible</code>, <code>gcs</code>, or <code>tos</code>. Async only. <code>url</code> is not validated</td></tr></tbody></table>

A valid `language_code` with no matching track returns an empty result (`{}`), not an error.

#### **`POST /v1/async/scrape/media/youtube/download`**

Downloads a video, its audio, or a clip of either, to your cloud storage.

**Modes:** `sync`, `async`

<table><thead><tr><th width="150">Name</th><th width="87">Type</th><th width="83">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>query</code></td><td>string</td><td>yes</td><td>Video ID, e.g. <code>9cQBNYsCqQs</code>. Not a URL. In batch, an array of IDs</td></tr><tr><td><code>storage</code></td><td>object</td><td>yes</td><td><code>{"type": string, "url": string}</code>. <code>type</code> is <code>s3</code>, <code>gcs</code>, <code>s3_compatible</code> or <code>tos</code>. <code>url</code> is the bucket and folder, e.g. <code>bucket-name/folder/</code>; the API names the file</td></tr><tr><td><code>output</code></td><td>array of strings</td><td>no</td><td>One of <code>["audio_video"]</code> (default), <code>["audio"]</code> or <code>["video"]</code></td></tr><tr><td><code>video_quality</code></td><td>string</td><td>no</td><td><code>best</code>, <code>worst</code>, <code>144</code>, <code>360</code>, <code>480</code>, <code>720</code>, <code>1080</code>, <code>1440</code>, <code>2160</code> or <code>4320</code>. Default <code>720</code>; if 720p is not available, the best quality below it</td></tr><tr><td><code>audio_language</code></td><td>string</td><td>no</td><td><code>default</code> (default) or <code>original</code>, the video’s original audio track when it has dubs</td></tr><tr><td><code>start_at</code></td><td>string</td><td>no</td><td>Start of a clip, as <code>hh:mm:ss</code>, e.g. <code>00:01:30</code>. Omit to start from the beginning</td></tr><tr><td><code>end_at</code></td><td>string</td><td>no</td><td>End of a clip, as <code>hh:mm:ss</code>, e.g. <code>00:05:45</code>. Must be later than <code>start_at</code></td></tr><tr><td><code>callback_url</code></td><td>string</td><td>no</td><td>Webhook URL the finished job is posted to</td></tr></tbody></table>

The finished job returns the file name in `results[0].filename`. An age-restricted video returns `state: "done"` with no file and status `11206` in `results[0].metadata.statuses.video_download`.

#### **`POST /v1/scrape/media/youtube/channel`**

Returns a channel’s details (name, ID, subscriber, video and view counts, country, join date, links) and its latest videos.

**Modes:** `sync`, `async`

<table><thead><tr><th width="135">Name</th><th width="87">Type</th><th width="84">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>query</code></td><td>string</td><td>yes</td><td>Channel handle, e.g. <code>@Oxylabs</code> (the <code>@</code> is optional). Channel IDs (<code>UC…</code>) are not supported</td></tr><tr><td><code>limit</code></td><td>integer</td><td>no</td><td>Number of videos to return. Default <code>20</code>; <code>0</code> returns channel details only</td></tr><tr><td><code>output</code></td><td>array of strings</td><td>no</td><td><code>["json"]</code> returns the parsed channel data. <code>["html"]</code> (default) returns the page source. Use <code>json</code>: <code>["markdown"]</code> returns little more than the page footer</td></tr><tr><td><code>callback_url</code></td><td>string</td><td>no</td><td>Async only. Webhook URL the finished job is posted to. Malformed URLs are rejected with <code>400</code></td></tr><tr><td><code>storage</code></td><td>object</td><td>no</td><td>Delivers the result to a bucket instead of the response: <code>{"type": string, "url": string}</code>. <code>type</code> is <code>s3</code>, <code>s3_gzip</code>, <code>s3_compatible</code>, <code>gcs</code>, or <code>tos</code>. Async only. <code>url</code> is not validated</td></tr></tbody></table>

#### **`POST /v1/scrape/media/youtube/search`**

Returns up to 20 YouTube search results.

**Modes:** `sync`, `async`

<table><thead><tr><th width="168">Name</th><th width="96">Type</th><th width="87">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>query</code></td><td>string</td><td>yes</td><td>Search phrase</td></tr><tr><td><code>upload_date</code></td><td>string</td><td>no</td><td><code>last_hour</code>, <code>today</code>, <code>this_week</code>, <code>this_month</code> or <code>this_year</code></td></tr><tr><td><code>type</code></td><td>string</td><td>no</td><td><code>video</code>, <code>channel</code>, <code>playlist</code> or <code>movie</code></td></tr><tr><td><code>duration</code></td><td>string</td><td>no</td><td><code>&#x3C;4</code> (under 4 minutes), <code>4-20</code> (4 to 20 minutes) or <code>>20</code> (over 20 minutes)</td></tr><tr><td><code>sort_by</code></td><td>string</td><td>no</td><td><code>relevance</code> (default), <code>upload_date</code>, <code>view_count</code> or <code>rating</code></td></tr><tr><td><code>360</code></td><td>boolean</td><td>no</td><td>Only 360° videos</td></tr><tr><td><code>3d</code></td><td>boolean</td><td>no</td><td>Only 3D videos</td></tr><tr><td><code>4k</code></td><td>boolean</td><td>no</td><td>Only 4K videos</td></tr><tr><td><code>creative_commons</code></td><td>boolean</td><td>no</td><td>Only Creative Commons-licensed videos</td></tr><tr><td><code>hd</code></td><td>boolean</td><td>no</td><td>Only HD videos</td></tr><tr><td><code>hdr</code></td><td>boolean</td><td>no</td><td>Only HDR videos</td></tr><tr><td><code>live</code></td><td>boolean</td><td>no</td><td>Only live streams</td></tr><tr><td><code>location_tag</code></td><td>boolean</td><td>no</td><td>Only videos that carry a location tag. Returns an empty list when none match</td></tr><tr><td><code>purchased</code></td><td>boolean</td><td>no</td><td>Only purchased content</td></tr><tr><td><code>subtitles</code></td><td>boolean</td><td>no</td><td>Only videos with subtitles or closed captions</td></tr><tr><td><code>vr180</code></td><td>boolean</td><td>no</td><td>Only VR180 videos</td></tr><tr><td><code>location</code></td><td>string</td><td>no</td><td>Country to get results for, as a two-letter ISO code, e.g. <code>IN</code></td></tr><tr><td><code>callback_url</code></td><td>string</td><td>no</td><td>Async only. Webhook URL the finished job is posted to. Malformed URLs are rejected with <code>400</code></td></tr><tr><td><code>storage</code></td><td>object</td><td>no</td><td>Delivers the result to a bucket instead of the response: <code>{"type": string, "url": string}</code>. <code>type</code> is <code>s3</code>, <code>s3_gzip</code>, <code>s3_compatible</code>, <code>gcs</code>, or <code>tos</code>. Async only. <code>url</code> is not validated</td></tr></tbody></table>

#### **`POST /v1/scrape/media/youtube/search/max`**

Returns up to 700 search results for the same parameters as `/search`, at higher cost and latency.

**Modes:** `sync`, `async`

<table><thead><tr><th width="166">Name</th><th width="96">Type</th><th width="90">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>query</code></td><td>string</td><td>yes</td><td>Search phrase</td></tr><tr><td><code>upload_date</code></td><td>string</td><td>no</td><td><code>last_hour</code>, <code>today</code>, <code>this_week</code>, <code>this_month</code> or <code>this_year</code></td></tr><tr><td><code>type</code></td><td>string</td><td>no</td><td><code>video</code>, <code>channel</code>, <code>playlist</code> or <code>movie</code></td></tr><tr><td><code>duration</code></td><td>string</td><td>no</td><td><code>&#x3C;4</code> (under 4 minutes), <code>4-20</code> (4 to 20 minutes) or <code>>20</code> (over 20 minutes)</td></tr><tr><td><code>sort_by</code></td><td>string</td><td>no</td><td><code>relevance</code> (default), <code>upload_date</code>, <code>view_count</code> or <code>rating</code></td></tr><tr><td><code>360</code></td><td>boolean</td><td>no</td><td>Only 360° videos</td></tr><tr><td><code>3d</code></td><td>boolean</td><td>no</td><td>Only 3D videos</td></tr><tr><td><code>4k</code></td><td>boolean</td><td>no</td><td>Only 4K videos</td></tr><tr><td><code>creative_commons</code></td><td>boolean</td><td>no</td><td>Only Creative Commons-licensed videos</td></tr><tr><td><code>hd</code></td><td>boolean</td><td>no</td><td>Only HD videos</td></tr><tr><td><code>hdr</code></td><td>boolean</td><td>no</td><td>Only HDR videos</td></tr><tr><td><code>live</code></td><td>boolean</td><td>no</td><td>Only live streams</td></tr><tr><td><code>location_tag</code></td><td>boolean</td><td>no</td><td>Only videos that carry a location tag. Returns an empty list when none match</td></tr><tr><td><code>purchased</code></td><td>boolean</td><td>no</td><td>Only purchased content</td></tr><tr><td><code>subtitles</code></td><td>boolean</td><td>no</td><td>Only videos with subtitles or closed captions</td></tr><tr><td><code>vr180</code></td><td>boolean</td><td>no</td><td>Only VR180 videos</td></tr><tr><td><code>location</code></td><td>string</td><td>no</td><td>Country to get results for, as a two-letter ISO code, e.g. <code>IN</code></td></tr><tr><td><code>callback_url</code></td><td>string</td><td>no</td><td>Async only. Webhook URL the finished job is posted to. Malformed URLs are rejected with <code>400</code></td></tr><tr><td><code>storage</code></td><td>object</td><td>no</td><td>Delivers the result to a bucket instead of the response: <code>{"type": string, "url": string}</code>. <code>type</code> is <code>s3</code>, <code>s3_gzip</code>, <code>s3_compatible</code>, <code>gcs</code>, or <code>tos</code>. Async only. <code>url</code> is not validated</td></tr></tbody></table>

#### **`POST /v1/scrape/media/youtube/autocomplete`**

Returns YouTube’s search suggestions for a partial phrase.

**Modes:** `sync`, `async`

<table><thead><tr><th width="135">Name</th><th width="84">Type</th><th width="89">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>query</code></td><td>string</td><td>yes</td><td>Partial phrase to complete, e.g. <code>how to make</code></td></tr><tr><td><code>location_tag</code></td><td>string</td><td>no</td><td>Country the suggestions are for, as a lowercase two-letter code, e.g. <code>de</code></td></tr><tr><td><code>language</code></td><td>string</td><td>no</td><td>Suggestion language, e.g. <code>en</code></td></tr><tr><td><code>callback_url</code></td><td>string</td><td>no</td><td>Async only. Webhook URL the finished job is posted to. Malformed URLs are rejected with <code>400</code></td></tr><tr><td><code>storage</code></td><td>object</td><td>no</td><td>Delivers the result to a bucket instead of the response: <code>{"type": string, "url": string}</code>. <code>type</code> is <code>s3</code>, <code>s3_gzip</code>, <code>s3_compatible</code>, <code>gcs</code>, or <code>tos</code>. Async only. <code>url</code> is not validated</td></tr></tbody></table>

#### **`POST /v1/scrape/media/youtube/video/trainability`**

Returns a video’s declared AI-training permission: `permitted` is `["all"]`, `["None"]`, or a list of the parties allowed to train on it.

**Modes:** `sync`, `async`

<table><thead><tr><th width="135">Name</th><th width="75">Type</th><th width="85">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>query</code></td><td>string</td><td>yes</td><td>Video ID, e.g. <code>rFNDylrjn_w</code>. Not a URL</td></tr><tr><td><code>callback_url</code></td><td>string</td><td>no</td><td>Async only. Webhook URL the finished job is posted to. Malformed URLs are rejected with <code>400</code></td></tr><tr><td><code>storage</code></td><td>object</td><td>no</td><td>Delivers the result to a bucket instead of the response: <code>{"type": string, "url": string}</code>. <code>type</code> is <code>s3</code>, <code>s3_gzip</code>, <code>s3_compatible</code>, <code>gcs</code>, or <code>tos</code>. Async only. <code>url</code> is not validated</td></tr></tbody></table>

The signal is declared by the rights holder. It is not a legal clearance.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://developers.oxylabs.io/api-reference/dedicated-scrapers/media-scrapers.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
