AutomationFlowsSocial Media › Batch Upload Instagram Reels to Youtube with Scheduled Delays

Batch Upload Instagram Reels to Youtube with Scheduled Delays

ByLucio @misterfunable on n8n.io

Automatically upload your Instagram videos to YouTube with configurable time gaps between each upload, using n8n Tables for deduplication. Fetches recent Instagram posts via the Meta Graph API and filters to only video content (VIDEO/REELS) Checks each video against an n8n Table…

Cron / scheduled trigger★★★★☆ complexity19 nodesHTTP RequestData TableYouTube
Social Media Trigger: Cron / scheduled Nodes: 19 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #12773 — we link there as the canonical source.

This workflow follows the Datatable → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "nodes": [
    {
      "id": "f56b36cc-07c2-4b30-9ccd-14cbf024e24e",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        480,
        512
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 0 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a3db91a5-2081-4652-b10d-2eae58b67fc1",
      "name": "Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        704,
        512
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={\n  \"includeSourceLink\": true,\n  \"waitTimeoutSeconds\": 15,\n  \"maxTitleLength\": 100,\n  \"categoryId\": \"22\",\n  \"privacyStatus\": \"public\",\n  \"notifySubscribers\": false,\n  \"defaultLanguage\": \"en\",\n  \"ageRestricted\": false\n}"
      },
      "typeVersion": 3.4
    },
    {
      "id": "cd666bdb-afb2-4581-94fe-1a890594e15c",
      "name": "Fetch Instagram Posts",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        976,
        512
      ],
      "parameters": {
        "url": "https://graph.instagram.com/me/media",
        "options": {},
        "jsonQuery": "={\n  \"fields\": \"id,caption,media_url,media_type,timestamp,permalink\",\n  \"limit\": \"25\"\n}",
        "sendQuery": true,
        "specifyQuery": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "f8823bb8-e746-4afc-9e1f-82467e790fcf",
      "name": "Split Out",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1200,
        512
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data"
      },
      "typeVersion": 1
    },
    {
      "id": "25e84b3b-2ba8-406c-af40-db775c423eb5",
      "name": "Filter Videos Only",
      "type": "n8n-nodes-base.filter",
      "position": [
        1424,
        512
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "video-check",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.media_type }}",
              "rightValue": "VIDEO"
            },
            {
              "id": "reels-check",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.media_type }}",
              "rightValue": "REELS"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "79ca0127-80ec-4783-beb6-751640786cc0",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1648,
        512
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "8fa6eac8-accd-42bf-8d51-645a37e06bff",
      "name": "Check If Already Uploaded",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        1872,
        576
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "postId",
              "keyValue": "={{ $json.id }}"
            }
          ]
        },
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "oOxou5oOQXuS4cQY",
          "cachedResultUrl": "/projects/vZdjtqHcrLoO32Ib/datatables/oOxou5oOQXuS4cQY",
          "cachedResultName": "Instagram To YouTube"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "49f0159a-e36a-4a31-a708-5fe93638707f",
      "name": "If Not Uploaded Yet",
      "type": "n8n-nodes-base.if",
      "position": [
        2096,
        576
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "eab5894a-31d7-43f4-8866-104c416eed3f",
              "operator": {
                "type": "string",
                "operation": "notExists",
                "singleValue": true
              },
              "leftValue": "={{ $json.postId }}",
              "rightValue": ""
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "d4cf02f7-c2c3-469a-a37d-5f699b14a7c9",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        2320,
        512
      ],
      "parameters": {
        "amount": "={{ $('Configuration').item.json.waitTimeoutSeconds }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "a392de42-c87f-4ed9-8987-25c671cbc7e8",
      "name": "Process Title and Tags",
      "type": "n8n-nodes-base.code",
      "position": [
        2544,
        512
      ],
      "parameters": {
        "jsCode": "// Get configuration from the Configuration node\nconst config = $('Configuration').first().json;\nconst includeSourceLink = config.includeSourceLink;\nconst MAX_TITLE_LENGTH = config.maxTitleLength || 100;\n\n// Get the post data from the Loop Over Items node\nconst caption = $('Loop Over Items').item.json.caption || '';\nconst postId = $('Loop Over Items').item.json.id;\nconst mediaUrl = $('Loop Over Items').item.json.media_url;\nconst permalink = $('Loop Over Items').item.json.permalink;\n\n// Extract hashtags\nconst hashtagRegex = /#[\\w\\u00C0-\\u024F]+/gu;\nconst hashtags = caption.match(hashtagRegex) || [];\n\n// Get text before first hashtag\nconst firstHashtagIndex = caption.indexOf('#');\nlet textBeforeHashtags = firstHashtagIndex === -1 \n  ? caption.trim() \n  : caption.substring(0, firstHashtagIndex).trim();\n\n// Build title\nlet title = textBeforeHashtags;\n\n// If no text before hashtags, use first hashtag\nif (!title && hashtags.length > 0) {\n  title = hashtags[0].replace('#', '');\n}\n\n// If still no title, use generic\nif (!title) {\n  title = 'Instagram Video';\n}\n\n// Smart truncation at word boundary\nif (title.length > MAX_TITLE_LENGTH) {\n  title = title.substring(0, MAX_TITLE_LENGTH);\n  const lastSpace = title.lastIndexOf(' ');\n  if (lastSpace > MAX_TITLE_LENGTH * 0.6) {\n    title = title.substring(0, lastSpace);\n  }\n  title = title.trim() + '...';\n}\n\n// Build description - conditionally include source link\nlet description = caption;\n\nif (includeSourceLink) {\n  description += `\\n\\n---\\nOriginally posted on Instagram: ${permalink}`;\n}\n\n// Extract tags for YouTube (without # symbol, max 10)\nconst tags = hashtags\n  .map(h => h.replace('#', ''))\n  .filter(t => t.length > 1 && t.length <= 30)\n  .slice(0, 10);\n\n// Return processed data\nreturn [{\n  json: {\n    postId: postId,\n    title: title,\n    description: description,\n    tags: tags,\n    mediaUrl: mediaUrl,\n    originalCaption: caption,\n    hashtagCount: hashtags.length,\n    sourceLinkIncluded: includeSourceLink\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "4b1118e5-8b2e-4f1e-82e7-8d3dad1918aa",
      "name": "Download Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2768,
        512
      ],
      "parameters": {
        "url": "={{ $json.mediaUrl }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "b7f81c01-978c-48b0-8b53-0f71d610fd13",
      "name": "Upload to YouTube",
      "type": "n8n-nodes-base.youTube",
      "position": [
        2992,
        512
      ],
      "parameters": {
        "title": "={{ $('Process Title and Tags').item.json.title }}",
        "options": {
          "tags": "={{ $('Process Title and Tags').item.json.tags.join(',') }}",
          "license": "youtube",
          "embeddable": true,
          "description": "={{ $('Process Title and Tags').item.json.description }}",
          "privacyStatus": "={{ $('Configuration').item.json.privacyStatus }}",
          "defaultLanguage": "={{ $('Configuration').item.json.defaultLanguage }}",
          "notifySubscribers": "={{ $('Configuration').item.json.notifySubscribers }}",
          "publicStatsViewable": true,
          "selfDeclaredMadeForKids": false
        },
        "resource": "video",
        "operation": "upload",
        "categoryId": "={{ $('Configuration').item.json.categoryId }}",
        "regionCode": "US"
      },
      "credentials": {
        "youTubeOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "72339ade-f7d9-4950-8946-6f63192625f3",
      "name": "Save Upload Record",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        3216,
        512
      ],
      "parameters": {
        "columns": {
          "value": {
            "postId": "={{ $('Process Title and Tags').item.json.postId }}",
            "youtubeId": "={{ $json.id }}"
          },
          "schema": [
            {
              "id": "postId",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "postId",
              "defaultMatch": false
            },
            {
              "id": "youtubeId",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "youtubeId",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "postId"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "oOxou5oOQXuS4cQY",
          "cachedResultUrl": "/projects/vZdjtqHcrLoO32Ib/datatables/oOxou5oOQXuS4cQY",
          "cachedResultName": "Instagram To YouTube"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f99eaf5e-218f-4121-8711-e88de0b65983",
      "name": "Done",
      "type": "n8n-nodes-base.set",
      "position": [
        1648,
        320
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ffd3b7ab-4ac6-4c71-8ee1-a6c93732a701",
              "name": "status",
              "type": "string",
              "value": "Workflow completed"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "78ebe9fc-71af-4285-ba65-63029674a12a",
      "name": "Sticky Note - Instructions",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -256,
        96
      ],
      "parameters": {
        "width": 678,
        "height": 1104,
        "content": "## Instagram to YouTube Uploader\n\nAutomatically upload Instagram videos to YouTube with scheduled intervals.\n\n### Why This Template?\nThis workflow posts videos at a set time, then progressively uploads remaining content with configurable gaps between each upload. It's a simpler alternative to managing a spreadsheet-based publishing queue - all configuration lives in one node.\n\n### Configuration Options\nEdit the **Configuration** node:\n\n```json\n{\n  \"includeSourceLink\": true,    // Instagram link in description\n  \"waitTimeoutSeconds\": 900,    // Gap between uploads (seconds)\n  \"maxTitleLength\": 100,        // Max title length\n  \"categoryId\": \"24\",           // YouTube category\n  \"privacyStatus\": \"public\",    // public/private/unlisted\n  \"notifySubscribers\": false,   // Notify on upload\n  \"defaultLanguage\": \"en\",      // Video language\n  \"ageRestricted\": false        // 18+ content flag\n}\n```\n\n### Key Settings Explained\n- **includeSourceLink**: Set `false` for unverified accounts that can't add external links\n- **waitTimeoutSeconds**: Gap between uploads (900 = 15 min)\n- **ageRestricted**: Set `true` for 18+ content\n\n### Features\n- Video-only filter (skips images)\n- Hashtag to YouTube tags extraction\n- Deduplication via Data Table\n- COPPA compliance options\n\n### Setup\n1. Edit **Configuration** node\n2. Set **Bearer Auth** in **Fetch Instagram Posts**\n3. Create Data Table: `postId`, `youtubeId`\n4. Set **YouTube OAuth2** in **Upload to YouTube**\n\n### Category IDs\n| ID | Category |\n|----|----------|\n| 22 | People & Blogs |\n| 24 | Entertainment |\n| 20 | Gaming |\n| 10 | Music |"
      },
      "typeVersion": 1
    },
    {
      "id": "f37d44ef-5e72-4562-b30b-92f9c07e05c1",
      "name": "Sticky Note - Config",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        640,
        432
      ],
      "parameters": {
        "color": 5,
        "width": 256,
        "height": 224,
        "content": "## Configuration"
      },
      "typeVersion": 1
    },
    {
      "id": "ce3781f6-19f2-41a7-b214-aababc076914",
      "name": "Sticky Note - Fetch",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        944,
        432
      ],
      "parameters": {
        "color": 6,
        "width": 500,
        "height": 304,
        "content": "## Fetch & Filter Videos\n"
      },
      "typeVersion": 1
    },
    {
      "id": "08766e8e-9bcf-4b98-a482-a3475d3fa16f",
      "name": "Sticky Note - Check",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1840,
        432
      ],
      "parameters": {
        "color": 7,
        "width": 388,
        "height": 384,
        "content": "## Deduplication"
      },
      "typeVersion": 1
    },
    {
      "id": "0f1a89af-347a-41c2-8037-7678d2c3600d",
      "name": "Sticky Note - Upload",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2512,
        432
      ],
      "parameters": {
        "color": 3,
        "width": 740,
        "height": 304,
        "content": "## Process & Upload"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Wait": {
      "main": [
        [
          {
            "node": "Process Title and Tags",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "Filter Videos Only",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configuration": {
      "main": [
        [
          {
            "node": "Fetch Instagram Posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Video": {
      "main": [
        [
          {
            "node": "Upload to YouTube",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Done",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Check If Already Uploaded",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload to YouTube": {
      "main": [
        [
          {
            "node": "Save Upload Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Videos Only": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Upload Record": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Not Uploaded Yet": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Instagram Posts": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Title and Tags": {
      "main": [
        [
          {
            "node": "Download Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If Already Uploaded": {
      "main": [
        [
          {
            "node": "If Not Uploaded Yet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Automatically upload your Instagram videos to YouTube with configurable time gaps between each upload, using n8n Tables for deduplication. Fetches recent Instagram posts via the Meta Graph API and filters to only video content (VIDEO/REELS) Checks each video against an n8n Table…

Source: https://n8n.io/workflows/12773/ — original creator credit. Request a take-down →

More Social Media workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Social Media

📺 Full walkthrough video: https://youtu.be/Me4d4BILvHk

Gmail, Data Table, HTTP Request
Social Media

Are you a cord-cutter? Do you find yourself looking through the many titles of videos uploaded to Youtube, just to find the ones you want to watch? Even when you subscribe to the channels you like, do

Google Sheets, HTTP Request, YouTube +1
Social Media

YouTube Shorts Otomasyonu - Haftalık Eğlenceli Video. Uses httpRequest, executeCommand, youTube. Scheduled trigger; 15 nodes.

HTTP Request, Execute Command, YouTube
Social Media

Meta long-lived user tokens typically expire after ~60 days. If a token expires, any workflows that rely on it start failing. Manual renewal is easy to forget and time consuming. This template monitor

Data Table, HTTP Request
Social Media

This n8n template acts as your automated social media data analyst. Instead of manually checking your analytics across different dashboards every week, this workflow scrapes your latest stats, calcula

HTTP Request, YouTube, Airtable +3