Table of Contents
n8n youtube automation
n8n youtube automation, Most YouTube automation tutorials rely on paid AI APIs like ChatGPT or Gemini. While they work, they come with costs, rate limits, privacy concerns, and internet dependency.
What if you could:
• Generate YouTube titles, descriptions, and tags
• Upload videos automatically
• Run everything locally
• Use zero API keys
• Pay nothing
In this article on n8n youtube automation, we’ll build exactly that using n8n and Ollama, powered by a lightweight local LLM.
This setup is ideal for developers, YouTubers, and indie creators who want full control.
What Is n8n?
n8n is an open-source workflow automation tool, similar to Zapier, but:
• Self-hosted
• Developer-friendly
• No per-task pricing
• Full JavaScript support
It allows you to visually connect APIs, logic, files, and platforms like YouTube.Why automate YouTube uploads?
What Is Ollama?
Ollama lets you run Large Language Models (LLMs) directly on your machine.
Why Ollama?
• No internet required
• No API keys
• Runs on Mac, Windows, Linux
• Supports models like Phi-3, LLaMA, Mistral
In this workflow, Ollama acts as your local ChatGPT replacement.
Running Ollama with Docker
Why host.docker.internal?
When n8n is also running inside Docker, it cannot access localhost directly.
Instead, we use:
http://host.docker.internal:11434
This is a very common Docker networking issue, and many developers face issue for this specifically.
Calling the Ollama HTTP API from n8n
In n8n, add an HTTP Request node.
Endpoint
POST http://host.docker.internal:11434/api/generate
Request Body (JSON)
{
"model": "phi3:mini",
"prompt": "Generate an attractive YouTube title and description for uploading a video on Supabase backend integration.",
"stream": false
}
Important Notes
• stream: false is mandatory for automation
• phi3:mini is lightweight and fast
• Works perfectly on Mac M1 with 8GB RAM
Filter and Clean API Output Using JavaScript in n8n
// Access input data from previous node (HTTP Request)
const inputData = $input.all();
function extractYouTubeData(inputData) {
if (!Array.isArray(inputData) || inputData.length === 0) {
return { title: "", description: "", tags: [] };
}
// Combine all responses
let fullText = "";
for (const item of inputData) {
const res = item.json?.response || item.json?.data || "";
if (res) fullText += res + "\n";
}
let title = "";
let description = "";
let tags = [];
// 1. Try to parse JSON block if available
const jsonMatch = fullText.match(/```(?:json)?\s*([\s\S]*?)```/i);
if (jsonMatch) {
try {
const parsed = JSON.parse(jsonMatch[1]);
title = parsed.title || "";
description = parsed.description || "";
tags = parsed.tags || [];
} catch (e) {
console.error("JSON parse error:", e);
}
}
// 2. Fallback: Extract Title: ... and Description: ...
if (!title) {
const titleMatch = fullText.match(/Title:\s*["']?(.+?)["']?\s*(?:\n|$)/i);
if (titleMatch) title = titleMatch[1].trim();
}
if (!description) {
const descMatch = fullText.match(/Description:\s*([\s\S]+)/i);
if (descMatch) description = descMatch[1].trim();
}
// 3. Optional: Auto-generate tags from title if no tags
if (tags.length === 0 && title) {
tags = title
.split(/\s+/)
.filter(word => word.length > 2)
.map(word => word.replace(/[^a-zA-Z0-9]/g, ""))
.slice(0, 10); // limit to 10 tags
}
return { title, description, tags };
}
const result = extractYouTubeData(inputData);
return [result];
Why this Code Node Is Needed in n8n
When you call a local LLM (like Ollama), the response often contains:
• Extra metadata
• Tokens
• Streaming-related fields
• Nested objects you don’t want to send to YouTube
Platforms like YouTube expect clean, minimal fields:
• title
• description
• tags
This Code node acts as a filter + transformer layer.
Using Dynamic Expressions in the YouTube Node (n8n)
In the YouTube Upload node, you should map the fields like this:
Title field
{{ $json.title }}
Description field
{{ $json.description }}
Tags field
{{ $json.tags }}
Finally we Automated flow
Now it’s time to have a look through the n8n youtube automation tutorial.