AutomationFlowsSocial Media › Publish Youtube Shorts to Tiktok with Rss, Rapidapi and Tiktok API

Publish Youtube Shorts to Tiktok with Rss, Rapidapi and Tiktok API

BySalman Mehboob @salmanmehboob on n8n.io

This workflow polls a YouTube Shorts playlist RSS feed, deduplicates videos using an n8n Data Table, downloads each new Short via the YouTube Media Downloader API (RapidAPI), and uploads it to TikTok using the TikTok Content Posting API in either draft or direct publish mode.…

Event trigger★★★★☆ complexity21 nodesRss Feed Read TriggerData TableHTTP Request
Social Media Trigger: Event Nodes: 21 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #16171 — 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
{
  "id": "JLeTvGPtNfssLeuu",
  "name": "Auto-Publish YouTube Shorts to TikTok",
  "tags": [],
  "nodes": [
    {
      "id": "a08fcaa2-751e-4a68-b660-eea19724ea5b",
      "name": "RSS Feed Trigger",
      "type": "n8n-nodes-base.rssFeedReadTrigger",
      "position": [
        0,
        -112
      ],
      "parameters": {
        "feedUrl": "https://www.youtube.com/feeds/videos.xml?playlist_id=YOUR_PLAYLIST_ID",
        "pollTimes": {
          "item": [
            {
              "mode": "everyHour"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3c2f878b-cac0-49d6-961b-c8d4a24b107b",
      "name": "If row does not exist",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        224,
        -112
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "short_id",
              "keyValue": "={{ $json.id }}"
            }
          ]
        },
        "operation": "rowNotExists",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "ty9zGN4MhSl47Kl9",
          "cachedResultUrl": "/projects/UixkftX5yd6UCJ81/datatables/ty9zGN4MhSl47Kl9",
          "cachedResultName": "YouTube Shorts"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "4c0eae6e-81fb-4582-9bf4-18c64c34452f",
      "name": "Add Row",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        448,
        -112
      ],
      "parameters": {
        "columns": {
          "value": {
            "short_id": "={{ $json.id }}"
          },
          "schema": [
            {
              "id": "short_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "short_id",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "short_id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "ty9zGN4MhSl47Kl9",
          "cachedResultUrl": "/projects/UixkftX5yd6UCJ81/datatables/ty9zGN4MhSl47Kl9",
          "cachedResultName": "YouTube Shorts"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "ddf38cee-3cb8-4c53-aa54-94582566c206",
      "name": "Arrange Data",
      "type": "n8n-nodes-base.set",
      "position": [
        672,
        -112
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "92b71f91-81ed-4efd-b79b-2415471b3daf",
              "name": "title",
              "type": "string",
              "value": "={{ $('If row does not exist').item.json.title }}"
            },
            {
              "id": "66ab280c-f3ef-468d-9c6d-2ef55eea378a",
              "name": "link",
              "type": "string",
              "value": "={{ $('If row does not exist').item.json.link }}"
            },
            {
              "id": "53fa8fd0-cf8f-4083-b58e-ba70465245bc",
              "name": "author",
              "type": "string",
              "value": "={{ $('If row does not exist').item.json.author }}"
            },
            {
              "id": "ab85ed29-5785-4eab-bcff-53763d7b29c5",
              "name": "pubDate",
              "type": "string",
              "value": "={{ $('If row does not exist').item.json.isoDate }}"
            },
            {
              "id": "2cd89822-38ea-43a4-a7ee-d18303c0b7a5",
              "name": "id",
              "type": "string",
              "value": "={{ $json.short_id }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "06b35fdb-8e23-4cdd-bda1-524464e3a05c",
      "name": "Get Download Link",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        896,
        -112
      ],
      "parameters": {
        "url": "https://youtube-media-downloader.p.rapidapi.com/v2/video/details",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "videoId",
              "value": "={{ $('Arrange Data').item.json.id.replace('yt:video:', '') }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "x-rapidapi-host",
              "value": "youtube-media-downloader.p.rapidapi.com"
            },
            {
              "name": "x-rapidapi-key",
              "value": "YOUR_RAPIDAPI_KEY"
            }
          ]
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "1ce2ebfd-3395-4e77-bde4-3c641abd22d2",
      "name": "Download Link Parser",
      "type": "n8n-nodes-base.code",
      "position": [
        1120,
        -112
      ],
      "parameters": {
        "jsCode": "const data = $input.first().json;\nconst mp4WithAudio = data.videos.items.find(v => v.hasAudio && v.extension === 'mp4');\n\nreturn [{\n  json: {\n    title: data.title,\n    videoId: data.id,\n    downloadUrl: mp4WithAudio.url,\n    quality: mp4WithAudio.quality,\n    size: mp4WithAudio.size,\n    sizeText: mp4WithAudio.sizeText\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "20f68061-d5fc-4f8d-b969-9ac162138966",
      "name": "Download Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1344,
        -112
      ],
      "parameters": {
        "url": "={{ $json.downloadUrl }}",
        "options": {}
      },
      "typeVersion": 4.4
    },
    {
      "id": "0f286c3f-12ac-4fa3-8cec-79efebf32bff",
      "name": "Get TikTok Token",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1632,
        -112
      ],
      "parameters": {
        "url": "https://open.tiktokapis.com/v2/oauth/token/",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "client_key",
              "value": "YOUR_TIKTOK_CLIENT_KEY"
            },
            {
              "name": "client_secret",
              "value": "YOUR_TIKTOK_CLIENT_SECRET"
            },
            {
              "name": "grant_type",
              "value": "refresh_token"
            },
            {
              "name": "refresh_token",
              "value": "YOUR_TIKTOK_REFRESH_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "accfcbe8-1332-4300-aa19-98b600fd663f",
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "position": [
        2048,
        -112
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "mode-001",
              "name": "mode",
              "type": "string",
              "value": "publish"
            },
            {
              "id": "9cb88a6f-76ca-410f-af23-7704388e6452",
              "name": "privacy_level",
              "type": "string",
              "value": "SELF_ONLY"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "5b137fd7-4b9a-4f17-8b56-e19073e73a70",
      "name": "Draft or Publish?",
      "type": "n8n-nodes-base.if",
      "position": [
        2256,
        -112
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.mode }}",
              "rightValue": "draft"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "683a5955-9fbc-4651-8f6b-ed117500098e",
      "name": "TikTok Init Draft",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2560,
        -208
      ],
      "parameters": {
        "url": "https://open.tiktokapis.com/v2/post/publish/inbox/video/init/",
        "body": "={\n  \"source_info\": {\n    \"source\": \"FILE_UPLOAD\",\n    \"video_size\": {{ $('Download Link Parser').item.json.size }},\n    \"chunk_size\": {{ $('Download Link Parser').item.json.size }},\n    \"total_chunk_count\": 1\n  }\n}",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "raw",
        "sendHeaders": true,
        "rawContentType": "application/json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('Get TikTok Token').item.json.access_token }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json; charset=UTF-8"
            }
          ]
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "99a9080e-1227-4400-880b-627487ff029f",
      "name": "TikTok Init Publish",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2560,
        -16
      ],
      "parameters": {
        "url": "https://open.tiktokapis.com/v2/post/publish/video/init/",
        "body": "={\n  \"post_info\": {\n    \"title\": {{ JSON.stringify(($('Get Download Link').item.json.description || $('Arrange Data').item.json.title) + '') }},\n    \"privacy_level\": \"{{ $json.privacy_level }}\",\n    \"disable_duet\": false,\n    \"disable_comment\": false,\n    \"disable_stitch\": false,\n    \"video_cover_timestamp_ms\": 1000\n  },\n  \"source_info\": {\n    \"source\": \"FILE_UPLOAD\",\n    \"video_size\": {{ $('Download Link Parser').item.json.size }},\n    \"chunk_size\": {{ $('Download Link Parser').item.json.size }},\n    \"total_chunk_count\": 1\n  }\n}",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "raw",
        "sendHeaders": true,
        "rawContentType": "application/json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('Get TikTok Token').item.json.access_token }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json; charset=UTF-8"
            }
          ]
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "8b9e1e23-eb74-4c9a-8e41-7cf8964c35ca",
      "name": "Upload Video to TikTok",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2816,
        -128
      ],
      "parameters": {
        "url": "={{ $json.data.upload_url }}",
        "method": "PUT",
        "options": {},
        "sendBody": true,
        "contentType": "binaryData",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "video/mp4"
            },
            {
              "name": "Content-Range",
              "value": "=bytes 0-{{ $('Download Link Parser').item.json.size - 1 }}/{{ $('Download Link Parser').item.json.size }}"
            }
          ]
        },
        "inputDataFieldName": "={{ $('Download Video').item.binary.data }}"
      },
      "typeVersion": 4.4
    },
    {
      "id": "077ee3fb-a3f5-4aae-bab3-62436b85e5b1",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -656,
        -528
      ],
      "parameters": {
        "width": 512,
        "height": 768,
        "content": "# \ud83d\udcf1 YouTube Shorts \u2192 TikTok Auto Publisher\n\n## How It Works\n1. Polls a YouTube channel RSS feed every hour for new Shorts.\n2. Checks if the Short has already been processed using a data table to avoid duplicates.\n3. Fetches video download URL and metadata via YouTube Media Downloader API.\n4. Downloads the video binary from YouTube CDN.\n5. Authenticates with TikTok API using a refresh token.\n6. Routes to either Draft or Direct Publish mode based on Config setting.\n7. Uploads the binary video to TikTok via the Content Posting API.\n\n## Setup Checklist\n- [ ] Replace RSS feed URL with your YouTube channel's playlist ID\n- [ ] Add your RapidAPI key in the Get Download Link node\n- [ ] Add your TikTok client_key and client_secret in Get TikTok Token node\n- [ ] Add your TikTok refresh_token in Get TikTok Token node (valid 1 year)\n- [ ] Set mode in Config node: \"draft\" or \"publish\"\n- [ ] Set privacy_level in Config node: \"SELF_ONLY\" (required for unaudited apps)\n- [ ] For publish mode: set your TikTok account to Private in TikTok app settings\n\n## Customization\n- Change poll frequency in RSS Feed Trigger (everyHour, everyDay, etc.)\n- Add hashtags to the title expression in TikTok Init Publish node"
      },
      "typeVersion": 1
    },
    {
      "id": "48c6ab62-8fcd-4229-97fb-464b33cd7fee",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -32,
        -368
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 480,
        "content": "## \ud83d\udce1 RSS Feed & Deduplication\n\nPolls the YouTube channel RSS feed every hour.\nChecks if the video ID already exists in the data table.\nIf new \u2192 adds it to the table and continues.\nIf already processed \u2192 stops here (no duplicate posts).\n\n\u2699\ufe0f TO CONFIGURE:\nReplace the playlist ID in the feed URL:\nhttps://www.youtube.com/feeds/videos.xml?playlist_id=YOUR_PLAYLIST_ID"
      },
      "typeVersion": 1
    },
    {
      "id": "04d55596-a734-4f5e-a4f6-5d932f0fcbe6",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        640,
        -448
      ],
      "parameters": {
        "color": 7,
        "width": 848,
        "height": 560,
        "content": "## \ud83d\udce5 Video Fetch & Download\n\nArranges data from the RSS feed into clean fields.\nCalls YouTube Media Downloader API (RapidAPI) to get video stream URLs.\nParses the response to extract the MP4 with audio (360p \u2014 only quality with audio baked in).\nDownloads the actual binary video file ready for upload.\n\n\u2699\ufe0f TO CONFIGURE:\nReplace RapidAPI key in Get Download Link node:\nHeader \u2192 x-rapidapi-key \u2192 YOUR_RAPIDAPI_KEY\n\n\u2139\ufe0f NOTE:\nOnly 360p has audio included. Higher qualities (720p/1080p)\nhave no audio and require ffmpeg to merge \u2014 not supported here."
      },
      "typeVersion": 1
    },
    {
      "id": "a7f0227a-3e25-4d28-8755-dc1d18b8d251",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1520,
        -576
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 688,
        "content": "## \ud83d\udd10 TikTok Authentication\n\nUses a refresh token to get a fresh access token on every run.\nAccess token expires every 24 hours \u2014 this node handles renewal automatically.\nRefresh token is valid for 1 year.\n\n\u2699\ufe0f TO CONFIGURE \u2014 replace these 3 values:\n- client_key      \u2192 YOUR_TIKTOK_CLIENT_KEY\n- client_secret   \u2192 YOUR_TIKTOK_CLIENT_SECRET\n- refresh_token   \u2192 YOUR_TIKTOK_REFRESH_TOKEN\n\n\u2139\ufe0f HOW TO GET REFRESH TOKEN:\n1. Go to developers.tiktok.com \u2192 create app\n2. Add Content Posting API product\n3. Add your TikTok account as sandbox tester\n4. Run OAuth flow to get auth code\n5. Exchange code for tokens via /v2/oauth/token/\nRefresh token is returned in that response \u2014 valid 1 year."
      },
      "typeVersion": 1
    },
    {
      "id": "e90e2f57-4f80-4fd6-920e-bd033329c0d1",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1952,
        -576
      ],
      "parameters": {
        "color": 7,
        "width": 496,
        "height": 688,
        "content": "## \u2699\ufe0f Mode Config & Router\n\nControls whether video goes to TikTok as Draft or Direct Publish.\nThe IF node routes based on the mode value set here.\n\n\u2699\ufe0f TO CONFIGURE:\n\nmode \u2192\n  \"draft\"    = video goes to TikTok inbox as draft (you post manually)\n  \"publish\"  = video posts directly (account must be private in sandbox)\n\nprivacy_level \u2192\n  \"SELF_ONLY\"             = only you can see (required for unaudited apps)\n  \"MUTUAL_FOLLOW_FRIENDS\" = mutual followers (requires app audit)\n  \"FOLLOWER_OF_CREATOR\"   = your followers (requires app audit)\n  \"PUBLIC_TO_EVERYONE\"    = public (requires app audit)\n\n\u26a0\ufe0f IMPORTANT:\nUntil your TikTok app passes audit, SELF_ONLY is the only\nworking option AND your TikTok account must be set to Private.\nAfter audit \u2192 all privacy levels become available."
      },
      "typeVersion": 1
    },
    {
      "id": "ec27047e-008f-496f-a06d-cb3d0ad7c98a",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2480,
        -656
      ],
      "parameters": {
        "color": 7,
        "width": 528,
        "height": 768,
        "content": "## \ud83d\ude80 TikTok Upload\n\nTwo init nodes \u2014 only one runs based on Config mode:\n\nDRAFT MODE (TikTok Init Draft):\n- Sends video to TikTok inbox as a draft\n- No caption/description sent \u2014 you add manually before posting\n- Uses: /v2/post/publish/inbox/video/init/\n\nPUBLISH MODE (TikTok Init Publish):\n- Posts directly to your TikTok profile\n- Caption = YouTube description (falls back to title if no description)\n- Uses: /v2/post/publish/video/init/\n\nBoth init nodes return an upload_url.\nUpload Video to TikTok node sends the binary to that URL.\n\n\u2699\ufe0f TO CUSTOMIZE CAPTION (in TikTok Init Publish body):\nCurrent expression uses description \u2192 falls back to title.\nYou can append hashtags like:\n+ '\\n#shorts #trending #viral'"
      },
      "typeVersion": 1
    },
    {
      "id": "55803e4a-ab88-4a37-af8f-60f957bb8494",
      "name": "Get Refresh Token (One Time Setup)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        976,
        -1056
      ],
      "parameters": {
        "url": "https://open.tiktokapis.com/v2/oauth/token/",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "client_key",
              "value": "YOUR_CLIENT_KEY"
            },
            {
              "name": "client_secret",
              "value": "YOUR_CLIENT_SECRET"
            },
            {
              "name": "code",
              "value": "YOUR_AUTH_CODE"
            },
            {
              "name": "grant_type",
              "value": "authorization_code"
            },
            {
              "name": "redirect_uri",
              "value": "YOUR_REDIRECT_URI"
            }
          ]
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "eed624a0-15e3-43af-b359-fcbb9eae9c2a",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        768,
        -1904
      ],
      "parameters": {
        "width": 576,
        "height": 1024,
        "content": "## \ud83d\udd11 Get Refresh Token \u2014 ONE TIME SETUP ONLY\n\nRun this node ONCE to get your refresh_token.\nAfter getting it \u2192 paste into Get TikTok Token node in main workflow.\nThen disable or delete this node.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n\u2699\ufe0f HOW TO FILL THIS NODE:\n\n1. OPEN this URL in your browser (logged in as your TikTok account):\nhttps://www.tiktok.com/v2/auth/authorize\n?client_key=YOUR_CLIENT_KEY\n&response_type=code\n&scope=video.publish,video.upload,user.info.basic\n&redirect_uri=YOUR_REDIRECT_URI\n&state=abc123\n\n2. Approve the permissions on TikTok\n\n3. You will be redirected to a URL like:\nhttps://your-redirect-uri?code=XXXXXX...&scopes=...\nCopy everything after \"code=\" and before \"&scopes\"\nThat is your AUTH CODE \u26a0\ufe0f expires in ~10 minutes\n\n4. Fill this node:\n- client_key    \u2192 YOUR_TIKTOK_CLIENT_KEY\n- client_secret \u2192 YOUR_TIKTOK_CLIENT_SECRET  \n- code          \u2192 PASTE AUTH CODE FROM STEP 3\n- grant_type    \u2192 authorization_code (dont change)\n- redirect_uri  \u2192 YOUR_REDIRECT_URI\n\n5. Run the node\n\n6. From the output copy:\n- refresh_token \u2192 paste into Get TikTok Token node\n- Valid for 1 year \u2014 repeat this process after 1 year\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n\u26a0\ufe0f IMPORTANT NOTES:\n- Auth code is single use \u2014 if it fails, go back to step 1\n- Make sure redirect_uri matches exactly what is in your TikTok app\n- Make sure your TikTok account is added as sandbox tester\n  in developers.tiktok.com before running step 1"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "c547885a-c588-4a80-8e0f-06cd41c50f21",
  "connections": {
    "Config": {
      "main": [
        [
          {
            "node": "Draft or Publish?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add Row": {
      "main": [
        [
          {
            "node": "Arrange Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Arrange Data": {
      "main": [
        [
          {
            "node": "Get Download Link",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Video": {
      "main": [
        [
          {
            "node": "Get TikTok Token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get TikTok Token": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RSS Feed Trigger": {
      "main": [
        [
          {
            "node": "If row does not exist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Draft or Publish?": {
      "main": [
        [
          {
            "node": "TikTok Init Draft",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "TikTok Init Publish",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Download Link": {
      "main": [
        [
          {
            "node": "Download Link Parser",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "TikTok Init Draft": {
      "main": [
        [
          {
            "node": "Upload Video to TikTok",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "TikTok Init Publish": {
      "main": [
        [
          {
            "node": "Upload Video to TikTok",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Link Parser": {
      "main": [
        [
          {
            "node": "Download Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If row does not exist": {
      "main": [
        [
          {
            "node": "Add Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

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

About this workflow

This workflow polls a YouTube Shorts playlist RSS feed, deduplicates videos using an n8n Data Table, downloads each new Short via the YouTube Media Downloader API (RapidAPI), and uploads it to TikTok using the TikTok Content Posting API in either draft or direct publish mode.…

Source: https://n8n.io/workflows/16171/ — 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

This automation detects when you post a Tiktok video, automatically downloads the video without watermark, stores it in Google Drive, and reposts your Tiktok video to other social media platforms. All

HTTP Request, Google Drive, Rss Feed Read Trigger +1
Social Media

This n8n template demonstrates how to monitor YouTube channels and create AI-generated summaries in Notion. It helps you build a searchable video knowledge base without watching every new upload manua

Rss Feed Read Trigger, @Videodb/N8N Nodes Videodb, HTTP Request +1
Social Media

This workflow retrieves a LinkedIn contact’s full name from their profile URL using the LinkUp AI Search API. It’s a lightweight alternative to web scraping or complex APIs — integrating neatly into y

HTTP Request, Data Table
Social Media

AI Social Media Promoter – Automated Blog Sharing Workflow This workflow is built for bloggers, creators, and marketing teams who want to automatically promote new blog content across Instagram, Faceb

Output Parser Structured, Rss Feed Read Trigger, OpenAI Chat +6
Social Media

This n8n workflow is designed for content creators, bloggers, digital marketers, and social media managers who want to fully automate their content distribution pipeline. The workflow creates an end-t

Rss Feed Read Trigger, OpenAI, WordPress +10