미디어 다운로더 API

v1 · 베이스 URL https://ytdl.blbt.app · 웹 UI로 돌아가기

인증

환경변수 API_TOKEN 에 선언한 값을 그대로 Authorization 헤더에 넣는다. 별도의 토큰 발급 절차는 없다.

Authorization: Bearer <API_TOKEN>

Bearer 접두사 없이 토큰만 보내도 동작한다. 비교는 상수 시간으로 수행한다. 웹 UI가 쓰는 /api/* (Turnstile 세션 쿠키)와는 완전히 분리된 인증 체계다.

작업 소유자 ID는 토큰 해시에서 파생된다. 토큰을 교체하면 이전 토큰으로 만든 작업 목록은 더 이상 조회되지 않는다.

에러 형식

{ "error": { "code": "invalid_request", "message": "`url` must be an http(s) URL" } }
codeHTTP의미
invalid_request400본문·쿼리 파라미터가 규약에 맞지 않음
unauthorized401헤더 누락 또는 토큰 불일치
not_found404없는 작업·파일·엔드포인트
method_not_allowed405경로는 맞으나 메서드가 다름
job_not_ready409아직 done 이 아닌 작업의 파일 요청
info_failed422해당 URL의 메타데이터를 읽지 못함
engine_unavailable502다운로드 엔진에 도달 불가
not_configured503배포에 API_TOKEN 이 없음

엔드포인트

GET/v1 · GET/v1/health

인증 없이 호출할 수 있다. /v1 은 엔드포인트 목록과 제한값을 담은 자기서술 인덱스, /v1/health 는 컨테이너를 깨우지 않는 라이브니스 프로브다.

POST/v1/info

다운로드 전에 제목·길이·선택 가능한 화질을 확인한다.

curl -s https://ytdl.blbt.app/v1/info \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'
{
  "title": "Rick Astley - Never Gonna Give You Up",
  "id": "dQw4w9WgXcQ",
  "extractor": "Youtube",
  "duration": 213,
  "is_playlist": false,
  "entries_count": 1,
  "heights": [2160, 1440, 1080, 720, 480, 360]
}

POST/v1/jobs

필드타입기본값설명
urlstring(필수)http/https URL
mode"video" | "audio""video"audio 는 mp3로 추출
qualityinteger | nullnull해상도 상한(예: 1080). null = 최고 화질
playlistbooleanfalse재생목록 전체 다운로드
browser_authobjectnull쿠키·PO 토큰 주입(선택)
curl -s https://ytdl.blbt.app/v1/jobs \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"url":"...","mode":"video","quality":1080}'

202 Accepted + 작업 객체를 반환하고 Location 헤더에 조회 URL이 담긴다.

GET/v1/jobs

이 토큰으로 만든 작업만 최신순으로 반환한다. ?limit=(1~50), ?status=(예: done) 로 걸러낼 수 있다.

GET/v1/jobs/{job_id}

작업 객체를 반환한다. done 이면 files[].download_url 에 1시간짜리 서명 URL이 채워진다.

GET/v1/jobs/{job_id}/download

서명 URL로 302 리다이렉트한다. 파일이 여러 개면 ?file=<인덱스> 로 고른다.

curl -L -OJ "https://ytdl.blbt.app/v1/jobs/$JOB/download" \
  -H "Authorization: Bearer $API_TOKEN"
리다이렉트 대상인 /files/... 는 서명으로만 보호되며 헤더 인증을 요구하지 않는다. 1시간 동안 누구에게나 유효하니 공유에 주의할 것.

DELETE/v1/jobs/{job_id}

기록과 R2 파일을 삭제한다. 진행 중인 다운로드 자체는 중단되지 않는다.

{ "deleted": true, "job_id": "j_ab12cd34ef56", "files_deleted": 1 }

작업 객체

{
  "job_id": "j_ab12cd34ef56",
  "status": "done",
  "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "mode": "video",
  "quality": 1080,
  "playlist": false,
  "title": "Rick Astley - Never Gonna Give You Up",
  "progress": { "percent": 100.0, "speed": null, "eta": null },
  "files": [
    {
      "filename": "Rick Astley ... [dQw4w9WgXcQ].mp4",
      "size": 18234567,
      "download_url": "https://ytdl.blbt.app/files/...?exp=...&sig=...",
      "expires_at": "2026-08-16T10:00:00.000Z"
    }
  ],
  "error": null,
  "created_at": "2026-08-16T09:00:00.000Z",
  "updated_at": "2026-08-16T09:01:12.000Z"
}

상태 전이: queued → downloading → processing → uploading → done, 실패 시 error. 두 종료 상태에서만 폴링을 멈추면 된다.

전체 예제

API=https://ytdl.blbt.app

JOB=$(curl -s $API/v1/jobs \
  -H "Authorization: Bearer $API_TOKEN" -H 'Content-Type: application/json' \
  -d '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ","mode":"audio"}' \
  | python3 -c 'import sys,json; print(json.load(sys.stdin)["job_id"])')

while :; do
  ST=$(curl -s $API/v1/jobs/$JOB -H "Authorization: Bearer $API_TOKEN" \
    | python3 -c 'import sys,json; print(json.load(sys.stdin)["status"])')
  echo "status=$ST"
  [ "$ST" = done ] || [ "$ST" = error ] && break
  sleep 5
done

curl -L -OJ "$API/v1/jobs/$JOB/download" -H "Authorization: Bearer $API_TOKEN"

권장 폴링 주기는 3~5초. 컨테이너는 활성 작업이 없으면 10분 뒤 잠들며, 첫 요청은 콜드 스타트로 수 초 더 걸릴 수 있다.

제한

서명 다운로드 URL 유효기간1시간
작업 기록 보존20시간
R2 파일 보존1일
목록 최대 항목 수50
동시 다운로드2

레이트 리밋은 없다. API_TOKEN 이 유일한 방어선이므로 유출되지 않게 관리할 것.