Back to home

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.

ProfileCostMaximum video heightMaximum artifactProcessing timeout
economy1 credit720p750 MiB15 minutes
large5 credits1080p2 GiB30 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

CapabilitySupported now
Public single-video URLs across 1,000+ platformsYes
Embedded media and generic public web pagesYes, when the extractor finds usable media
MP4 video up to 720p or 1080pYes, subject to profile and source formats
M4A or 192 kbps MP3 audioYes

Async jobs, polling, cancellation, idempotency, and bounded retries

Yes
Private one-hour artifacts, signed URLs, HEAD, Range, and SHA-256Yes

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:

FieldRequiredValues and behavior
sourceUrlYesPublic HTTP or HTTPS URL, up to 4,096 characters
kindNo

video by default, or audio

profileNo

economy by default, or large

videoMaxHeightVideo only144–720 for economy; 144–1080 for large
audioFormatAudio only

m4a by default, or mp3

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 size
  • artifactExpiresAt: when the private artifact will be deleted
  • downloadUrl: a signed, temporary URL
  • downloadUrlExpiresAt: 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 statusTypical codeWhat to do
401unauthorizedReplace or re-enable the API key
402insufficient_creditsPurchase credits, then submit with a new key
409idempotency_conflictReuse the original body or generate a new key
413request_too_largeKeep the JSON body below 16 KiB
422invalid_requestCorrect the request fields or source URL
429too_many_requests

Wait for the Retry-After duration

503service_unavailableRetry 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.