YouTube to Google Sheets, content tracking stays clean
Your YouTube content data is probably scattered. A little in YouTube Studio, a little in old spreadsheets, a little in someone’s “notes” doc. Then reporting week hits and you’re stuck copy-pasting titles, tags, dates, and thumbnails again (and finding three different versions of “the truth”).
This YouTube Sheets sync automation hits marketing managers first because they’re the ones asked for “quick numbers.” But creators building content systems and agency operators managing multiple channels feel it too. You end up spending about 2 hours just getting data into a usable format, before analysis even starts.
This workflow pulls your video metadata and captions straight from the YouTube API and keeps a Google Sheet updated automatically. You’ll learn what it does, what you need, and how to run it daily so your tracking stays clean.
How This Automation Works
Here’s the complete workflow you’ll be setting up:
n8n Workflow Template: YouTube to Google Sheets, content tracking stays clean
flowchart LR
subgraph sg0["When clicking ‘Execute workflow’ Flow"]
direction LR
n0["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Get My Channel"]
n1["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>List Uploads"]
n2@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If", pos: "b", h: 48 }
n3["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Loop Vars"]
n4@{ icon: "mdi:database", form: "rounded", label: "Update Posts", pos: "b", h: 48 }
n5@{ icon: "mdi:swap-vertical", form: "rounded", label: "Variables", pos: "b", h: 48 }
n6@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split Out", pos: "b", h: 48 }
n7["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Get Video Details"]
n8["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Collect ids"]
n9@{ icon: "mdi:database", form: "rounded", label: "Update Posts1", pos: "b", h: 48 }
n10@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split Out1", pos: "b", h: 48 }
n11@{ icon: "mdi:play-circle", form: "rounded", label: "When clicking ‘Execute workf..", pos: "b", h: 48 }
n12["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Get captions text"]
n13["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Get captions ID"]
n14@{ icon: "mdi:database", form: "rounded", label: "Update Posts2", pos: "b", h: 48 }
n15@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If1", pos: "b", h: 48 }
n16@{ icon: "mdi:database", form: "rounded", label: "Get row(s) in sheet", pos: "b", h: 48 }
n17@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If2", pos: "b", h: 48 }
n2 --> n16
n2 --> n3
n15 --> n12
n17 --> n7
n3 --> n1
n6 --> n4
n5 --> n3
n10 --> n9
n8 --> n2
n1 --> n6
n4 --> n8
n9 --> n13
n0 --> n5
n13 --> n15
n7 --> n10
n12 --> n14
n16 --> n17
n11 --> n0
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n11 trigger
class n2,n15,n17 decision
class n4,n9,n14,n16 database
class n0,n1,n7,n12,n13 api
class n3,n8 code
classDef customIcon fill:none,stroke:none
class n0,n1,n3,n7,n8,n12,n13 customIcon
Why This Matters: Content Tracking That Doesn’t Drift
Manual tracking breaks in slow motion. You start with good intentions: a neat spreadsheet, a few columns, maybe a weekly update. Then uploads happen, titles get tweaked, thumbnails change, tags evolve, and captions are added after the fact. The sheet falls behind, and now every report becomes a one-off scramble. Worse, you make decisions on stale data because it “looks close enough.” Honestly, that’s how you miss patterns that could’ve improved your next month of content.
It adds up fast. Here’s where it breaks down.
- Copy-pasting video details across 20–50 uploads turns into a recurring admin task you keep postponing.
- Small differences creep in (a changed title, missing tag set, wrong publish date), which makes comparisons unreliable.
- Captions usually get ignored because downloading SRT files manually is annoying, so you lose a goldmine for SEO and topic analysis.
- When someone asks for “all videos from last quarter with tags,” you spend your time collecting data instead of interpreting it.
What You’ll Build: A Self-Updating YouTube Content Sheet
This workflow creates a living Google Sheet that mirrors what’s actually on your YouTube channel. You run it manually the first time (or schedule it), and it fetches your channel’s upload playlist, then walks through every page of results so nothing gets skipped. For each video, it writes the basics first (like the YouTube ID and title), then looks up whether a row already exists so it can update instead of duplicating. After that, it pulls richer metadata such as tags, privacy status, upload status, thumbnails, and descriptions. If captions exist, it also downloads the captions in SRT format and stores them right in the sheet.
The workflow starts from your own channel profile, which means you’re not guessing at upload playlist IDs. It then loops through uploads with pagination, updates rows in Google Sheets, and finally branches into captions retrieval only when captions are actually available.
What You’re Building
| What Gets Automated | What You’ll Achieve |
|---|---|
|
|
Expected Results
Say your channel has 40 videos and you publish 3 per week. Manually tracking each new upload takes maybe 10 minutes to collect title, tags, publish date, thumbnail URL, and a caption export, so you burn about 30 minutes a week just on new videos. Then once a month you “refresh” the sheet because older titles and tags changed, which can take another 2 hours. With this workflow: you schedule a daily run, it updates the sheet automatically, and your monthly refresh becomes basically zero.
Before You Start
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- YouTube (Google account) for access to your channel’s uploads.
- Google Sheets to store and update the video database.
- Google OAuth credentials (get it from Google Cloud Console APIs & Services).
Skill level: Intermediate. You’ll connect OAuth credentials and match your sheet columns to the workflow fields.
Want someone to build this for you? Talk to an automation expert (free 15-minute consultation).
Step by Step
A manual run or schedule kicks things off. The included Manual Trigger is perfect for your first test run. After that, you can swap it for a Cron trigger so the sheet stays current without anyone remembering to press a button.
Your channel profile is fetched first. Using an HTTP Request to the YouTube API, the workflow pulls your channel details and identifies the exact uploads playlist behind your channel. That’s important because it keeps the automation tied to your own uploads, not a hard-coded list that breaks later.
Uploads are retrieved, page by page. Code nodes track pagination and collect video IDs, while a Split Out step iterates through each upload item. At this stage the workflow writes “basic” details to Google Sheets so you get an early, structured list even before deeper enrichment runs.
Rows are updated with full metadata and captions. The workflow looks up existing rows in Google Sheets, checks if the video already exists, then fetches full metadata for what’s missing or needs refresh. It also requests a captions index and only downloads SRT text when captions are available, then saves that into the correct row.
You can easily modify the columns you store to include things like categoryId or max resolution thumbnails based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Manual Trigger
This workflow starts manually so you can validate data pulls before scheduling or cloning for production use.
- Add the Manual Run Trigger node as the workflow trigger.
- Keep default settings (no parameters required) so you can click Execute Workflow to test.
Step 2: Connect YouTube API and Initialize Settings
These nodes fetch the channel uploads playlist and initialize pagination variables for looping through video items.
- Open Fetch Channel Profile and set URL to
=https://www.googleapis.com/youtube/v3/channels. - Under Query Parameters, set part to
contentDetailsand mine totrue. - Credential Required: Connect your googleOAuth2Api credentials in Fetch Channel Profile.
- Open Initialize Settings and set JSON Output to
{ "per_page": 50, "current_page": 0, "nextPageToken":"", "playlistId": "{{ $json.items[0].contentDetails.relatedPlaylists.uploads }}", "ids":"" }.
mine=true query only works for authenticated accounts.Step 3: Set Up Paging and Upload Retrieval
These nodes iterate pages of uploads and capture basic video IDs and publish dates.
- In Iterate Paging Vars, keep the provided JavaScript Code to increment
current_pageand carry forwardnextPageTokenand aggregated IDs. - Configure Retrieve Upload Items with URL
=https://www.googleapis.com/youtube/v3/playlistItemsand set query params: partcontentDetails, maxResults{{ $json.per_page }}, playlistId{{ $json.playlistId }}, pageToken{{ $json.nextPageToken }}. - Credential Required: Connect your googleOAuth2Api credentials in Retrieve Upload Items.
- Set Expand Upload List to split Field To Split Out as
items.
Step 4: Connect Google Sheets and Manage Paging Logic
This step writes basic upload data, aggregates IDs, and determines whether another page should be fetched.
- In Update Sheet Basics, set Operation to
appendOrUpdateand map columns: published →{{ $json.contentDetails.videoPublishedAt }}, youtube_id →{{ $json.contentDetails.videoId }}. - Credential Required: Connect your googleSheetsOAuth2Api credentials in Update Sheet Basics.
- In Aggregate Video IDs, keep the JavaScript to concatenate unique IDs into
ids. - Configure Paging Condition Check to compare leftValue
{{ $json.current_page }}with rightValue{{ Math.ceil($('Retrieve Upload Items').last().json.pageInfo.totalResults / $('Retrieve Upload Items').last().json.pageInfo.resultsPerPage) }}. - Open Lookup Sheet Rows and select your Document ID and Sheet Name; keep filtersUI lookup columns for
captions,privacyStatus, anduploadStatus. - Credential Required: Connect your googleSheetsOAuth2Api credentials in Lookup Sheet Rows.
- In Row Presence Check, keep the condition
{{ $json }}notEmpty to proceed only when rows are found.
[YOUR_ID] placeholders in Update Sheet Basics and Lookup Sheet Rows with your actual Google Sheets document and sheet IDs.Step 5: Set Up Video Metadata Enrichment
This path fetches video metadata and updates the details in your Google Sheet.
- In Fetch Video Metadata, set URL to
https://www.googleapis.com/youtube/v3/videosand query params: partsnippet,status, id{{ $json.youtube_id }}. - Credential Required: Connect your googleOAuth2Api credentials in Fetch Video Metadata.
- Configure Expand Video Items to split Field To Split Out as
items. - In Update Sheet Details, set Operation to
appendOrUpdateand map columns: tags →{{ $json.snippet.tags }}, title →{{ $json.snippet.title }}, maxres →{{ $json.snippet.thumbnails.maxres.url }}, categoryId →{{ $json.snippet.categoryId }}, youtube_id →{{ $json.id }}, description →{{ $json.snippet.description }}, uploadStatus →{{ $json.status.uploadStatus }}, privacyStatus →{{ $json.status.privacyStatus }}. - Credential Required: Connect your googleSheetsOAuth2Api credentials in Update Sheet Details.
Step 6: Configure Captions Download and Storage
These nodes check for captions, download them as SRT text, and store the content back in the sheet.
- In Fetch Captions Index, set URL to
https://www.googleapis.com/youtube/v3/captionswith query param videoId →{{ $json.youtube_id }}. - Credential Required: Connect your googleOAuth2Api credentials in Fetch Captions Index.
- In Captions Available Check, keep the condition
{{ $json.items[0].id }}notEmpty. - Open Download Captions Text and set URL to
=https://www.googleapis.com/youtube/v3/captions/{{ $json.items[0].id }}, with query params tfmtsrtand altmedia; add header Accept →text/plain; charset=UTF-8. - Credential Required: Connect your googleOAuth2Api credentials in Download Captions Text.
- In Update Sheet Captions, set Operation to
appendOrUpdateand map captions →{{ $json.data }}and youtube_id →{{ $('Update Sheet Details').item.json.youtube_id }}. - Credential Required: Connect your googleSheetsOAuth2Api credentials in Update Sheet Captions.
Step 7: Test and Activate Your Workflow
Run a manual test to verify YouTube data sync and confirm sheet updates before enabling the workflow for production use.
- Click Execute Workflow on Manual Run Trigger to run a full test.
- Confirm that Update Sheet Basics appends or updates
youtube_idandpublishedvalues. - Verify Update Sheet Details writes metadata fields like
title,privacyStatus, anduploadStatus. - If captions exist, ensure Update Sheet Captions writes
captionstext to the matchingyoutube_id. - Once validated, toggle the workflow to Active to use it in production or duplicate it to add a schedule trigger.
Troubleshooting Tips
- Google (YouTube + Sheets) OAuth credentials can expire or need specific permissions. If things break, check the credential status inside n8n’s Credentials tab first, then confirm scopes in Google Cloud Console.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Caption downloads can fail for private videos or videos without caption tracks. Turn on “Continue on Fail” for the captions branch if you’d rather keep syncing metadata than have one edge case stop the whole run.
Quick Answers
About 30 minutes if your Google OAuth is ready.
No. You’ll authenticate Google, pick your Sheet, and confirm the “Videos” tab columns match what the workflow writes.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in OpenAI API costs if you enable AI features, but this workflow’s core sync can run without OpenAI.
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
Yes, and you should. You can add columns by editing the Set/Edit Fields step and the Google Sheets “appendOrUpdate” mappings, then extend the HTTP Request that fetches video details to include fields like categoryId or statistics. Some teams also disable the captions branch to speed things up, then run a separate weekly captions pull for only new videos.
Most of the time it’s OAuth. Reconnect your Google credential in n8n, confirm the YouTube Data API v3 is enabled in Google Cloud, and make sure the consent screen and scopes match what the node requests. If it fails only on captions, that’s often a permissions issue (private videos) or simply that no caption track exists for that upload.
It can handle hundreds of videos, but the first full sync will take longer because it paginates through your entire uploads playlist.
For a full-channel backfill plus ongoing updates, usually yes. Zapier and Make are great for “new video posted → do one thing,” but they get clunky when you need pagination, row lookups, and conditional branches for captions. n8n handles that logic cleanly, and self-hosting avoids per-task pricing when you run daily. If you only need a simple two-step alert, those tools can be quicker to click together. Talk to an automation expert if you want a recommendation for your setup.
Once this is running, your spreadsheet stops being a “project” and becomes infrastructure. The workflow keeps the data straight so you can focus on decisions, not data wrangling.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.