Paste the URL of one YouTube video.
YouTube Downloader
Download one authorized YouTube video or audio file to a folder you choose.
6 steps · runs code · uses 2 tools
What's new in version 1: Built and tested single-URL YouTube downloads with per-run video/audio selection, folder choice, safe URL handling, MP4 merging, and overwrite support.
What you provide
Osaurus asks for these each time the workflow runs.
Choose whether to save video or audio.
One of: video, audio
Choose where the downloaded file should be saved.
What it does
Every step in the order it runs. Code steps show their full source so you can read exactly what runs on your Mac.
Safely encode the URL and select the requested download branch.
No network access. · Times out after 30s
async function run(input, ctx) { const bytes = []; for (const ch of input.url.trim()) { const cp = ch.codePointAt(0); if (cp <= 0x7f) bytes.push(cp); else if (cp <= 0x7ff) bytes.push(0xc0 | (cp >> 6), 0x80 | (cp & 0x3f)); else if (cp <= 0xffff) bytes.push(0xe0 | (cp >> 12), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f)); else bytes.push(0xf0 | (cp >> 18), 0x80 | ((cp >> 12) & 0x3f), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f)); } const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; let out = ''; for (let i = 0; i < bytes.length; i += 3) { const a = bytes[i]; const b = i + 1 < bytes.length ? bytes[i + 1] : 0; const c = i + 2 < bytes.length ? bytes[i + 2] : 0; const n = (a << 16) | (b << 8) | c; out += alphabet[(n >> 18) & 63] + alphabet[(n >> 12) & 63]; out += i + 1 < bytes.length ? alphabet[(n >> 6) & 63] : '='; out += i + 2 < bytes.length ? alphabet[n & 63] : '='; } return { choice: input.choice, url_b64: out, overwrite: true }; }Data passed to this step
{ "url": "{{input.youtube_url}}", "choice": "{{input.download_type}}" }Download the best directly available MP4 video with audio.
Runs only when Prepare safe download reports
choice is "video".Data passed to this step
{ "command": "URL_B64='{{nodes.prepare.output.url_b64}}'; URL=$(printf '%s' \"$URL_B64\" | base64 -d); rm -f youtube-download.mp4 youtube-download.f*; yt-dlp --js-runtimes node --no-playlist --format 'bv*[ext=mp4]+ba[ext=m4a]/bv*+ba/b' --merge-output-format mp4 --output youtube-download.mp4 \"$URL\"" }Download the best directly available M4A audio stream.
Runs only when Prepare safe download reports
choice is "audio".Data passed to this step
{ "command": "URL_B64='{{nodes.prepare.output.url_b64}}'; URL=$(printf '%s' \"$URL_B64\" | base64 -d); rm -f youtube-download.m4a; yt-dlp --js-runtimes node --no-playlist --format 'bestaudio[ext=m4a]' --output youtube-download.m4a \"$URL\"" }Copy the completed MP4 file to the chosen folder.
Data passed to this step
{ "source": "youtube-download.mp4", "overwrite": "{{nodes.prepare.output.overwrite}}", "destination": "{{input.destination_folder}}/youtube-download.mp4" }Copy the completed M4A file to the chosen folder.
Data passed to this step
{ "source": "youtube-download.m4a", "overwrite": "{{nodes.prepare.output.overwrite}}", "destination": "{{input.destination_folder}}/youtube-download.m4a" }Return the path and type of the file that was saved.
No network access. · Times out after 30s
async function run(input, ctx) { const folder = input.folder.replace(/\/$/, ''); const filename = input.media_type === 'video' ? 'youtube-download.mp4' : 'youtube-download.m4a'; return { file_path: folder + '/' + filename, media_type: input.media_type, note: 'Download completed. Only save content you are authorized to download.' }; }Data passed to this step
{ "folder": "{{input.destination_folder}}", "media_type": "{{input.download_type}}" }
What it can access
Read from the workflow's steps, not only what the author declared. Osaurus shows this again before you add the workflow.
What you get back
note
file_path
One of: video, audio
Examples
Sample inputs the author included.
Download one YouTube audio file
{
"youtube_url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
"download_type": "audio",
"destination_folder": "tmp"
}Download one YouTube video
{
"youtube_url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
"download_type": "video",
"destination_folder": "tmp"
}The signed file
This is the exact template Osaurus imports. Its hash and signature were checked when it was uploaded.
Show template JSON (10.7 KB)
{
"id": "BC20B98D-1B93-4A74-A971-C8F77F56CABB",
"kind": "workflow",
"name": "YouTube Downloader",
"author": {
"name": "tpae",
"address": "0xc820da3Ce55C600A6282D2B21083Fe5Aa7E51F3D",
"signature": "27f68ec2c07bcd9c49624e8dd711ac25bfda95dab336965409cf91cc7bd48db50557742740b0c71c65c040aa4ecb0d3869569d548d623cb194600755d080114c1c"
},
"format": "osaurus.template",
"summary": "Download one authorized YouTube video or audio file to a folder you choose.",
"version": 1,
"workflow": {
"edges": [
{
"to": "download_video",
"from": "prepare",
"when": {
"op": "equals",
"path": "choice",
"value": "video"
}
},
{
"to": "download_audio",
"from": "prepare",
"when": {
"op": "equals",
"path": "choice",
"value": "audio"
}
},
{
"to": "copy_video",
"from": "download_video"
},
{
"to": "copy_audio",
"from": "download_audio"
},
{
"to": "finish",
"from": "copy_video"
},
{
"to": "finish",
"from": "copy_audio"
}
],
"nodes": [
{
"id": "prepare",
"code": {
"source": "async function run(input, ctx) {\n const bytes = [];\n for (const ch of input.url.trim()) {\n const cp = ch.codePointAt(0);\n if (cp <= 0x7f) bytes.push(cp);\n else if (cp <= 0x7ff) bytes.push(0xc0 | (cp >> 6), 0x80 | (cp & 0x3f));\n else if (cp <= 0xffff) bytes.push(0xe0 | (cp >> 12), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f));\n else bytes.push(0xf0 | (cp >> 18), 0x80 | ((cp >> 12) & 0x3f), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f));\n }\n const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n let out = '';\n for (let i = 0; i < bytes.length; i += 3) {\n const a = bytes[i];\n const b = i + 1 < bytes.length ? bytes[i + 1] : 0;\n const c = i + 2 < bytes.length ? bytes[i + 2] : 0;\n const n = (a << 16) | (b << 8) | c;\n out += alphabet[(n >> 18) & 63] + alphabet[(n >> 12) & 63];\n out += i + 1 < bytes.length ? alphabet[(n >> 6) & 63] : '=';\n out += i + 2 < bytes.length ? alphabet[n & 63] : '=';\n }\n return { choice: input.choice, url_b64: out, overwrite: true };\n}",
"network": [],
"secrets": [],
"timeout": 30
},
"kind": "code",
"name": "Prepare safe download",
"input": {
"url": "{{input.youtube_url}}",
"choice": "{{input.download_type}}"
},
"retry": {
"max_attempts": 1,
"backoff_seconds": 1
},
"intent": "Safely encode the URL and select the requested download branch.",
"timeout": 120,
"output_schema": {
"type": "object",
"required": [
"choice",
"url_b64",
"overwrite"
],
"properties": {
"choice": {
"enum": [
"video",
"audio"
],
"type": "string"
},
"url_b64": {
"type": "string"
},
"overwrite": {
"type": "boolean"
}
},
"additionalProperties": false
}
},
{
"id": "download_video",
"kind": "tool",
"name": "Download video",
"tool": {
"name": "shell_run"
},
"input": {
"command": "URL_B64='{{nodes.prepare.output.url_b64}}'; URL=$(printf '%s' \"$URL_B64\" | base64 -d); rm -f youtube-download.mp4 youtube-download.f*; yt-dlp --js-runtimes node --no-playlist --format 'bv*[ext=mp4]+ba[ext=m4a]/bv*+ba/b' --merge-output-format mp4 --output youtube-download.mp4 \"$URL\""
},
"retry": {
"max_attempts": 2,
"backoff_seconds": 2
},
"intent": "Download the best directly available MP4 video with audio.",
"timeout": 300,
"output_schema": {}
},
{
"id": "download_audio",
"kind": "tool",
"name": "Download audio",
"tool": {
"name": "shell_run"
},
"input": {
"command": "URL_B64='{{nodes.prepare.output.url_b64}}'; URL=$(printf '%s' \"$URL_B64\" | base64 -d); rm -f youtube-download.m4a; yt-dlp --js-runtimes node --no-playlist --format 'bestaudio[ext=m4a]' --output youtube-download.m4a \"$URL\""
},
"retry": {
"max_attempts": 2,
"backoff_seconds": 2
},
"intent": "Download the best directly available M4A audio stream.",
"timeout": 180,
"output_schema": {}
},
{
"id": "copy_video",
"kind": "tool",
"name": "Save video",
"tool": {
"name": "file_copy"
},
"input": {
"source": "youtube-download.mp4",
"overwrite": "{{nodes.prepare.output.overwrite}}",
"destination": "{{input.destination_folder}}/youtube-download.mp4"
},
"retry": {
"max_attempts": 1,
"backoff_seconds": 1
},
"intent": "Copy the completed MP4 file to the chosen folder.",
"timeout": 120,
"output_schema": {}
},
{
"id": "copy_audio",
"kind": "tool",
"name": "Save audio",
"tool": {
"name": "file_copy"
},
"input": {
"source": "youtube-download.m4a",
"overwrite": "{{nodes.prepare.output.overwrite}}",
"destination": "{{input.destination_folder}}/youtube-download.m4a"
},
"retry": {
"max_attempts": 1,
"backoff_seconds": 1
},
"intent": "Copy the completed M4A file to the chosen folder.",
"timeout": 120,
"output_schema": {}
},
{
"id": "finish",
"code": {
"source": "async function run(input, ctx) {\n const folder = input.folder.replace(/\\/$/, '');\n const filename = input.media_type === 'video' ? 'youtube-download.mp4' : 'youtube-download.m4a';\n return {\n file_path: folder + '/' + filename,\n media_type: input.media_type,\n note: 'Download completed. Only save content you are authorized to download.'\n };\n}",
"network": [],
"secrets": [],
"timeout": 30
},
"kind": "code",
"name": "Report saved file",
"input": {
"folder": "{{input.destination_folder}}",
"media_type": "{{input.download_type}}"
},
"retry": {
"max_attempts": 1,
"backoff_seconds": 1
},
"intent": "Return the path and type of the file that was saved.",
"timeout": 120,
"output_schema": {
"type": "object",
"required": [
"file_path",
"media_type",
"note"
],
"properties": {
"note": {
"type": "string"
},
"file_path": {
"type": "string"
},
"media_type": {
"enum": [
"video",
"audio"
],
"type": "string"
}
},
"additionalProperties": false
}
}
],
"output": {
"note": "{{nodes.finish.output.note}}",
"file_path": "{{nodes.finish.output.file_path}}",
"media_type": "{{nodes.finish.output.media_type}}"
},
"secrets": [],
"examples": [
{
"name": "Download one YouTube audio file",
"input": {
"youtube_url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
"download_type": "audio",
"destination_folder": "tmp"
}
},
{
"name": "Download one YouTube video",
"input": {
"youtube_url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
"download_type": "video",
"destination_folder": "tmp"
}
}
],
"model_slots": [],
"dependencies": [
{
"manager": "pip",
"binaries": [
"yt-dlp"
],
"packages": [
"yt-dlp"
]
},
{
"manager": "apk",
"binaries": [
"ffmpeg"
],
"packages": [
"ffmpeg"
]
}
],
"input_schema": {
"type": "object",
"x-order": [
"youtube_url",
"download_type",
"destination_folder"
],
"required": [
"youtube_url",
"download_type",
"destination_folder"
],
"properties": {
"youtube_url": {
"type": "string",
"title": "YouTube link",
"description": "Paste the URL of one YouTube video."
},
"download_type": {
"enum": [
"video",
"audio"
],
"type": "string",
"title": "Download type",
"description": "Choose whether to save video or audio."
},
"destination_folder": {
"type": "string",
"title": "Destination folder",
"format": "folder",
"description": "Choose where the downloaded file should be saved."
}
},
"additionalProperties": false
},
"output_schema": {
"type": "object",
"required": [
"file_path",
"media_type",
"note"
],
"properties": {
"note": {
"type": "string",
"title": "Result"
},
"file_path": {
"type": "string",
"title": "Saved file"
},
"media_type": {
"enum": [
"video",
"audio"
],
"type": "string",
"title": "Download type"
}
},
"additionalProperties": false
},
"requirement_notes": {}
},
"changelog": "Built and tested single-URL YouTube downloads with per-run video/audio selection, folder choice, safe URL handling, MP4 merging, and overwrite support.",
"created_at": "2026-10-07T19:23:31Z",
"content_hash": "sha256:70a717b3d59e59d8bfd5652543db60bcf6cbe46e3a80f8ffc0e6dcabf7dbb2b0",
"requirements": {
"notes": {},
"tools": [
"shell_run",
"file_copy"
],
"models": [],
"network": [],
"plugins": [],
"secrets": [],
"knowledge": [],
"mcp_servers": [],
"permissions": [],
"dependencies": [
{
"manager": "pip",
"binaries": [
"yt-dlp"
],
"packages": [
"yt-dlp"
]
},
{
"manager": "apk",
"binaries": [
"ffmpeg"
],
"packages": [
"ffmpeg"
]
}
]
},
"format_version": 1,
"available_to_orchestrator": true
}