Automating YouTube-to-Instagram with AWS, Flask, Meta API, and n8n — The Ultimate Zero-Cost Automation Blueprint

Published on July 8, 2025

Why Pay for Automation Tools When You Can Build a Beast for Free?

Tired of shelling out cash for tools that post your YouTube videos to Instagram? Want instant, hands-free cross-posting magic the moment you hit “Upload”? This is your cheat code.

Welcome to the Ultimate Guide for Hands-Free Hustlers.

We’re going to build an automation powerhouse that watches your YouTube channel and immediately posts your latest videos to Instagram — all without lifting a finger. Best part? It’s all free.

🎯 The Mission: One Upload to Rule Them All

You upload to YouTube. Like clockwork, Instagram reacts and shares your content with the world. Zero effort. Maximum presence.


🧰 Tools You’ll Need (a.k.a. Your Tech Arsenal)

  • AWS EC2 instance (Amazon Linux 2)

  • Python 3 & Flask

  • Meta Developer App + Instagram Creator Account

  • YouTube channel

  • n8n (for optional GUI automation)

  • Your brain + basic terminal skills


Subscribe now

🏗️ Step 1: Spinning Up Your AWS EC2 Server

  1. Log into AWS EC2 and launch a t2.micro instance with Amazon Linux 2.

  2. Generate and download your key pair (.pem file for Mac/Linux or .ppk for Windows/PuTTY).

  3. Configure the Security Group to allow:

  • Port 22 (SSH)

  • Port 5000 (Flask Webhook)

SSH into your instance:

ssh -i your-key.pem ec2-user@your-ec2-ip

Update packages and install dependencies:

sudo yum update -y
sudo yum install python3 git -y
python3 -m venv venv
source venv/bin/activate
pip install flask xmltodict requests

🧪 Step 2: Your Flask App — The Webhook Hero

Create a file called webhook.py:

nano webhook.py

Paste this code:

from flask import Flask, request
import xmltodict
import requests
import time

CHANNEL_ID = "YouTube_UC_channel_ID"
IG_USER_ID = "your-instagram-user-id"
PAGE_ACCESS_TOKEN = "your-long-lived-access-token"

app = Flask(__name__)

def post_to_instagram(video_id, title, thumb_url):
    caption = f"🪓 NEW VIDEO: {title} 🔥\n▶️ https://youtu.be/{video_id}"
    create_url = f"https://graph.facebook.com/v15.0/{IG_USER_ID}/media"
    payload = {
        "image_url": thumb_url,
        "caption": caption,
        "access_token": PAGE_ACCESS_TOKEN
    }
    resp = requests.post(create_url, data=payload)
    resp.raise_for_status()
    creation_id = resp.json().get("id")

    time.sleep(2)
    publish_url = f"https://graph.facebook.com/v15.0/{IG_USER_ID}/media_publish"
    publish_payload = {
        "creation_id": creation_id,
        "access_token": PAGE_ACCESS_TOKEN
    }
    resp2 = requests.post(publish_url, data=publish_payload)
    resp2.raise_for_status()
    return resp2.json()

@app.route("/webhook", methods=["GET", "POST"])
def webhook():
    if request.method == "GET":
        return request.args.get("hub.challenge", ""), 200

    doc = xmltodict.parse(request.data)
    entries = doc.get("feed", {}).get("entry", [])
    if not isinstance(entries, list):
        entries = [entries]

    for e in entries:
        vid = e.get("yt:videoId")
        title = e.get("title")
        thumb = e.get("media:group", {}).get("media:thumbnail", {}).get("@url")
        try:
            result = post_to_instagram(vid, title, thumb)
            app.logger.info("Posted to IG: %s", result)
        except Exception as err:
            app.logger.error("IG post failed: %s", err)

    return "", 204

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

Run your webhook:

python3 webhook.py

📡 Step 3: Subscribing to YouTube Upload Events

Use WebSub (PubSubHubbub) to get notified of new videos:

In PowerShell (update topic —YouTube_UC_ID) :

Invoke-RestMethod `
  -Uri 'https://pubsubhubbub.appspot.com/subscribe' `
  -Method Post `
  -Body @{
    'hub.mode'     = 'subscribe'
    'hub.topic'    = 'https://www.youtube.com/xml/feeds/videos.xml?channel_id=YouTube_UC_ID'
    'hub.callback' = 'http://your-ec2-ip:5000/webhook'
  }

Look for a 202 Accepted response — it means YouTube accepted the subscription.


🔑 Step 4: Instagram Graph API Setup (Meta)

  1. Go to Meta for Developers

  2. Create a new app (type: “For Everything Else”)

  3. Add:

  • Instagram Graph API

  • Facebook Pages API

4. Link a Facebook Page to your Instagram Creator account

5. Use Graph Explorer to get a short-lived User Access Token

6. Exchange for a long-lived token:

curl -G \
  "https://graph.facebook.com/v15.0/oauth/access_token" \
  --data-urlencode "grant_type=fb_exchange_token" \
  --data-urlencode "client_id=YOUR_APP_ID" \
  --data-urlencode "client_secret=YOUR_APP_SECRET" \
  --data-urlencode "fb_exchange_token=YOUR_SHORT_LIVED_USER_TOKEN"

7. Fetch your Page and Instagram user ID:

$response = Invoke-RestMethod -Uri "https://graph.facebook.com/v15.0/me/accounts?access_token=LONG_LIVED_USER_TOKEN" -Method Get
$response.data

✅ Step 5: Final Test Run

There are two ways to test the setup without waiting for a real video upload:

🔁 Option 1: Manual Trigger with Sample Data

Create a file called sample.xml with a fake YouTube video payload (be sure to add your YouTube_Video_ID number of a recently published video):


  
    "YouTube_Video_ID"
    
    
      https://i.ytimg.com/vi/<>/hqdefault.jpg"/>
    
  

Then use curl or Postman to simulate the webhook:

curl -X POST http://your-ec2-ip:5000/webhook \
  -H "Content-Type: application/atom+xml" \
  --data-binary @sample.xml

Check Flask logs for success or errors.

🧪 Option 2: Direct Function Call

You can also bypass Flask and run (be sure to add your YouTube_Video_ID number of a recently published video:

post_to_instagram("<>", "Test Video Title", "https://i.ytimg.com/vi/<>/hqdefault.jpg")

To confirm everything’s working.

If nothing shows up on Instagram, check:

  • Your long-lived token is still valid

  • The image URL is publicly accessible

  • Your IG user ID matches your Creator account

🎛️ BONUS: Add a Visual Automation Layer with n8n

Want a slick dashboard to manage or trigger this logic? Use n8n.io!

  1. Spin up n8n (local or cloud)

  2. Create a new workflow:

  • HTTP Trigger listens for PubSub callbacks

  • HTTP Request node forwards it to your Flask endpoint

This way, you don’t need to expose Flask directly if you prefer proxying it.

🏁 Wrap-Up

You just:

  • Hosted a Flask webhook

  • Subscribed to YouTube’s real-time video push system

  • Authenticated with Meta’s API

  • Built a full pipeline that posts your latest videos to Instagram — automatically

All without paying a dime for automation platforms. This is your DIY social growth engine.

Automation isn’t just for pros — it’s for builders like you.

You now own it 💥