How Channel Logo URLs Are Extracted From Markdown `<img>` Tags in Free-TV/IPTV
The Free-TV/IPTV repository extracts channel logo URLs by splitting markdown table rows on pipe characters, grabbing the fifth column containing the <img> tag, and slicing the string between src=" and the closing quote.
The Free-TV/IPTV project stores thousands of streaming channels in markdown tables organized by country. When the make_playlist.py script generates M3U playlists, it must parse these markdown tables to extract the raw image URLs from HTML <img> tags embedded in the Logo column. This extraction process uses lightweight string manipulation rather than a full HTML parser to keep the build pipeline fast and dependency-free.
The Markdown Table Structure
Channel data lives in the lists/ directory as markdown files (e.g., usa.md, uk.md). Each row represents a single channel and follows this pipe-delimited format:
| 2 | Retro TV | [>](https://example.com/stream.m3u8) | <img height="20" src="https://i.imgur.com/PNTYOgg.png" /> | RetroTVEast.us |
The fourth column (index 4 when split) contains the raw <img> tag with the logo URL stored in the src attribute. According to the source code, the Channel class receives the entire markdown line as a string and processes it to isolate this URL.
Parsing Logic in make_playlist.py
The extraction happens in make_playlist.py within the Channel class constructor. The implementation uses two precise string operations to transform the markdown cell into a clean URL.
Splitting the Markdown Row
First, the script splits the incoming line on the pipe character (|) to break the table row into individual columns:
parts = md_line.split('|')
self.logo = parts[4].strip() # Extracts: <img height="20" src="https://i.imgur.com/PNTYOgg.png" />
This yields the raw HTML string including the <img> tag and its attributes.
Extracting the src Attribute
Next, the code locates the src=" substring and slices the content up to the closing double quote. This is implemented in lines 104–106 of make_playlist.py:
self.logo = self.logo[self.logo.find('src="') + 5:self.logo.rfind('"')]
The find('src="') + 5 calculation skips past the src=" prefix (5 characters), while rfind('"') locates the final quote of the attribute. The result is the pure URL: https://i.imgur.com/PNTYOgg.png.
Code Example: Extracting a Logo URL
You can observe this behavior by instantiating the Channel class directly with a markdown line:
from make_playlist import Channel
group = "USA"
md_line = '| 2 | Retro TV | [>](https://example.com/stream.m3u8) | <img height="20" src="https://i.imgur.com/PNTYOgg.png" /> | RetroTVEast.us |'
ch = Channel(group, md_line)
print(ch.logo) # Output: https://i.imgur.com/PNTYOgg.png
This manual parsing approach assumes the src attribute always uses double quotes and appears before any other attributes in the closing tag.
Generating the M3U Output
Once extracted, the logo URL is stored in self.logo and later injected into the M3U playlist as the tvg-logo attribute. The to_m3u_line() method formats the entry as:
#EXTINF:-1 tvg-name="Retro TV" tvg-logo="https://i.imgur.com/PNTYOgg.png" group-title="USA",Retro TV
https://example.com/stream.m3u8
This metadata allows IPTV players to display the channel icon alongside the stream name.
Summary
- Location: Extraction logic resides in
make_playlist.py, lines 104–106 within theChannelclass. - Method: The script splits markdown rows on pipe characters, selects the fifth element (index 4), and slices between
src="and the closing quote. - Output: The resulting URL populates the
tvg-logoattribute in the generated M3U playlist. - Trade-off: String slicing is used instead of an HTML parser for performance, requiring strict adherence to the
<img src="...">format in the markdown tables.
Frequently Asked Questions
Why does the repository use manual string parsing instead of an HTML parser?
The Free-TV/IPTV project favors manual string slicing over libraries like BeautifulSoup or html.parser to minimize dependencies and keep the build script lightweight. Since the markdown format is strictly controlled and generated by the maintainers, simple string manipulation is reliable and executes faster than parsing full HTML documents.
What happens if the img tag format changes?
If contributors modify the <img> tag structure—such as using single quotes for the src attribute or reordering attributes—the current parsing logic in make_playlist.py would fail to extract the URL correctly. The find('src="') method specifically searches for double quotes, so any deviation would require updating lines 104–106 to match the new pattern.
Where are the markdown files with channel data located?
The channel data resides in the lists/ directory at the root of the repository. Each country has its own markdown file (e.g., usa.md, germany.md) containing tables where each row includes the channel number, name, stream URL, logo <img> tag, and EPG ID.
How is the extracted logo URL used in the final playlist?
The extracted URL is assigned to the tvg-logo attribute in the M3U playlist's #EXTINF directive. This metadata tag is the standard way IPTV applications associate thumbnail images with specific channels, allowing players to display the logo in the channel guide and interface.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →