Skip to main content
POST
Create Job

Overview

Creates a new download job. For single videos, returns a job_id. For Spotify shows, YouTube playlists and YouTube channels, automatically creates a batch and returns a batch_id with all episode/video job IDs.
If url contains a YouTube playlist ID, this endpoint downloads the ENTIRE playlist, not just one video. This applies even if you only meant to download a single video — see Playlist Auto-Detection below before you’re surprised by a batch of thousands of jobs from what looked like a single-video request.

Billing

Each completed job is metered separately. When your account’s 720p floor is enabled, clips and audio extraction can count the full source’s 720p reference even if the delivered file is smaller. A single job using clips counts the sum of its outputs with one reference calculation; playlist and show batches contain separately metered jobs. See Billing & Metering for all rules and examples.

Header Parameters

string
required
Your API key for authentication

Request

string
required
The video or show URL to download. If this URL contains a genuine YouTube playlist ID (list=PL..., UU..., or OL...) is a YouTube channel URL (youtube.com/@handle, /channel/UC..., /c/..., /user/...) or is a Spotify show, the request downloads the WHOLE playlist/channel/show as a batch — see Playlist Auto-Detection.
string
Output container format. Video: mp4, mkv, webm, mov. Audio: m4a, mp3, ogg, opus. Default: mp4 (or m4a when audio_only is true)
string
Video codec: copy (no re-encode), h264, h265/hevc, vp9, vp8. Default: copy
string
Audio codec: copy (no re-encode), aac, opus, mp3, vorbis. Default: copy with automatic fallback to aac if incompatible
string
Audio bitrate when transcoding: 64k, 128k, 192k, 256k, 320k. Default: 192k
integer
Video quality CRF (0-51, lower = better quality). Only used when video_codec is not copy. Default: 23
string
Custom filename (without extension). Max 255 characters. Cannot contain .., /, \, or null bytes.
string
S3 folder prefix for organizing files. Max 200 characters. Cannot contain .., start with / or \, or be empty/whitespace-only.
string
URL to receive completion notification via POST request.
boolean
default:"false"
Extract audio track only. Outputs m4a (native AAC, no re-encoding) by default. Set format to mp3, ogg, or opus for other audio formats. Supports audio_codec and audio_bitrate for transcoding control.
boolean
default:"false"
Download subtitles if available. Returns subtitle URL in job response.
boolean
default:"false"
Download video thumbnail. Returns thumbnail URL in job response.
Thumbnail upload currently uses the Spotify thumbnail returned by extraction. A YouTube request can accept this option without producing a thumbnail URL; do not rely on it for YouTube thumbnails.
string
Quality preset that overrides video_quality. Options: highest, high, medium, low, lowest.
string
Video resolution preference. Options: best (default), lowest, 2160 (4K), 1440, 1080, 720, 480, 360, 240, 144. Resolution uses the shorter dimension for both horizontal and vertical videos.lowest selects the smallest available video format. A numeric value selects the highest available resolution at or below that value. If every available format exceeds it, the smallest available format is used; the video is not resized. For example, 240 selects 144p when the source offers 144p and 360p, or 360p when the source starts at 360p.For 144 and lowest, separate audio defaults to the lowest available AAC track. Explicit audio codec preferences are respected. A higher bitrate may remain when no lower AAC track is available or when audio is embedded in the selected HLS stream. Check actual_quality in the completed job status for the delivered resolution.
string
Start timestamp for video clipping. Format: HH:MM:SS, MM:SS, or seconds (e.g., 00:01:30 or 90).
string
End timestamp for video clipping. Format: HH:MM:SS, MM:SS, or seconds (e.g., 00:05:00 or 300). Must be greater than clip_start.
array
1–100 ranges for separate files from a single source download. Each item requires string clip_start and clip_end (seconds, MM:SS or HH:MM:SS). Mutually exclusive with top-level clip_start/clip_end. One job delivers all outputs through clip_files; see multi-clip example.
boolean
default:"false"
Enable live stream recording mode. Auto-detected for live URLs.
boolean
default:"false"
For live streams: record from the beginning (VOD mode) instead of the live point.
integer
Maximum recording duration in seconds. Recommended for live streams as a safety cap. Example: 7200 for 2 hours.
boolean
default:"false"
Wait for scheduled/upcoming streams to start before downloading.
boolean
default:"false"
Enable progress webhooks during processing. Sends updates at each stage: downloading, muxing, uploading.
object
Inline storage credentials, optional when another destination is available. Direct users can override pre-configured storage; marketplace users can also reuse saved credentials or use platform storage when enabled. Supports 4 providers via the provider field. See Inline Storage examples below. Mutually exclusive with storage_provider.
string
Deliver this job to one of your saved storage destinations, selected by provider: "s3", "blob" (Azure), "gcs", "oss". Resolved against the destinations configured on your API key first, then on your organization. Returns 400 storage_provider_not_configured if no destination of that provider exists. Mutually exclusive with storage (both present → 400). Omit it to use your default destination. See Choosing a saved destination.
boolean
default:"false"
For Spotify show batches only. Creates the batch in paused mode: jobs are not enqueued for processing immediately. Use PATCH /batch/{id}/jobs to rename episodes, then POST /batch/{id}/start to launch.
string
Cookies of a signed-in, age-verified YouTube account, used only to download an age-restricted YouTube video. Send the Netscape cookies.txt export as one string (one cookie per line, 7 tab-separated columns). Accepted with a single YouTube video URL only, up to 64 KiB. Cookies are never logged, never returned by the API, and are discarded once the download finishes. See Age-Restricted Videos.

Single Job Response

string
UUID of the created job
Response

Batch Response (Spotify Shows)

When the URL is a Spotify show, a batch is created automatically:
string
UUID of the batch job
integer
Number of episodes in the show
boolean
Whether the batch was created in paused mode
array
List of episode details with job IDs, URLs, titles, descriptions, and release dates
array
List of job IDs for each episode (legacy field)
Response (default mode)
Response (paused mode)

Examples

Choosing a saved destination

If you configured several storage destinations (one per provider) in the dashboard, pick the one a job should use with storage_provider:
  • Accepted values: "s3", "blob" (Azure Blob), "gcs", "oss" — the provider of a destination you saved.
  • Resolution order: destinations on the API key, then on the organization. Omit the field to use your default destination (the one marked default, else the most recently saved).
  • 400 storage_provider_not_configured — no saved destination of that provider on the key or the organization.
  • 400 storage_and_storage_provider_are_exclusive — you sent both storage (inline credentials) and storage_provider.
  • If the destination cannot be resolved when the worker uploads (credentials revoked in between), the job is marked Failed — it is never silently delivered elsewhere.

Inline Storage

The storage field lets you provide cloud storage credentials directly in the request. Marketplace requests first use supplied credentials, then previously saved credentials. If neither is available, platform storage is allowed when MARKETPLACE_DEFAULT_STORAGE is enabled (the server default); otherwise the request requires customer storage.
Inline storage credentials take priority over pre-configured storage and are validated before the job is accepted, in three steps — each failure returns 400 with the reason:
  1. Shape — bucket/container name, keys, endpoint (Invalid storage configuration: …), no network call.
  2. Backend construction — provider-specific requirements (e.g. GCS project_id).
  3. Live probe — a small test object is uploaded then deleted with your credentials (Storage credentials validation failed: …). The result is cached for 5 minutes per credential set, so repeated jobs with the same storage don’t pay the probe again.
A 201 Created means validation passed, possibly using a result cached for up to five minutes; permissions and reachability can change afterward. If, despite that, the backend cannot be initialised at upload time, the job is marked Failed with storage_unreachable — it is never silently delivered to another bucket.Credentials are never logged. For direct API keys they live only in the encrypted job payload until the job completes. For marketplace users (RapidAPI, Apify, Zyla) they are saved so later requests can omit storage — see the marketplace section.

Provider Fields

Age-Restricted Videos

YouTube serves age-restricted videos only to a signed-in account whose age is verified. Without cookies, such a job ends with status Warning and an age-restriction error. To download it, send the cookies of an age-verified account in the cookies field:
The job then runs like any other: poll GET /jobs/{id} until it is Completed. All other options (max_resolution, format, storage, webhook_url…) work as usual.

Exporting the cookies

1

Use a dedicated account

Create or pick a YouTube account used only for this purpose, and verify its age. The cookies give access to the whole Google account: never send the cookies of a personal or company account.
2

Sign in from a private window

Open a private (incognito) browser window and sign in to youtube.com with that account.
3

Export youtube.com cookies

Export the cookies of the youtube.com tab in Netscape cookies.txt format with a cookies.txt browser extension. The file format is the one yt-dlp reads with --cookies.
4

Close the private window

Close the window right after the export. While a YouTube tab stays open, the browser rotates the session cookies and an export taken from an everyday window usually stops working within hours.

Accepted format

Send cookies only for videos that need them: other videos download without an account.

How cookies are handled

  • They are used for this job’s YouTube requests only, never for another job or another customer.
  • They are never written to logs, never stored in the job record, and never returned by GET /jobs/{id}. While the job waits in the queue they are kept encrypted, and they are discarded as soon as the download finishes.
  • POST /jobs/{id}/retry runs without them. To retry, submit POST /jobs again with fresh cookies.

When YouTube rejects the cookies

If the cookies have expired, belong to a signed-out session or to an account whose age is not verified, the job ends with status Warning. Nothing is delivered, so nothing is billed:
Export fresh cookies (see above) and submit the job again.

Success Response

Playlist Auto-Detection

POST /jobs inspects url and automatically creates a batch (one job per video) instead of a single job whenever it detects a genuine YouTube playlist or a YouTube channel. There is no separate “batch” endpoint or flag to opt into this — it happens automatically based on the URL you send.

Which URLs trigger it

This is the #1 source of “I asked for one video and got thousands of jobs” confusion. YouTube’s own UI automatically appends &list=RD<video_id>&start_radio=1 to the URL bar any time you open a video from an autoplay queue, the homepage, related videos, or a “Radio”/Mix button — not because you’re viewing a playlist. If you’re integrating by copy-pasting URLs from a browser, always double-check for a list= parameter before sending it here. As of 2026-07-08, list=RD.../WL/LL URLs are correctly treated as single-video requests (this was previously a real bug that caused two production incidents) — but if you’re on an older integration or unsure, strip any list=/start_radio= query parameters from the URL yourself before calling this endpoint to be safe.

Size limit

Even a genuine playlist (PL/UU/OL) is capped at 500 videos per request (configurable server-side via MAX_PLAYLIST_BATCH_SIZE). A channel URL is capped at 20,000 videos (MAX_CHANNEL_BATCH_SIZE), because it cannot be an accidental copy-paste. A collection larger than its cap is rejected outright with a 413 Payload Too Large — it is never silently truncated. If you need to download a larger playlist, split it into smaller batches or contact support. Videos that YouTube lists as unavailable in the playlist or channel (deleted, private, blocked) are skipped: they would only produce failed jobs.

Channels and concurrency

Every video of the batch becomes its own job, but a channel is not downloaded all at once. Each API key has a limit of jobs in flight (250 by default). Jobs beyond that limit are created immediately with status pending and the step Queued (account concurrency limit), then released automatically as earlier jobs finish. Nothing is refused, and every job ID is returned in video_jobs right away. An unknown channel, or a tab the channel does not have (for example /streams on a channel that never streamed), returns 404.

Response

string
UUID of the batch job
integer
Number of videos in the playlist
array
List of job IDs for each video
Genuine Playlist (downloads all videos)
Response
Channel (downloads every upload, queued past the key's concurrency limit)
Response
Radio/Mix URL (downloads only the one video)
Response
413 Payload Too Large (playlist exceeds the cap)

Error Responses

Notes

The 429 Too Many Requests (server at capacity) and 503 Service Unavailable (service draining) responses include a Retry-After header indicating how many seconds to wait before retrying. The 503 credential_encryption_unavailable response has no Retry-After header: retry after a short delay.
Codec auto-correction: When format is set, incompatible codec/format combinations are automatically corrected to ensure valid output (the same rule applies to POST /jobs/bulk):
  • webm + h264/h265 or no video codec → video codec changed to vp9
  • webm + aac/mp3 or no audio codec → audio codec changed to opus
  • mov + vp9/vp8 or no video codec → video codec changed to h264 (mov cannot hold VP9, VP8 or AV1)
  • mp4 + vp8 → video codec changed to vp9 (mp4 cannot hold VP8)
  • mp4/mov + opus/vorbis or no audio codec → audio codec changed to aac
  • m4a + any codec other than aac → audio codec changed to aac
  • ogg + aac/mp3 or no audio codec → audio codec changed to opus
  • opus + any other codec → opus; mp3 + any other codec → mp3
  • Setting audio_bitrate without audio_codec (or with copy) → audio codec defaults to aac
Codec names are case-insensitive. vp8 is encoded with libvpx and vorbis with libvorbis.Unknown or empty format values return 400 at admission. Omitting the field selects the default.