YouTube Proxy Download

POST/openapi/v1/youtube/proxy-download — 4 credits per 10 minutes of video.

Pass a YouTube link and get back the same response as Extract Post, plus proxy URLs for every variant up to 1080p. Download them from cloud servers, VPS or serverless functions — no residential proxies, cookies or PO tokens to maintain.

Why YouTube returns 403 Forbidden on servers

You call /extract/post, get a googlevideo.com link, and downloading it from your server fails with HTTP Error 403: Forbidden. What we measured:

  • Data-center IPs are refused. The same direct link downloaded fine (206) from a residential connection and failed with 403 from data-center servers in several regions across Asia and Europe. The link is not tied to the IP that extracted it — YouTube judges the IP that downloads it.
  • Some links only download from US IPs. Links that carry a gcr=us parameter return 403 to any IP outside the US.

So fixing extraction alone (a different tool, cookies, PO tokens) doesn't help: as long as the download runs on a data-center IP, it still gets 403.

How it works

  1. You send a YouTube link to POST /openapi/v1/youtube/proxy-download.
  2. We extract the video and return the usual extraction result, with a proxy URL added to each variant up to 1080p.
  3. You download the proxy URL. Our download network fetches the file from YouTube and streams it to you, so YouTube never sees your server's IP.

The direct URLs (video_url, audio_url, resource_url) are all still in the response. Variants above 1080p only have direct URLs, and if your server can download direct URLs (for example on a residential connection), you can keep using them.

Request / Response

curl -X POST https://api.snapany.com/openapi/v1/youtube/proxy-download \
  -H "Authorization: Bearer sk_snapany_xxx" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'

Accepts youtube.com links (videos, Shorts, live replays, m. and music. subdomains) and youtu.be links. Anything else — including youtube-nocookie.com embeds and short links that redirect to YouTube (such as t.co) — returns HTTP 400 with code unsupported_site and is not charged.

Response (abridged — IDs and URLs are placeholders):

{
  "site": "youtube",
  "title": "Scenic tour of the Karst mountains",
  "medias": [
    {
      "media_type": "video",
      "resource_url": "https://rr1---sn-example.googlevideo.com/videoplayback?itag=18&expire=1700000000&sig=EXAMPLE",
      "resource_proxy_url": "https://proxy.example.com/proxy?payload=EXAMPLE_360P_RESOURCE",
      "preview_url": "https://i.ytimg.com/vi/EXAMPLE0001/maxresdefault.jpg",
      "duration": 754,
      "variants": [
        {
          "quality": 2160,
          "quality_label": "4K",
          "fps": 30,
          "video_url": "https://rr1---sn-example.googlevideo.com/videoplayback?itag=313&expire=1700000000&sig=EXAMPLE",
          "video_ext": "webm",
          "video_codec": "vp9",
          "video_filesize": 687194112,
          "audio_url": "https://rr1---sn-example.googlevideo.com/videoplayback?itag=251&expire=1700000000&sig=EXAMPLE",
          "audio_ext": "weba",
          "audio_codec": "opus",
          "audio_filesize": 11354112
        },
        {
          "quality": 1080,
          "quality_label": "1080p",
          "fps": 30,
          "video_url": "https://rr1---sn-example.googlevideo.com/videoplayback?itag=137&expire=1700000000&sig=EXAMPLE",
          "video_proxy_url": "https://proxy.example.com/proxy?payload=EXAMPLE_1080P_VIDEO",
          "video_ext": "mp4",
          "video_codec": "h264",
          "video_filesize": 181403648,
          "audio_url": "https://rr1---sn-example.googlevideo.com/videoplayback?itag=140&expire=1700000000&sig=EXAMPLE",
          "audio_proxy_url": "https://proxy.example.com/proxy?payload=EXAMPLE_1080P_AUDIO",
          "audio_ext": "m4a",
          "audio_codec": "aac",
          "audio_filesize": 12202891
        },
        {
          "quality": 360,
          "quality_label": "360p",
          "fps": 30,
          "video_url": "https://rr1---sn-example.googlevideo.com/videoplayback?itag=18&expire=1700000000&sig=EXAMPLE",
          "video_proxy_url": "https://proxy.example.com/proxy?payload=EXAMPLE_360P_VIDEO",
          "video_ext": "mp4",
          "video_codec": "h264",
          "video_filesize": 50847744
        }
      ]
    },
    {
      "media_type": "audio",
      "resource_url": "https://rr1---sn-example.googlevideo.com/videoplayback?itag=140&expire=1700000000&sig=EXAMPLE",
      "resource_proxy_url": "https://proxy.example.com/proxy?payload=EXAMPLE_AUDIO_RESOURCE",
      "duration": 754,
      "variants": [
        {
          "audio_url": "https://rr1---sn-example.googlevideo.com/videoplayback?itag=140&expire=1700000000&sig=EXAMPLE",
          "audio_proxy_url": "https://proxy.example.com/proxy?payload=EXAMPLE_AUDIO_EN",
          "audio_ext": "m4a",
          "audio_codec": "aac",
          "audio_filesize": 12202891,
          "language_tag": "en",
          "language_name": "English"
        }
      ]
    }
  ],
  "id": "EXAMPLE0001",
  "post_url": "https://www.youtube.com/watch?v=EXAMPLE0001",
  "created_at": "2025-06-02T12:00:00.000Z",
  "author": { "username": "@travelchannel", "display_name": "Travel Channel" }
}

Fields added on top of the Extract Post response:

FieldOnPresent when
video_proxy_urlvariantThe variant is 1080p or below
audio_proxy_urlvariantA video variant at 1080p or below has a separate audio stream; every language variant of an audio media
resource_proxy_urlvideo or audio mediaThe file behind resource_url is 1080p or below

Files over 3 GB never get a proxy URL. There is no preview_proxy_url and no expiry field — see the validity rules below.

Full schema: API Reference.

Downloading with video_proxy_url

Pick the highest variant that has a video_proxy_url. If it also has an audio_proxy_url, video and audio are separate streams: download both, then merge them with ffmpeg. If there is only a video_proxy_url, it is already a complete file. Proxy URLs need no API key and no extra headers.

Variants at 1080p and below are usually MP4 (H.264) video with M4A (AAC) audio, so -c copy produces a standard MP4 without re-encoding. For a single ready-to-play file, use resource_proxy_url on the video media (often a lower resolution with audio included); for audio only, use resource_proxy_url on the audio media.

curl (with jq):

# 1. Get the proxy URLs
curl -s -X POST https://api.snapany.com/openapi/v1/youtube/proxy-download \
  -H "Authorization: Bearer sk_snapany_xxx" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}' > post.json

# 2. Pick the highest variant that has a proxy URL (1080p or below)
jq '[.medias[] | select(.media_type == "video") | .variants[]? | select(.video_proxy_url)] | max_by(.quality)' post.json > variant.json

# 3. Download both streams: -f fails on HTTP errors, -C - resumes an interrupted download
#    (no audio_proxy_url? The video file is complete — skip the audio line and step 4)
curl -fL -C - -o video.mp4 "$(jq -r .video_proxy_url variant.json)"
curl -fL -C - -o audio.m4a "$(jq -r .audio_proxy_url variant.json)"

# 4. Merge: stream copy, no re-encode
ffmpeg -i video.mp4 -i audio.m4a -c copy merged.mp4

Python:

import subprocess
import requests

response = requests.post(
    "https://api.snapany.com/openapi/v1/youtube/proxy-download",
    headers={"Authorization": "Bearer sk_snapany_xxx"},
    json={"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"},
)
response.raise_for_status()
post = response.json()

# Highest variant with a proxy URL (proxy URLs only exist at 1080p and below)
video = next(media for media in post["medias"] if media["media_type"] == "video")
variant = max((v for v in video["variants"] if v.get("video_proxy_url")), key=lambda v: v["quality"])


def download(url, path):
    # No API key or headers needed: the proxy URL itself grants access
    with requests.get(url, stream=True, timeout=60) as r:
        r.raise_for_status()  # e.g. 404 payload_expired
        with open(path, "wb") as f:
            for chunk in r.iter_content(1 << 20):
                f.write(chunk)


download(variant["video_proxy_url"], "video.mp4")
if variant.get("audio_proxy_url"):
    download(variant["audio_proxy_url"], "audio.m4a")
    subprocess.run(["ffmpeg", "-i", "video.mp4", "-i", "audio.m4a", "-c", "copy", "merged.mp4"], check=True)

Node.js (18+):

import { spawnSync } from 'node:child_process'
import { createWriteStream } from 'node:fs'
import { Readable } from 'node:stream'
import { pipeline } from 'node:stream/promises'

const response = await fetch('https://api.snapany.com/openapi/v1/youtube/proxy-download', {
  method: 'POST',
  headers: { Authorization: 'Bearer sk_snapany_xxx', 'Content-Type': 'application/json' },
  body: JSON.stringify({ url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' }),
})
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`)
const post = await response.json()

// Highest variant with a proxy URL (proxy URLs only exist at 1080p and below)
const video = post.medias.find(media => media.media_type === 'video')
const variant = video.variants.filter(v => v.video_proxy_url).sort((a, b) => b.quality - a.quality)[0]

async function download(url, path) {
  const res = await fetch(url)
  if (!res.ok) throw new Error(`${res.status} ${await res.text()}`) // e.g. 404 payload_expired
  await pipeline(Readable.fromWeb(res.body), createWriteStream(path))
}

await download(variant.video_proxy_url, 'video.mp4')
if (variant.audio_proxy_url) {
  await download(variant.audio_proxy_url, 'audio.m4a')
  spawnSync('ffmpeg', ['-i', 'video.mp4', '-i', 'audio.m4a', '-c', 'copy', 'merged.mp4'], { stdio: 'inherit' })
}

For large files, download with Range requests (curl -C -, or your own Range: bytes=… headers) so an interrupted transfer resumes instead of starting over.

Validity, limits and billing

Validity: proxy URLs are valid for at least 30 minutes and at most 1 hour from the response. Start downloading as soon as you get the response, and plan around 30 minutes.

After that, a proxy URL returns HTTP 404:

{ "code": "payload_expired", "message": "link has expired" }

Call the endpoint again to get fresh URLs — retrying the same URL won't help.

If a proxy URL returns HTTP 403 while it is still valid, YouTube refused that request:

{ "code": "upstream_error", "message": "upstream refused the request", "retryable": true, "upstream_status": 403 }

This is rare, and a single retry usually succeeds.

Limits:

  • Proxy URLs go up to 1080p. Variants above 1080p (1440p, 4K, 8K) stay in the response with direct URLs only — see the FAQ below.
  • Files over 3 GB get no proxy URL.
  • YouTube links only. Links that can't be extracted — playlists, channels, streams that are still live, members-only or deleted videos — fail with HTTP 400 (see Errors) and are not charged.

Billing: charged once the response is returned, based on what it contains.

Response containsCost
Video proxy URLs (video_proxy_url on a variant, or resource_proxy_url on video media)4 credits per 10 minutes of video (rounded up)
Audio proxy URLs only4 credits
No proxy URLs1 credit

Examples: a video of 10 minutes or less costs 4 credits, 10–20 minutes costs 8, and 1 hour costs 24. The length comes from the duration field; when it is missing, the call costs 4 credits. The example response above (duration: 754, about 12.5 minutes) costs 8 credits. Calls that fail (unsupported link, extraction failure) are not charged.

FAQ

Do I need to maintain residential proxies?

Not with this endpoint. Residential proxies commonly cost $3–4 per GB, so a 20-minute 1080p video (roughly 270–470 MB) costs about $0.81–1.88 in proxy traffic alone, before the work of keeping cookies and PO tokens valid. Through this endpoint the same video costs 8 credits — about $0.0053–0.0088 depending on your credit pack.

What about "Sign in to confirm you're not a bot"?

That error comes up during extraction, when YouTube treats a request as automated — common on server IPs. With this endpoint, extraction runs on our side, so your server needs no cookies, signed-in account or PO tokens.

Does it work on AWS Lambda, EC2 or a VPS?

Yes. Your server only talks to the SnapAny API and our download network, never to YouTube directly, so it makes no difference whether it runs on AWS Lambda, EC2, another cloud or a VPS. Mind your runtime's own limits: Lambda caps execution time and /tmp storage, so stream long videos straight to object storage (such as S3) or download them in Range chunks.

Can I get 4K through the proxy?

No — proxy URLs go up to 1080p. The 1440p, 4K and 8K variants stay in the response with direct URLs only. YouTube serves those resolutions only as VP9 or AV1, and the files are 3–7 times larger than 1080p, so you would usually need to transcode them anyway. Those direct URLs generally download fine from a residential connection. If you need higher resolutions through the proxy, let us know.