Getting the latest video from a particular YouTube channel into a FlutterFlow app sounds straightforward — until you realise how many layers sit between a YouTube channel and a working video URL in your Flutter widget. This article walks through the full solution using YouTube's RSS feed, a Dart custom action, and FlutterFlow's YouTube Player widget. It was first written in 2022 and has been fully refreshed for 2026, reflecting current FlutterFlow conventions, updated Dart package versions, and the modern FlutterFlow custom code workflow.
The detail page in question is, on the face of it, very simple. Part of it comprises a container populated with data from Google Firebase, making the elements engaging and useful. You can tap the YouTube video to play it, and tap buttons to invoke the relevant engagement methods for the entity whose information has been pulled from Firebase. The YouTube Player component in FlutterFlow is excellent — all it needs is the URL of the video to work with.
Container for YouTube Player and engagement method buttons
A FlutterFlow container-based widget comprising a YouTube player, and button-based links in a row to the engagement methods of Twitter/X, YouTube, Facebook and phone call.
Screenshot from FlutterFlow designer
FlutterFlow Widget tree for YouTube Player and engagement method buttons
The widget comprises a ListView which gets a document from a collection in Firebase, and a container with a column and text widgets to display it. The buttons have actions populated by data from Firebase.
Screenshot from FlutterFlow designer
In the end this became a journey into FlutterFlow custom actions, pubspec dependencies, Dart programming and XML parsing. It took longer than expected because each piece needed to be learned sequentially — but once it clicked, the solution works reliably and updates automatically every time the page loads.
Contents
- Container for YouTube Player and engagement method buttons
- FlutterFlow Widget tree for YouTube Player and engagement method buttons
- What's changed in 2026
- YouTube RSS feeds
- YouTube Channel ID
- YouTube RSS feed structure
- The YouTube video player in FlutterFlow
- FlutterFlow Custom Action to populate the YouTube URL
- The key insight: run the action on the calling page, not the destination page
- On Tap Action
- Page parameters
- Why prototype the custom action as a standalone Dart app first?
- Dart: the ytxml prototype app
- pubspec.yaml
- ytxml.dart
- FlutterFlow Custom Action
- Debugging with VS Code and the FlutterFlow extension
- See also
What's changed in 2026
Since this article was first written, a few things have shifted that are worth knowing before you dive in.
- FlutterFlow's custom code tooling has matured significantly. The in-browser code editor now offers better inline error reporting and dependency resolution hints. You can also use the FlutterFlow VS Code extension to write and test custom actions locally with full IDE support, which is a substantial improvement over the earlier workflow of downloading the project and debugging blind.
- The
xmlDart package has moved on. Version6.xis now current and is compatible with modern FlutterFlow projects. The^5.3.0ceiling mentioned in the original article no longer applies — you should targetxml: ^6.5.0in your pubspec dependencies. - FlutterFlow's YouTube Player widget remains a first-class Base Element, and the approach described here still works exactly as intended. The widget API has not changed in any breaking way.
- YouTube's RSS feed is still live. Despite years of speculation that Google would deprecate it, the feed endpoint at
https://www.youtube.com/feeds/videos.xml?channel_id=remains available and undocumented-but-functional in 2026. It continues to be the cleanest way to retrieve a channel's latest video without needing an API key or quota management. - Twitter is now X. References to a Twitter button in the UI are updated accordingly, though the underlying approach is identical.
- VSCodium remains a solid choice for local Flutter debugging, and the FlutterFlow VS Code extension now makes it easier to keep your local codebase in sync with the FlutterFlow project without a full manual download each time.
YouTube RSS feeds
YouTube has made an RSS feed available since the platform launched. It is not prominently advertised — YouTube would clearly prefer you to use their website and player — but it has proven remarkably durable. In 2026 it remains the simplest way to programmatically retrieve a channel's latest video without registering for the YouTube Data API, managing OAuth credentials, or worrying about quota limits.
YouTube Channel ID
To use the RSS feed you need the YouTube Channel ID. This is sometimes visible directly in the channel URL — for example, https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw — where the channel ID is the final segment: UCuAXFkgsw1L7xaCfnd5JJOw.
Vanity URLs and individual video links don't expose the channel ID directly. A small shell script (linked at the bottom of this page) can resolve the channel ID from any YouTube video share link. Share a video, paste the link as a parameter, and you get back the full RSS feed URL.
% ./youtube-rss.sh https://youtu.be/dQw4w9WgXcQ
https://www.youtube.com/feeds/videos.xml?channel_id=UCuAXFkgsw1L7xaCfnd5JJOw
YouTube RSS feed structure
The RSS feed URL follows a consistent pattern with channel_id as the query parameter. The feed returns structured XML from which you can extract the unique video identifier for every video in the channel's recent history.
Inside each <entry> block you will find the video identifier in the <yt:videoId> element — for example <yt:videoId>LLFhKaqnWwk</yt:videoId>. The entries appear in reverse chronological order, so the first entry is always the most recent video. Here is an excerpt:
<entry>
<id>yt:video:LLFhKaqnWwk</id>
<yt:videoId>LLFhKaqnWwk</yt:videoId>
<yt:channelId>UCuAXFkgsw1L7xaCfnd5JJOw</yt:channelId>
<title>Rick Astley - Never Gonna Give You Up (Official Animated Video)</title>
<link rel="alternate" href="https://www.youtube.com/watch?v=LLFhKaqnWwk"/>
<author>
<name>Rick Astley</name>
<uri>https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw</uri>
</author>
</entry>
The YouTube video player in FlutterFlow
The FlutterFlow YouTubePlayer widget is a Base Element — a first-party, maintained component that ships as part of FlutterFlow itself. You can find it in the Base Elements section of the Widget Panel, or add it directly from the widget tree.

Beyond the standard FlutterFlow controls, the YouTube Player widget lets you set the video URL, whether to loop, whether to mute, whether to show YouTube's native controls, and whether to allow full screen. In this implementation the URL field uses a Combine Text variable as its input. The URL returned from the custom action is not quite in the format the control expects, and wrapping it in a Combine Text expression resolves that cleanly.

The Combine Text has a single value — the variable ytVid — which is produced by the custom action described below.
FlutterFlow Custom Action to populate the YouTube URL
The goal is for the page to always show the channel's most recent video without any manual intervention. Even with a modest number of detail pages, keeping video links current by hand would become unmanageable quickly. Running this logic on the device at page load time is fast, free (no Firebase function invocation cost), and requires no server-side infrastructure. The only requirement is an active internet connection, which is a reasonable assumption for a mobile app in 2026.
The key insight: run the action on the calling page, not the destination page
The custom action that fetches the latest video is not placed on the detail page itself. It runs on the calling page, as an On Tap action, immediately before the Navigate To action that opens the detail page. This keeps the detail page lean and fast to render.
On Tap Action

The action takes a single argument — idChannel, a string pulled from the Firebase document representing the channel ID for this entity — and returns a single Action Output variable, ytVid, containing the latest video URL ready for the YouTube Player on the next screen.
Page parameters
The Navigate To action passes page parameters to the destination, including ytVid for the YouTube Player to consume.

Why prototype the custom action as a standalone Dart app first?
FlutterFlow is a low-code platform, not a no-code one — and that distinction matters. You have the full power of Dart and the pub.dev ecosystem available through custom actions and custom widgets. The trade-off is that when something goes wrong, the feedback loop inside FlutterFlow's browser-based editor can be slower than working in a local IDE.
For non-trivial custom actions, it pays to validate your logic as a plain Dart command-line app first. This removes all Flutter and FlutterFlow moving parts while you work through the logic, and gives you a tight, fast iteration loop. Once the Dart app works correctly, porting it to a FlutterFlow custom action is a small mechanical step.
Dart: the ytxml prototype app
ytxml is a minimal command-line Dart application. Given a YouTube Channel ID, it fetches the RSS feed and returns the URL of the most recent video.
pubspec.yaml
name: ytxml
description: A simple command-line application.
version: 1.0.0
# homepage: https://www.ezone.co.uk/flutter/youtube-xml-flutter-latest.html
dependencies:
xml: ^6.5.0
ytxml.dart
//
// Copyright 2022-2026 Multizone Ltd. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Multizone Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import 'dart:convert';
import 'dart:io';
import 'package:xml/xml.dart';
// To run in Dart from the command line an app needs a 'main' so this Future is uncommented.
Future<String> main(String idChannel) async {
if (idChannel.isEmpty) {
print('Was expecting a YouTube Channel ID as a parameter');
return ("No YouTube Channel ID");
}
// A FlutterFlow Custom Action cannot have a 'main' as one already exists.
// Comment out the Dart main Future and if statement above, and uncomment
// the line below, to use this code in a FlutterFlow custom action.
// Future<String> latestVideo(String idChannel) async {
var idString = idChannel.toString();
print(idString); // Verify the parameter. Remove for production.
final HttpClient httpClient = HttpClient();
final url = 'https://www.youtube.com/feeds/videos.xml?channel_id=$idString';
final request = await httpClient.getUrl(Uri.parse(url));
final response = await request.close();
final stream = response.transform(utf8.decoder);
final contents = await stream.join();
final document = XmlDocument.parse(contents);
var vids =
document.findAllElements('yt:videoId').map((node) => node.text).toList();
var firstVideo = 'https://youtu.be/' + (vids.first);
print(firstVideo); // Verify the returned video link. Remove for production.
return (firstVideo);
}
This app is asynchronous, using a Dart Future. The xml package parses the RSS feed for the given channel ID, extracts all video identifiers into a list, and uses Dart's .first property to grab the first entry — which is consistently the most recent video. That value is returned as the firstVideo string, either printed to the console during prototyping or handed back to FlutterFlow as the custom action's return value.
One note on logging: Dart's print() function works fine in a standalone command-line app and in FlutterFlow custom actions during development. For production Flutter apps, prefer debugPrint() (which requires import 'package:flutter/foundation.dart') or a dedicated logging package. The flutter/foundation.dart import is not available in a pure Dart command-line context, which is another reason to keep the prototype and the FlutterFlow action as separate, clearly commented variants of the same code.
FlutterFlow Custom Action
Once the standalone Dart app produces the correct output, porting it to FlutterFlow is straightforward. Paste the working code into a new custom action, then make the following adjustments:
- Comment out the
Future<String> main(String idChannel)declaration and the empty-checkifblock beneath it. - Uncomment the
Future<String> latestVideo(String idChannel)declaration. - Set the FlutterFlow Action name to
latestVideo. - Set the return type to String.
- Define an argument
idChannelof type String. - Add the pubspec dependencies:
xml: ^6.5.0. Theconvertpackage is part of the Dart SDK and does not need a separate entry in modern FlutterFlow projects.

Compile the action inside FlutterFlow. Any dependency warnings in the editor can generally be ignored at this stage — FlutterFlow's browser-based linter does not fully resolve transitive dependencies, but the build process does. Clear all genuine code errors, then run the app. In most cases, if the standalone Dart prototype worked, the FlutterFlow action will work first time.
Debugging with VS Code and the FlutterFlow extension
Since this article was first written, the FlutterFlow VS Code extension has become the recommended way to work with custom code locally. It keeps your local project in sync with your FlutterFlow canvas without requiring a manual project download each time, and gives you full IDE debugging support — breakpoints, variable inspection, and the full Dart DevTools suite.
If you prefer a fully open-source toolchain, VSCodium — the community-maintained, freely-licensed binary distribution of VS Code — works equally well and supports the same Flutter and Dart extensions.

I/flutter) shows the idChannel passed to the custom action and the latestVideo URL returned to FlutterFlow. The Dart DevTools panel on the right shows the same values as stdout entries.Whether you use VS Code, VSCodium, or Android Studio, attaching to a real device over USB and filtering the log output by I/flutter is the fastest way to confirm that your custom action is receiving the right input and returning the right output before you remove the print() statements for production.
See also
A script to get the RSS feed for a YouTube page by Timothy J. Luoma.
The FlutterFlow YouTubePlayer widget documentation.
Dart.Dev — Get started: Command-line and server apps
Dart.Dev — Asynchronous programming: futures, async, await
xml package on pub.dev
VSCodium and Flutter on this website