A playlist is not one download job
The download worker is configured for one item rather than playlist expansion. Do not send a playlist URL and expect the endpoint to create a batch of per-video jobs.
The download endpoint creates one job for an individual video URL. It does not expand a playlist into a batch, so enumerate video URLs and submit them one at a time.
Use the shared API host unless the dashboard shows an account-specific hostname.
curl --get "https://p.savenow.to/ajax/download.php" \
--data-urlencode "url=https://www.youtube.com/watch?v=VIDEO_ID" \
--data "format=720" \
--data "apikey=YOUR_API_KEY"
The download worker is configured for one item rather than playlist expansion. Do not send a playlist URL and expect the endpoint to create a batch of per-video jobs.
Use a playlist listing method that you control, then pass each individual watch or Shorts URL to /ajax/download.php. Keep each returned job id so your app can show and retry items separately.
Create one job per video with a format and API key. Poll each id through /ajax/progress.php; below 1000 it is pending, and at 1000 a file is ready only when success is 1 or true and download_url is non-empty.
Each video request follows normal format and duration billing. Start requests at a rate your account and application can handle, and stop retries on terminal errors rather than resubmitting the same item blindly.
Resolve the playlist into individual video URLs before calling the download endpoint.
Store each video URL and returned id so the UI can show item-level progress, failures, and retries.
Poll existing job ids first. Create a new job only after deciding how the application handles a terminal failure.
One download request does not turn a playlist into many media jobs.
Each video uses the selected output format and its applicable duration pricing.
Send the dashboard API key with every create request and keep it out of browser code.
playlist URL
Not a batch
The download endpoint does not expand playlist URLs into a set of jobs.
video URL
Required per item
Send one individual YouTube watch or Shorts URL for each video.
format
Required
Select one output format for each job, such as 720 or mp3.
apikey
Required
Use the API key on the server when creating each job.
id
Per-job response
Track the id returned for each submitted video URL.
curl --get "https://p.savenow.to/ajax/download.php" --data-urlencode "url=https://www.youtube.com/watch?v=VIDEO_ID" --data "format=720" --data "apikey=YOUR_API_KEY"
const apiKey = process.env.VDA_API_KEY;
if (!apiKey) throw new Error('Set VDA_API_KEY on the server.');
const videoUrls = [
'https://www.youtube.com/watch?v=VIDEO_ID_1',
'https://www.youtube.com/watch?v=VIDEO_ID_2',
];
const jobs = [];
for (const url of videoUrls) {
const params = new URLSearchParams({ url, format: '720', apikey: apiKey });
const response = await fetch(`https://p.savenow.to/ajax/download.php?${params}`);
if (!response.ok) throw new Error(`Download request failed: ${response.status}`);
const job = await response.json();
if (!job.success || !job.id) throw new Error(job.message || 'A video job was not accepted.');
jobs.push({ url, id: job.id, progressUrl: job.progress_url });
}
console.log(jobs);
import os
import requests
video_urls = [
"https://www.youtube.com/watch?v=VIDEO_ID_1",
"https://www.youtube.com/watch?v=VIDEO_ID_2",
]
api_key = os.environ["VDA_API_KEY"]
jobs = []
for url in video_urls:
response = requests.get(
"https://p.savenow.to/ajax/download.php",
params={"url": url, "format": "720", "apikey": api_key},
timeout=30,
)
response.raise_for_status()
job = response.json()
if not job.get("success") or not job.get("id"):
raise RuntimeError(job.get("message") or "A video job was not accepted.")
jobs.append({"url": url, "id": job["id"], "progress_url": job.get("progress_url")})
print(jobs)
The download API receives individual video URLs. Resolve the playlist in your application before creating jobs.
Read the download API guideA playlist creates multiple billable requests when you submit its individual items. Estimate by selected format and video duration.
Review API pricingCreate jobs from a backend service so the API key is not exposed in browser code.
Get an API keyDownload YAML or JSON specs and inspect downloader, progress, and subtitle endpoints.
Read docsKeep button, card, widget, and REST paths reachable for existing users and migrations.
View resourcesNo. The downloader is configured for one item per request and does not expand a playlist into a batch.
List its individual video URLs in your application, then create one download job for each URL and track each returned id separately.
Do not use a playlist URL when you expect every item. Submit an individual watch or Shorts URL for each video instead.
Each video job follows the normal selected-format and duration pricing rules. Estimate the total from the individual items before processing a large playlist.