AutomationFlowsSocial Media › Automate Tiktok Video Transcription with Rapidapi and Google Sheets

Automate Tiktok Video Transcription with Rapidapi and Google Sheets

ByEvoort Solutions @evoortsolutions on n8n.io

This automated workflow extracts transcripts from TikTok videos by reading video URLs from a Google Sheet, calling the API via TikTok Transcript Generator, cleaning the subtitle data, and updating the sheet with transcripts. It efficiently handles batches, errors, and rate…

Event trigger★★★★☆ complexity21 nodesGoogle SheetsHTTP Request
Social Media Trigger: Event Nodes: 21 Complexity: ★★★★☆ Added:

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

This workflow follows the Google Sheets → 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": "OW8DfG2xXPS60mSj",
  "name": "TikTok Transcript",
  "tags": [],
  "nodes": [
    {
      "id": "c0de0228-f79b-4b18-9e5d-ee6218259078",
      "name": "Google Sheets2",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1380,
        40
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "4b18deea-cfc2-4a8d-b2f3-8b31cac0d573",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        -560,
        40
      ],
      "parameters": {
        "url": "https://tiktok-transcript-generator.p.rapidapi.com/tiktok/index.php",
        "method": "POST",
        "options": {
          "response": {
            "response": {}
          }
        },
        "sendBody": true,
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $json['Video Url'] }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "x-rapidapi-host",
              "value": "tiktok-transcript-generator.p.rapidapi.com"
            },
            {
              "name": "x-rapidapi-key"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "baad7161-51f5-4f29-8af0-39244e10eb60",
      "name": "Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        580,
        -40
      ],
      "parameters": {
        "columns": {
          "value": {
            "Video Url": "={{ $('If').item.json['Video Url'] }}",
            "Transcript": "={{ $json.cleanedSubtitles }}",
            "Generated Date": "={{ new Date().toISOString().slice(0, 10) }}"
          },
          "schema": [
            {
              "id": "Video Url",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Video Url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Transcript",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Transcript",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Generated Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Generated Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Video Url"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "ab5bcc9b-e2a0-4ec7-a4db-de512662549d",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -1100,
        40
      ],
      "parameters": {
        "options": {
          "reset": false
        }
      },
      "typeVersion": 3
    },
    {
      "id": "d5d6e8a4-a2da-4cd5-80fc-3cf7c294697d",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        900,
        140
      ],
      "parameters": {
        "amount": 10
      },
      "typeVersion": 1.1
    },
    {
      "id": "6bea9362-5502-4c3c-acac-3f1a16bb0c64",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        -820,
        60
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "e0b7b7c8-3a7a-466d-bae7-269282b49d34",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json['Video Url'] }}",
              "rightValue": ""
            },
            {
              "id": "64dde394-0e49-4306-a24a-de2bf448fc95",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.Transcript }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a9ca3926-efbd-42fa-9388-b24625690145",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        -20,
        -40
      ],
      "parameters": {
        "jsCode": "return items.map(item => {\n  const raw = item.json.subtitles;\n\n  // Remove \"WEBVTT\" header and timestamp lines\n  const cleaned = raw\n    .replace(/^WEBVTT\\s*/gm, '')                       // Remove \"WEBVTT\"\n    .replace(/^\\d{2}:\\d{2}:\\d{2} --> \\d{2}:\\d{2}:\\d{2}/gm, '') // Remove timestamps\n    .replace(/^\\s*\\n/gm, '')                           // Remove empty lines\n    .trim();\n\n  return {\n    json: {\n      cleanedSubtitles: cleaned\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "becf9d6b-26a1-4498-9683-18ad15bc82ea",
      "name": "If1",
      "type": "n8n-nodes-base.if",
      "position": [
        -260,
        40
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cd25e377-5c82-40b1-85ea-b372ee7765b7",
              "operator": {
                "type": "number",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.error.status }}",
              "rightValue": 404
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "7c8d30f1-df83-4ee1-83ce-32f6d9b0a810",
      "name": "Google Sheets1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        300,
        140
      ],
      "parameters": {
        "columns": {
          "value": {
            "Video Url": "={{ $('If').item.json['Video Url'] }}",
            "Transcript": "No transcription available",
            "Generated Date": "={{ new Date().toISOString().slice(0, 10) }}"
          },
          "schema": [
            {
              "id": "Video Url",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Video Url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Transcript",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Transcript",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Generated Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Generated Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Video Url"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "90a316f5-0f08-42f8-86a0-318bcc9814f9",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -1580,
        40
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "5d36dbf3-ebd6-4cd8-913b-ee1308d6847b",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2500,
        -480
      ],
      "parameters": {
        "width": 780,
        "height": 980,
        "content": "# \ud83d\udcdd TikTok Transcript Extraction & Logging Workflow\n\nThis n8n workflow automatically fetches TikTok video transcripts via the RapidAPI TikTok Transcript Generator and updates a Google Sheet with cleaned transcriptions. It processes only rows missing transcripts, handles errors, and adds timestamps.\n\n---\n\n## \ud83e\udde9 Node-by-Node Explanation\n1. **Manual Trigger** \u2013 Starts the workflow manually on demand.  \n2. **Google Sheets2** \u2013 Reads TikTok video URLs and existing transcripts from the sheet.  \n3. **Loop Over Items** \u2013 Processes rows in batches of 10 for rate limiting.  \n4. **If** \u2013 Checks if a video URL exists and transcript is missing.  \n5. **HTTP Request** \u2013 Calls TikTok transcript API to fetch subtitles.  \n6. **If1** \u2013 Verifies the API response is successful (no 404 error).  \n7. **Code** \u2013 Cleans raw subtitles by removing timestamps and headers.  \n8. **Google Sheets** \u2013 Updates the sheet with cleaned transcript and date.  \n9. **Google Sheets1** \u2013 Marks videos with no transcript available in the sheet.  \n10. **Wait** \u2013 Pauses workflow to manage API rate limits before next batch.  \n\n---\n\n## \ud83d\udd11 Summary Use Cases  \n- Automate generation of TikTok video transcripts for content teams.  \n- Maintain a centralized Google Sheet of transcripts for SEO, captions, or repurposing content.  \n- Reduce manual effort and errors in transcribing TikTok videos.  \n- Handle API errors and missing data gracefully.\n\n---\n\n**This workflow enables seamless, automated transcription fetching and management for TikTok videos via Google Sheets integration, ideal for marketing, social media managers, and content creators.**\n"
      },
      "typeVersion": 1
    },
    {
      "id": "708c75c1-2ed7-48eb-b606-d6ff3eca7e30",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1660,
        -320
      ],
      "parameters": {
        "height": 580,
        "content": "### 1. When clicking \u2018Execute workflow\u2019  \n**Type:** Manual Trigger  \n**Purpose:**  \nManually triggers the workflow to start the process of reading TikTok URLs and generating transcripts.  \n**Use Case:**  \nInitiate the entire flow on demand without waiting for scheduled triggers."
      },
      "typeVersion": 1
    },
    {
      "id": "b7c01b0d-726b-44e7-8099-93812eccce4b",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1400,
        -320
      ],
      "parameters": {
        "height": 580,
        "content": "### 2. Google Sheets2  \n**Type:** Google Sheets (Read)  \n**Purpose:**  \nReads rows from the specified Google Sheet containing TikTok video URLs and existing transcript data.  \n**Use Case:**  \nFetch the list of videos to process and identify which ones need transcription.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "2d5229aa-2c40-41f6-8556-77690c3ed956",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1140,
        -320
      ],
      "parameters": {
        "height": 580,
        "content": "### 3. Loop Over Items  \n**Type:** Split In Batches  \n**Purpose:**  \nProcesses the fetched rows in smaller batches (default 10 items per batch) to avoid rate limits or overload.  \n**Use Case:**  \nControl the workflow execution speed and resource usage when handling large data sets.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "89710512-98f5-4dc2-b8a5-234ae49d343f",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -880,
        -320
      ],
      "parameters": {
        "height": 580,
        "content": "### 4. If  \n**Type:** Conditional Check (If)  \n**Purpose:**  \nFilters each row to process only those where the `Video Url` is not empty and `Transcript` is empty (i.e., videos needing transcription).  \n**Use Case:**  \nSkip rows already having transcripts to avoid redundant API calls."
      },
      "typeVersion": 1
    },
    {
      "id": "7514d668-1b6d-4786-8e7f-f07fbfeac194",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -620,
        -320
      ],
      "parameters": {
        "height": 580,
        "content": "### 5. HTTP Request  \n**Type:** HTTP Request  \n**Purpose:**  \nCalls the TikTok Transcript Generator API with the video URL to retrieve the transcript.  \n**Use Case:**  \nGet the subtitle/transcript data for TikTok videos programmatically.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "2cfb2c0d-980c-4654-9486-45bc765372c6",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -360,
        -320
      ],
      "parameters": {
        "height": 580,
        "content": "### 6. If  \n**Type:** Conditional Check (If)  \n**Purpose:**  \nChecks if the API response is valid and does not contain a 404 error.  \n**Use Case:**  \nHandle cases where transcripts are unavailable or the video URL is invalid."
      },
      "typeVersion": 1
    },
    {
      "id": "167cf773-1543-4778-ba99-d4adc87f3ec3",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -100,
        -320
      ],
      "parameters": {
        "height": 580,
        "content": "### 7. Code  \n**Type:** Code (JavaScript)  \n**Purpose:**  \nCleans the raw subtitles returned by the API by removing headers, timestamps, and empty lines for better readability.  \n**Use Case:**  \nPrepare the transcript text for clean storage and further processing."
      },
      "typeVersion": 1
    },
    {
      "id": "ad776fb7-d066-4f10-917e-a1fbf476e961",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        200,
        -180
      ],
      "parameters": {
        "height": 480,
        "content": "### 8. Google Sheets  \n**Type:** Google Sheets (Append or Update)  \n**Purpose:**  \nWrites the cleaned transcript, video URL, and generation date back into the Google Sheet, updating existing rows.  \n**Use Case:**  \nMaintain an up-to-date record of transcripts next to each TikTok video URL."
      },
      "typeVersion": 1
    },
    {
      "id": "45271bfa-118b-46c7-8e73-e077119ce31f",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        520,
        -380
      ],
      "parameters": {
        "height": 580,
        "content": "### 9. Google Sheets1  \n**Type:** Google Sheets (Append or Update)  \n**Purpose:**  \nFor cases where the API returns an error (like 404), it updates the sheet with a \"No transcription available\" message for that video URL.  \n**Use Case:**  \nClearly indicate videos for which transcripts could not be generated."
      },
      "typeVersion": 1
    },
    {
      "id": "4bb59f93-a06c-4252-bec4-2809fa4d6067",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        840,
        -220
      ],
      "parameters": {
        "height": 540,
        "content": "### 10. Wait  \n**Type:** Wait  \n**Purpose:**  \nPauses the workflow briefly between batches to prevent hitting API rate limits and ensure smooth execution.  \n**Use Case:**  \nThrottle the flow execution for stability and API compliance."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "957a8859-b78c-4fdc-b1c6-50de2acaa6a0",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If1": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Google Sheets1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code": {
      "main": [
        [
          {
            "node": "Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "If1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets1": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets2": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Google Sheets2",
            "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

This automated workflow extracts transcripts from TikTok videos by reading video URLs from a Google Sheet, calling the API via TikTok Transcript Generator, cleaning the subtitle data, and updating the sheet with transcripts. It efficiently handles batches, errors, and rate…

Source: https://n8n.io/workflows/5882/ — 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 n8n workflow automates the process of uploading video and image advertisements to Meta Ads Manager via the Meta Graph API (Facebook Ads) directly from Google Sheets and Google Drive. The workflow

Facebook Graph Api, Google Sheets, HTTP Request +2
Social Media

This workflow provides an end-to-end automation for discovering, evaluating, and optionally downloading high-quality educational YouTube videos.

HTTP Request, Google Sheets
Social Media

• Downloads videos/music from YouTube using yt-dlp • Merges assets with dynamic text overlays • Automatically uploads to YouTube as Shorts (9:16 format) • Tracks everything in Google Sheets Install yt

Google Sheets, Execute Command, Read Write File +1
Social Media

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

HTTP Request, Google Sheets, Google Drive +1
Social Media

This workflow is perfect for digital content creators, marketers, and social media managers who regularly create engaging short-form videos featuring inspirational or motivational quotes. While the wo

Google Sheets, Google Drive, Read Write File +2