Skip to content

Instantly share code, notes, and snippets.

@rlaphoenix
Last active February 6, 2026 17:53
Show Gist options
  • Select an option

  • Save rlaphoenix/f10d3f39882011bdffee143bd504b149 to your computer and use it in GitHub Desktop.

Select an option

Save rlaphoenix/f10d3f39882011bdffee143bd504b149 to your computer and use it in GitHub Desktop.
"""
Script to scrape FilmOn for all channels and returns as tvg m3u8.
Includes Channel Name, Logo, and Category.
URI is an example proxied stream from https://gist.github.com/rlaphoenix/e18170c950a917890823eb53777a15a0
as using the official URI will just expire, useless.
"""
import sys
import requests
from pathlib import Path
# Note: Logos and Channel Names may be out of date, their website is ancient
M3U8_OUT_PATH = r"C:\Users\Justin\Desktop\filmon.m3u8"
GET_UP_TO_CHANNEL = 9999
LOGO_SIZE = "extra_big" # 'extra_big', 'big', or '' for 56x28 very small banner
SKIP_ADULT = False
SKIP_VR_EXP = True
SKIP_VOD_VOX = True
IGNORE_OUT_OF_REGION_CHANNELS = True # will just print the ID and move on, otherwise abrupt end
def get_channel_data(channel: int) -> dict:
return requests.get(
url=f"http://www.filmon.com/api-v2/channel/{channel}",
params={"protocol": "hls"},
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0"
}
).json()
playlists = []
try:
for n in range(1, GET_UP_TO_CHANNEL):
res = get_channel_data(n)
if res["code"] == 404:
continue # no channel
elif res["code"] == 403:
print(f"Channel {n} is not available in your region, unknown what channel it is.")
if not IGNORE_OUT_OF_REGION_CHANNELS:
sys.exit(1)
continue # not available in current region
data = res["data"]
if (
(SKIP_VR_EXP and data["is360"]) or \
(SKIP_ADULT and data["is_adult"]) or \
(SKIP_VOD_VOX and (data["is_vod"] or data["is_vox"]))
):
continue
playlist = (n, data["title"], data["group"].title())
playlists.append(playlist)
print(playlist)
except KeyboardInterrupt:
print("CTRL+C detected, cancelling scrape, saving m3u8 so far")
m3u8 = "\n".join([
"#EXTM3U",
*(
"\n".join([
f'#EXTINF:-1 tvg-logo="https://static.filmon.com/assets/channels/{n}/{LOGO_SIZE}_logo.png" group-title="{category}",{name}',
f"https://nas.domain.tld/iptv/filmon/{n}/high.m3u8"
])
for n, name, category in playlists
)
])
Path(M3U8_OUT_PATH).write_text(m3u8)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment