Downloader Developer API
Integrate downloads from 1,000+ public media sites and platforms into an agent, backend service, script, or application.
Last updated: 2026-08-02
Overview
Downloader provides an asynchronous REST API for authorized public media across 1,000+ sites and platforms. The same API works for AI agents, backend services, command-line scripts, automation platforms, and your own product.
- Base path:
/api/v1 - OpenAPI 3.1:
/api/v1/openapi.json - Capability discovery:
/api/v1/capabilities - Authentication: Bearer API key
- Response format: JSON
- Output: MP4 video, M4A audio, or 192 kbps MP3 audio
- Coverage: 1,000+ public media sites and platforms
The previous /api/agent endpoints remain available for installed agent skills, but new integrations should use /api/v1.
Architecture and job lifecycle
Creating a download does not hold the HTTP connection open while media is processed. The SaaS API authenticates the caller, reserves credits, and creates a job. A separate processing Worker runs the durable download workflow and stores the result in private temporary storage.
submitting → accepted → queued → running → ready
Terminal error states are failed, canceled, and expired. Credits are automatically restored for all three. A ready artifact is normally retained for one hour.
1. Create an API key
Sign in, open Settings → API Keys, and create a key. The full sk_... value is displayed only once. Store it in a secret manager or server-side environment variable.
Never embed an API key in public browser JavaScript, a mobile binary, a public repository, logs, or analytics events. Calls from a browser are CORS-enabled, but exposing a permanent key to end users is not safe; proxy such calls through your backend.
export DOWNLOADER_BASE_URL="https://your-downloader-domain.com"
export DOWNLOADER_API_KEY="sk_..."
2. Discover current capabilities
This endpoint is public and can be used during setup or runtime validation.
curl "$DOWNLOADER_BASE_URL/api/v1/capabilities"
It reports current platform coverage, profiles, credit costs, output formats, source restrictions, artifact lifetime, signed URL lifetime, and request limits.
1,000+ platform coverage
Downloader covers 1,000+ public media sites and platforms, including video, social media, podcasts, news, education, and pages containing embedded media. One integration handles these source categories without maintaining separate platform-specific downloaders.
Platform compatibility changes as source sites change. The reliable compatibility check is to submit the public URL and inspect the returned job result.
| Profile | Cost | Maximum video height | Maximum artifact | Processing timeout |
|---|---|---|---|---|
economy | 1 credit | 720p | 750 MiB | 15 minutes |
large | 5 credits | 1080p | 2 GiB | 30 minutes |
Video is delivered as MP4 without video transcoding. Audio is available as M4A or MP3 at 192 kbps. Actual source compatibility depends on the current extractor and whether the public source exposes a usable format.
Product feature boundary
| Capability | Supported now |
|---|---|
| Public single-video URLs across 1,000+ platforms | Yes |
| Embedded media and generic public web pages | Yes, when the extractor finds usable media |
| MP4 video up to 720p or 1080p | Yes, subject to profile and source formats |
| M4A or 192 kbps MP3 audio | Yes |
Async jobs, polling, cancellation, idempotency, and bounded retries | Yes |
| Private one-hour artifacts, signed URLs, HEAD, Range, and SHA-256 | Yes |
Playlists, live streams, login/cookie sources, private media, or DRM | No |
Subtitles, thumbnails, arbitrary low-level downloader options, or guaranteed access bypass | No |
3. Check the credit balance
curl "$DOWNLOADER_BASE_URL/api/v1/credits" \
-H "Authorization: Bearer $DOWNLOADER_API_KEY"
{
"ok": true,
"data": {
"credits": 50,
"creditPolicy": {
"expires": false,
"economyCost": 1,
"largeCost": 5
}
}
}
4. Create a download
Generate one Idempotency-Key for each logical job and keep it stable across network retries.
curl -X POST "$DOWNLOADER_BASE_URL/api/v1/downloads" \
-H "Authorization: Bearer $DOWNLOADER_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-8f52cbd3-video" \
--data '{
"sourceUrl": "https://media.example/video",
"kind": "video",
"profile": "economy",
"videoMaxHeight": 720
}'
Audio example:
{
"sourceUrl": "https://media.example/video",
"kind": "audio",
"profile": "economy",
"audioFormat": "mp3"
}
Request fields:
| Field | Required | Values and behavior |
|---|---|---|
sourceUrl | Yes | Public HTTP or HTTPS URL, up to 4,096 characters |
kind | No |
|
profile | No |
|
videoMaxHeight | Video only | 144–720 for economy; 144–1080 for large |
audioFormat | Audio only |
|
Idempotency guarantees
- Keys may contain safe ASCII characters and must be 8–128 characters long.
- Retrying the same key with the same normalized request returns the existing job and does not charge credits again.
- Reusing a key with a different request returns
409 idempotency_conflict. - Use a new key when you intentionally create another download or retry a terminal failed job.
- Requests without a key are accepted, but safe retry behavior is not guaranteed.
5. Poll until completion
curl "$DOWNLOADER_BASE_URL/api/v1/downloads/JOB_ID" \
-H "Authorization: Bearer $DOWNLOADER_API_KEY"
Use exponential backoff rather than polling continuously. A practical schedule is 2, 4, 8, then 10 seconds between requests.
async function waitForDownload(baseUrl, apiKey, jobId) {
const terminal = new Set(['ready', 'failed', 'canceled', 'expired']);
let delay = 2000;
while (true) {
const response = await fetch(`${baseUrl}/api/v1/downloads/${jobId}`, {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await response.json();
if (!response.ok)
throw new Error(body.error?.message || 'API request failed');
if (terminal.has(body.data.status)) return body.data;
await new Promise((resolve) => setTimeout(resolve, delay));
delay = Math.min(delay * 2, 10000);
}
}
The progress object includes the processing stage, percentage, and byte counts when the source provides them.
6. Download the result
When status is ready, the job contains:
artifact: filename, content type, and sizeartifactExpiresAt: when the private artifact will be deleteddownloadUrl: a signed, temporary URLdownloadUrlExpiresAt: when that particular URL expires
The signed URL normally lasts five minutes and supports GET, HEAD, and single HTTP byte ranges. If the URL expires while the artifact still exists, call GET /api/v1/downloads/{id} again to receive a new URL.
curl -L "$SIGNED_DOWNLOAD_URL" --output result.mp4
Download or copy the artifact to your own durable storage promptly. Downloader's artifact storage is intentionally temporary.
List and cancel jobs
List up to 50 recent jobs:
curl "$DOWNLOADER_BASE_URL/api/v1/downloads?limit=20" \
-H "Authorization: Bearer $DOWNLOADER_API_KEY"
Cancel an active job:
curl -X DELETE "$DOWNLOADER_BASE_URL/api/v1/downloads/JOB_ID" \
-H "Authorization: Bearer $DOWNLOADER_API_KEY"
Cancellation is idempotent. The API returns the current job if it is already terminal. Reserved credits are restored when cancellation reaches the processing service.
Errors and retries
Errors use a stable envelope:
{
"ok": false,
"error": {
"code": "invalid_request",
"message": "Economy downloads support up to 720p"
}
}
| HTTP status | Typical code | What to do |
|---|---|---|
| 401 | unauthorized | Replace or re-enable the API key |
| 402 | insufficient_credits | Purchase credits, then submit with a new key |
| 409 | idempotency_conflict | Reuse the original body or generate a new key |
| 413 | request_too_large | Keep the JSON body below 16 KiB |
| 422 | invalid_request | Correct the request fields or source URL |
| 429 | too_many_requests | Wait for the |
| 503 | service_unavailable | Retry with backoff and the same idempotency key |
Do not retry 401, 402, 409, or validation errors automatically. Network failures, 429, and 503 may be retried with backoff. Preserve the same idempotency key for ambiguous create responses.
Source and safety policy
Downloader is for media that is public and that you are authorized to download. “1,000+ platforms” describes extractor coverage, not permission to download or a guarantee for every URL. The service does not accept cookies or login sessions and does not bypass DRM, geographic restrictions, access controls, or source rate limits. Playlists and live streams are rejected. A source may stop working when its public interface changes; inspect the job's error.code and error.message.
Agent integration without MCP
Agents use the same REST API through the installable downloader-agent Skill. No MCP server is required. Configure the Skill with the site origin and an API key:
export DOWNLOADER_API_URL="$DOWNLOADER_BASE_URL"
export DOWNLOADER_API_KEY="sk_..."
The Skill creates jobs, polls them, checks credits, downloads completed artifacts, and cancels jobs. Human developers can use the REST examples on this page directly.
Versioning
The /api/v1 path is the stable public contract. Backward-compatible fields may be added without changing the version. Removing or changing existing fields requires a new major API path. Use capability discovery instead of hard-coding limits when possible.
For generated clients and API tooling, import the OpenAPI 3.1 document.