Skip to content

Introduction

The Tunelio API gives you a direct download URL for any YouTube video or audio in a single request — no queues, no polling, no progress webhooks. The whole surface is two endpoints: GET /info for metadata, GET /create for the download link.

Base URL: https://tunelio.dev. All requests use TLS 1.2+. Responses are JSON with UTF-8 encoding.

Mental model

Call /info to see what formats are available for a given URL, then call /create with the chosen quality. The response from /create contains a url that points to our CDN tunnel — hand that to your user, your downloader, or a presigned S3 upload. There's no step three.

No polling, ever. If you've used other download APIs you may be used to job IDs and SSE streams. We don't have those — every request is request/response.

Authentication

All requests require an API key sent as a Bearer token in the Authorization header.

Authorization: Bearer tnl_8f3a92b1c4d5e6f7a8b9c0d1e2f3a4b5

Sign in with Telegram (one tap with @TunelioDevBot — no email or password), then generate your API key from the Dashboard. The whole flow takes about 60 seconds and doesn't require a payment method.

Keep your key server-side. Anyone with the key can spend your credits. Never embed it in a browser bundle or mobile binary — proxy through your own backend.

Quickstart

Make your first call in three lines. Replace the key with your own and the URL with any YouTube link.

curl "https://tunelio.dev/create?quality=720p&url=https://youtu.be/dQw4w9WgXcQ" \
  -H "Authorization: Bearer tnl_…"

GET /info

Resolves a YouTube URL and returns the full metadata — title, duration, thumbnail, and every available video and audio format with file sizes and dimensions.

Query parameters

urlstringrequiredA YouTube URL: watch?v=, youtu.be/, /shorts/, /embed/, or /live/. Any of these resolve identically.

Try it

GETtunelio.dev/info
Try it · costs 6 credits
GET tunelio.dev/info?url=https://youtu.be/dQw4w9WgXcQ

Response shape

titlestringVideo title as published.
duration_secondsintegerTotal length in seconds.
duration_strstringHuman-readable HH:MM:SS (or MM:SS when < 1h). Zero-padded.
thumbnailstring (URL)Highest-resolution thumbnail available.
formats[]array<Format>Every video format. See sub-fields below.
formats[].qualitystringHuman label: 144p, 240p, 360p, 480p, 720p, 1080p.
formats[].file_sizeinteger (bytes)Exact size in bytes.
formats[].file_size_strstringHuman-readable size — e.g. "84.50 MB" or "1.20 GB".
formats[].widthintegerEncoded frame width in pixels.
formats[].heightintegerEncoded frame height in pixels.
audioFormatobject<Audio>|nullThe best MP3 audio rendition — single object, or null if no audio track is available.
audioFormat.formatstringContainer — currently mp3.
audioFormat.file_sizeintegerExact MP3 size in bytes.
audioFormat.file_size_strstringHuman-readable MP3 size — e.g. "35.01 MB".

Cost

6 credits per call. Cached identical URLs return for free within 30 minutes.

GET /create

Generates a direct, signed CDN download URL for a chosen format. The link comes back in the same response — there's no job to poll, no webhook to listen for.

Query parameters

urlstringrequiredYouTube URL — same formats as /info.
qualitystringrequiredOne of 144p, 240p, 360p, 480p, 720p, 1080p, 2160p (Mega only), or mp3 for audio.

Try it

GETtunelio.dev/create
Try it · costs 10 credits
GET tunelio.dev/create?url=https://youtu.be/dQw4w9WgXcQ&quality=1080p

Response shape

urlstring (URL)Signed CDN tunnel URL. Hand to your user or pipe to storage.
filenamestringSuggested filename based on the video title and chosen format.
qualitystringEcho of your requested quality — e.g. 1080p or mp3.
modestring"video" or "audio".
typestring"merge" (video+audio muxed) or "single" (audio-only or pre-muxed).
expiresinteger (unix)Timestamp when the signed URL stops working — typically 6 hours out.
file_sizeintegerFinal file size in bytes.
file_size_strstringHuman-readable size — e.g. "84.50 MB".
statusstringAlways "tunnel" on success.

Cost

10 credits per call. The cost is the same regardless of file size — you pay for the resolution work, not the bytes.

Bytes don't pass through your server. Your backend only sees the small JSON response. The tunnel URL streams directly from our CDN to your end-user.

GET /credits

Returns your remaining credit balance and effective plan. Use it to check how much you have left before a batch of calls, or to surface a balance in your own dashboard.

No query parameters — just your API key. The same Bearer token (or X-API-Key header) used everywhere else authenticates this call.

Try it

GETtunelio.dev/credits
Try it · costs free
GET tunelio.dev/credits

Response shape

creditsintegerRemaining credit balance, as an integer.
planstringYour effective plan: trial, pro, ultra, or mega. A lapsed paid plan reports trial.

Response headers

The same balance is mirrored in response headers, matching /info and /create — handy if you want the numbers without parsing the body:

X-Credits-RemainingintRemaining credit balance.
X-Credits-PlanstrYour effective plan name.

Cost

Free. Checking your balance never consumes credits.

This endpoint is read-only and always free, so you can poll it as often as you like — for example before a large batch — without spending anything.

/tunnel

/tunnel is the URL you get back from /create. You never call it from your code — you hand the URL to your user, your <a download> tag, your S3 uploader, your Telegram bot, etc.

What it returns

The actual file — MP4 or MP3 — with appropriate Content-Type and Content-Disposition: attachment; filename="…" headers. It supports HTTP range requests, so video players can seek and downloaders can resume.

Authentication

None. The URL is self-signed with an exp timestamp and a sig HMAC. After expires passes, the link returns 410 Gone — call /create again for a fresh one.

Costs

Free. Bandwidth is on us within reason — we throttle abuse but normal use never triggers it.

Rate limits

Rate limits are per API key, measured in requests per minute. They reset every 60 seconds on a rolling window. Ultra and Mega plans have no rate limit.

Trial15 req / min
Pro5 req / sec
Ultrano limit
Megano limit

Exceeding the limit returns 429 Too Many Requests with a Retry-After header (in seconds). If you regularly bump the ceiling, upgrade rather than adding client-side backoff — limits exist so you don't accidentally drain your credits.

Errors

All error responses follow the same shape:

{
  "error": "invalid_url",
  "message": "Provided URL is not a recognised YouTube link."
}

Status codes

400invalid_requestMissing or malformed parameter — usually a bad URL or unknown quality.
401unauthorizedMissing or invalid Bearer token.
402insufficient_creditsYour account is out of credits. Top up or upgrade.
404not_foundVideo does not exist, is private, or was deleted.
410goneYou called a /tunnel URL after its expires timestamp.
429rate_limitedPlan rate limit hit. Respect the Retry-After header.
500server_errorUnexpected on our side. Safe to retry with exponential backoff.
503upstream_changedYouTube changed something we hadn't patched yet. Usually self-heals within an hour.

Credits & billing

Every call costs a fixed number of credits regardless of video size or duration:

GET /info6 credits
GET /create10 credits
/tunnel downloadfree

A typical "fetch info, then download" round-trip is 16 credits. New accounts start with 100 free credits. Paid plans refresh monthly with fresh credits each cycle.

Failed requests (4xx and 5xx) do not consume credits — you're only billed for successful resolutions.