---
title: "YouTube Downloader API — 4K Video, Audio & Search | FastSaverAPI"
url: https://fastsaverapi.com/youtube-downloader-api/
description: "Four YouTube endpoints, one API key: enumerate every format with its file size, then pull 144p to 2160p 4K or search YouTube Music. Credits, limits, Python."
updated: 2026-08-10
api_base: https://api.fastsaver.io/v1
site_index: https://fastsaverapi.com/llms.txt
openapi: https://fastsaverapi.com/openapi.json
---

# YouTube downloader API — from format lookup to a 4K file

Four endpoints make up the YouTube downloader API: read a video's formats and file sizes,
download anything from 144p to 2160p (4K), take the audio track on its own, or search YouTube
Music. Check the info call before you spend credits on a download.

- **Endpoints**: four — info , search , download , audio/tg-bot

- **Credits**: 2 info · 2 search · 15 download · 25 at 2K/4K · tg-bot audio 7 cached, 15 on a miss

- **Formats**: audio, 144p → 2160p (4K)

- **Auth**: X-Api-Key header

## four endpoints, and what each one is for

YouTube does not go through the universal /fetch endpoint. The work is different:
formats have to be enumerated, streams muxed, and the result is a file we produce rather than a
link we forward.

| Endpoint | Method | Credits | Use it when |
| --- | --- | --- | --- |
| /youtube/info | GET | 2 | Title, author, duration, thumbnails and every available format with its file size. |
| /youtube/search | GET | 2 | Tracks from YouTube Music — 10 per page, pages 1 to 3. |
| /youtube/download | POST | 15 · 25 | The file itself, at a resolution you choose, or the audio alone. |
| /youtube/audio/tg-bot | POST | 7 · 15 | A Telegram file_id instead of bytes. |

All four take the same X-Api-Key header. The GETs put parameters in the query
string; the POSTs take a JSON body.

/youtube/audio/tg-bot is the one row with two prices, and the difference is worth
budgeting for. If we already hold that video_id , you pay 7 credits and get a
file_id back almost immediately. If we do not, the request falls through to a real
download and bills the full 15 — the same as /youtube/download with
format: "audio" . A cold catalogue costs 15 a track; it is the second and later
requests for the same track that cost 7.

## check the formats before you spend fifteen credits

The correct order is info, then download. /youtube/info costs 2 credits and answers
two things up front: which resolutions this video actually has, and how big each one is. A
download that succeeds and hands you a four-gigabyte file nobody asked for still bills 15 — seven
and a half times the lookup that would have talked you out of it.

GET
https://api.fastsaver.io/v1/youtube/info
2 credits



```
curl -G "https://api.fastsaver.io/v1/youtube/info" \
  --data-urlencode "url=https://www.youtube.com/watch?v=HanBb8FonWs" \
  -H "X-Api-Key: fs_sk_•••••••••••"
```



```
{
  "ok": true,
  "video_id": "HanBb8FonWs",
  "title": "Snails - Frogbass",
  "author": "DubstepGutter",
  "author_url": "https://www.youtube.com/channel/UCG6QEHCBfWZOnv7UVxappyw",
  "thumbnail": "https://i.ytimg.com/vi/HanBb8FonWs/sddefault.jpg",
  "duration": 234,
  "thumbnails": {
    "low": "https://i.ytimg.com/vi/HanBb8FonWs/mqdefault.jpg",
    "max": "https://i.ytimg.com/vi/HanBb8FonWs/maxresdefault.jpg"
  },
  "formats": [
    { "type": "video", "format": "144p", "filesize": 6967209 },
    { "type": "video", "format": "360p", "filesize": 21096358 },
    { "type": "video", "format": "720p", "filesize": 60448393 }
  ]
}
```


The -G and --data-urlencode matter. A watch URL carries its own
?v= , so pasting it raw into the query string splits it: the server reads
url=https://www.youtube.com/watch plus a stray v parameter, finds no
video id and errors. In code, let your HTTP client encode it — params= in requests,
encodeURIComponent in JavaScript. A youtu.be/ID link has no query string
and needs none of this.

filesize is in bytes. Render your quality picker from this array — a 4K button on a
video that tops out at 720p is a support ticket.

Then ask for the file.

POST
https://api.fastsaver.io/v1/youtube/download
15 credits · 25 at 2K/4K



```
curl -X POST "https://api.fastsaver.io/v1/youtube/download" \
  -H "X-Api-Key: fs_sk_•••••••••••" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.youtube.com/watch?v=HanBb8FonWs", "format": "1080p"}'
```



```
{
  "ok": true,
  "video_id": "HanBb8FonWs",
  "duration": 234,
  "filename": "Snails - Frogbass (1080p, av1, youtube).mp4",
  "download_url": "https://api.fastsaver.io/v1/tunnel?id=3f7a1c9e-52b4-4d18-9f0a-6c2b7e51d8aa",
  "thumbnails": {
    "low": "https://i.ytimg.com/vi/HanBb8FonWs/mqdefault.jpg",
    "max": "https://i.ytimg.com/vi/HanBb8FonWs/maxresdefault.jpg"
  }
}
```


Two fields deserve a closer look.

- filename arrives as title (format, codec, source).mp4 ,
so av1 in the name is the codec you actually got. Fine for a
Content-Disposition header; sanitise it before it touches a filesystem, because it
carries whatever the uploader typed.
- download_url is https://api.fastsaver.io/v1/tunnel?id=… — the same
api.fastsaver.io host you just called, on the /v1/tunnel path, not a
YouTube CDN link. The file is muxed on our side, so there is no signed googlevideo URL to hand
you. The tunnel answers with a redirect to the file, so your client has to follow redirects
( curl -L ). Stream it straight through to storage or to your user.

## formats and what they cost

format is required and takes exactly one of these values. There is no "best" or
"auto" — you pick, which means you control the bill.

| format | What you get | Credits |
| --- | --- | --- |
| audio | Audio track only, no video stream. | 15 |
| 144p | Smallest file. Previews. | 15 |
| 240p | Low bandwidth. | 15 |
| 360p | Watchable on a phone. | 15 |
| 480p | SD. | 15 |
| 720p | HD. Sensible default. | 15 |
| 1080p | Full HD. | 15 |
| 1440p | 2K. | 25 |
| 2160p | 4K. | 25 |

Only 2K and 4K break the flat rate, and not for the sake of tiering. A 4K download moves several
times the data of a 1080p one and holds a worker longer while it does. We pass that through
instead of averaging it into every request, so 720p users are not subsidising 4K users.

## search youtube music, then deliver

/youtube/search queries music.youtube.com, not the main site, so results skew to
tracks rather than reaction videos and hour-long mixes. Ten per page; page is
required and accepts 1, 2 or 3. Thirty results is the ceiling.

GET
https://api.fastsaver.io/v1/youtube/search
2 credits · 10 results



```
curl "https://api.fastsaver.io/v1/youtube/search?query=the%20weeknd&page=1" \
  -H "X-Api-Key: fs_sk_•••••••••••"
```



```
{
  "ok": true,
  "page": 1,
  "results": [
    {
      "video_id": "HgLfYfJtc8M",
      "title": "The Weeknd - One Of The Girls",
      "duration": "4:05",
      "thumbnail": "https://i.ytimg.com/vi/HgLfYfJtc8M/mqdefault.jpg",
      "thumbnail_max": "https://i.ytimg.com/vi/HgLfYfJtc8M/maxresdefault.jpg"
    }
  ]
}
```


duration here is a display string like "4:05" , not the integer seconds
that /youtube/info and /youtube/download return. Parse accordingly.

video_id is the join key: build a watch URL from it for
/youtube/download , or hand it to the
Telegram bot media API , which documents
file_id delivery in full.

## the whole flow in one function

Pick the highest resolution the video offers that fits a size budget, then download it. Two
calls, one key, nothing to install on your side.



```
import requests

BASE = "https://api.fastsaver.io/v1"
HEADERS = {"X-Api-Key": "fs_sk_•••••••••••"}
LADDER = ["2160p", "1440p", "1080p", "720p", "480p", "360p"]

def best_format(url, max_bytes=250_000_000):
    info = requests.get(f"{BASE}/youtube/info", params={"url": url},
                        headers=HEADERS, timeout=60).json()
    sizes = {f["format"]: f["filesize"] for f in info.get("formats", [])}
    for quality in LADDER:
        if quality in sizes and sizes[quality] <= max_bytes:
            return quality
    return "360p"

def download(url):
    quality = best_format(url)
    job = requests.post(f"{BASE}/youtube/download", headers=HEADERS,
                        json={"url": url, "format": quality}, timeout=300).json()
    if not job.get("ok"):
        raise RuntimeError(job.get("detail", "download failed"))
    with requests.get(job["download_url"], stream=True, timeout=300) as r:
        r.raise_for_status()
        with open(job["filename"], "wb") as fh:
            for chunk in r.iter_content(1 << 20):
                fh.write(chunk)
    return job["filename"]

print(download("https://www.youtube.com/watch?v=HanBb8FonWs"))
```

Note the timeouts. A 4K mux is not a 200 ms JSON call; a default five-second client timeout will
abandon a request that was going to succeed. Stream the body rather than buffering gigabytes.

From a shell, the same lookup is one pipe:



```
API="https://api.fastsaver.io/v1"
curl -s "$API/youtube/info?url=https://youtu.be/HanBb8FonWs" \
  -H "X-Api-Key: $FS_KEY" | jq '.formats[] | select(.format == "1080p")'
```


## where the YouTube endpoints stop

- Public videos only. If a signed-out browser cannot play it, the API cannot resolve it. Gated content returns an error, not a file.
- A download_url lives about ten minutes. The id in https://api.fastsaver.io/v1/tunnel is held for 10 minutes and then dropped; after that the URL 404s with tunnel.not_found . Fetch the bytes in the same run; do not cache the string.
- Not every video has every format. /youtube/info is the only honest answer to "is 4K available", and it costs 2 credits to ask.
- Failures are cheap, not free. A private video, a dead link or a broken extraction still charges a flat 0.1 credits on any of the four endpoints, and answers 400. Nothing next to 15, but a retry loop over a video that will never resolve does bill.
- Big downloads take real time. Budget for it in your client timeout and your worker queue.
- Requests per minute follow the plan — 10 on Free, 900 on Mega. A 429 is a pacing signal: widen the gap between jobs rather than retrying the same one harder.
- YouTube changes things. Extraction breaks on their schedule. We fix it behind the same endpoint; your code does not move.

What you download is your responsibility. Most of YouTube is somebody's copyrighted work, and an
API key is not a licence.

## questions about the YouTube API

**Q: How do I download a YouTube video in 4K through an API?**

A: POST to /youtube/download with {"url": "…", "format": "2160p"} and
you get a download_url back. 2160p is 4K, 1440p is 2K, and both bill at 25 credits
instead of 15. Not every video has a 4K master, so check /youtube/info first.

**Q: Can I get only the audio, without the video track?**

A: Yes — POST /youtube/download with format: "audio" . The
YouTube to MP3 guide covers the Telegram path and the
cost comparison.

**Q: How long does the download_url stay valid?**

A: About ten minutes. It points at https://api.fastsaver.io/v1/tunnel?id=… — the same
api.fastsaver.io host you called, on the /v1/tunnel path — and that
id is held for 10 minutes, then dropped. After that the URL answers 404
tunnel.not_found . Pull the bytes in the same worker run; a URL cached yesterday
will not resolve today.

**Q: Why do 1440p and 2160p cost 25 credits instead of 15?**

A: Because they cost us more. A 4K stream is several times the bytes of a 1080p one and holds
a worker longer. If your users watch on a phone, 1080p at 15 credits is the better trade.

**Q: Can I search YouTube Music and download the result in one flow?**

A: Yes. /youtube/search returns 10 tracks per page, each with a
video_id , for 2 credits. Feed that id to /youtube/audio/tg-bot — 7
credits if we already have the track, 15 if we have to fetch it first — or build a watch URL
from it for /youtube/download . Pages 1–3 only, so 30 results per query.

## Keep reading

- YouTube to MP3 over HTTP — guide
- Telegram bot media API — file_id delivery
- Build a Telegram music bot — search + send
- All supported platforms — nine references

## Run a 4K download before you commit

Paste a video URL into the playground, pick a format and read the JSON. The free tier covers 66 standard downloads.

Open the playground
Get a free API key
