Skip to content

Instantly share code, notes, and snippets.

@r3code
Last active January 21, 2026 08:28
Show Gist options
  • Select an option

  • Save r3code/8a2ec623e3f556514928d77ddcae93de to your computer and use it in GitHub Desktop.

Select an option

Save r3code/8a2ec623e3f556514928d77ddcae93de to your computer and use it in GitHub Desktop.
kinescope.io video downloader

kinescope.io video downloader

  1. Install python3, download tools: ffmpeg and N_m3u8DL-RE
  2. Put kdl.py, ffmpeg and N_m3u8DL-RE into same folder
  3. Run python kdl.py it will ask you to input kinescope embed link (e.g. https://kinescope.io/embed/1234534) and referrer link (e.g. https://videos.mysite.org). kinescope forbids to access without a referrer.
  4. Wait for a download copletion.

kdl.py can automatically select the best quality of a video or you can choose it in a menu provided by N_m3u8DL-RE.
ffmpeg receives parts of the selected video and an audio and muxes them into output mp4 file.

Use your Browser developer tools to find a request to https://kinescope.io/embed/ an use in the script.

If you faced dash error

Best option to make sure that you are providing right referrer and embedded link is:

  1. Open in chrome
  2. Press F12
  3. Open your webpage, what you want to download
  4. Press ctrl+ F, and type "u0026"
  5. You will find list of urls, which contains videos. In Header tab you can grab right referrer and embedded link.
  6. If dash = re.findall(r'dash: {"src":"(.?)"', resp)[0].strip() still fails, then switch to response tab and find link, which contains "u0026" (what you found on step 4) , it wll loks like : https://kinescope.io/29402382-ec45-4ea0-b45f-be4fc4f34ff5/master.m3u8?expires=1731320757\u0026token= , without "\u0026token=" it exactly string , what code dash = re.findall(r'{"src":"(.?)"', resp)[0].strip() is trying to find, so just hardcode it

Thanks to @kunter

Updates

  • 2026-01-12 Parsing new Kinescope response format for a correct m3u8 link. Fixed IndexError: list index out of range at dash = re.findall(r'dash: {\"src\":\"(.*?)\"', dash)[0].strip()
import requests
import re
import subprocess
import json
from urllib.parse import unquote
m3u8DL_RE_path = 'N_m3u8DL-RE.exe'
link = input('\nkinescope embed link: ')
referrer_link = input('\nreferrer link: ')
select_best = input('\nselect best quality automatically (y/n) [hit ENTER to decline]: ')
headers = {
'authority': 'kinescope.io',
'referer': referrer_link,
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36',
}
resp = requests.get(link, headers=headers).text
try:
title = re.findall(r'<title>(.*?)</title>', resp)[0].strip()
print(title)
except IndexError:
title = input('video title: ')
# Поиск playerOptions
js_obj_match = re.search(r'var\s+playerOptions\s*=\s*(\{.*?\});\s*\n', resp, re.DOTALL)
final_url = None
if js_obj_match:
player_options_json_str = js_obj_match.group(1).strip()
try:
cleaned_json_str = player_options_json_str.replace('\\u0026', '&')
player_options = json.loads(cleaned_json_str)
sources = player_options.get("playlist", [{}])[0].get("sources", {})
final_url = sources.get("hls", {}).get("src") or sources.get("shakahls", {}).get("src")
except (json.JSONDecodeError, IndexError, KeyError, TypeError):
pass
if not final_url:
ld_json_match = re.search(r'<script type="application/ld\+json">\s*(.*?)\s*</script>', resp, re.DOTALL)
if ld_json_match:
ld_json_str = ld_json_match.group(1).strip()
try:
ld_json_data = json.loads(ld_json_str)
final_url = ld_json_data.get("contentUrl")
except json.JSONDecodeError:
pass
if not final_url:
print("\Error: Can't get stream URL (m3u8).")
exit(1)
final_url = unquote(final_url)
print(f'\nm3u8 link:\n{final_url}\n')
run_args = [
m3u8DL_RE_path,
'--concurrent-download',
'-H', f'referer: {link}',
'--log-level', 'INFO',
'--del-after-done',
'-M', 'format=mp4:muxer=ffmpeg',
'--save-name', title,
final_url
]
if select_best.lower().strip() == 'y':
run_args.append('--auto-select')
subprocess.run(run_args)
@Yur-ok
Copy link

Yur-ok commented Sep 2, 2024

Unfortunately I stuck here.

select best quality automatically (y/n) [hit ENTER to decline]: n

Traceback (most recent call last):
  File "/kdl.py", line 24, in <module>
    dash = re.findall(r'dash: {\"src\":\"(.*?)\"', resp)[0].strip()
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^
IndexError: list index out of range

@kl0p31
Copy link

kl0p31 commented Sep 21, 2024

IndexError: list index out of range

Me too(

@thundershturm
Copy link

I tried to modify a little bit this sript by deleting in 24 line "dash" bc in resp there is no string with it.

dash = re.findall(r'{\"src\":\"(.*?)\"', resp)[0].strip()

It worked and even downloaded .mp4 and .m4a files with errors like

An error occurred while sending the request.

And then during N_m3u8DL-RE tries to binary merge I've got


WARN : [h264 @ 0000020cb5a836c0] top block unavailable for requested intra mode -1
WARN : [h264 @ 0000020cb5a836c0] error while decoding MB 0 0, bytestream 425
WARN : [h264 @ 0000020cb5a836c0] error while decoding MB 2 0, bytestream -9
WARN : [h264 @ 0000020cb5a836c0] top block unavailable for requested intra mode -1
WARN : [h264 @ 0000020cb5a836c0] error while decoding MB 6 0, bytestream 21
WARN : [h264 @ 0000020cb5a836c0] Increasing reorder buffer to 2
WARN : [h264 @ 0000020cb5a836c0] error while decoding MB 76 0, bytestream -5

So mux failed. I guess it downloads files, but they're corrupted somehow

@ilyuzhko
Copy link

Traceback (most recent call last):
File "C:\Users\ops\Downloads\kdl\kdl.py", line 24, in
dash = re.findall(r'dash: {"src":"(.*?)"', resp)[0].strip()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^
IndexError: list index out of range

@kunter
Copy link

kunter commented Nov 10, 2024

I faced dash error as well and solved it by grabbing url manually.
Best option to make sure that you are providing right referrer and embedded link is:

  1. Open in chrome
  2. Press F12
  3. Open your webpage, what you want to download
  4. Press ctrl+ F, and type "u0026"
  5. You will find list of urls, which contains videos. In Header tab you can grab right referrer and embedded link.
  6. If dash = re.findall(r'dash: {"src":"(.?)"', resp)[0].strip() will still get you error, then switch to response tab and find link , which contains "u0026" (what you found on step 4) , it wll loks like :"https://kinescope.io/29402382-ec45-4ea0-b45f-be4fc4f34ff5/master.m3u8?expires=1731320757\u0026token=" , without "\u0026token=" it exactly string , what code dash = re.findall(r'{"src":"(.?)"', resp)[0].strip()
    trying to find, so just hardcode it

@r3code
Copy link
Author

r3code commented Nov 26, 2024

@kunter Thanks for your contribution! Added your workaround as a Reame part.

@fentezy16-maker
Copy link

Traceback (most recent call last):
File "C:\Users\fente\Desktop\Video\kdl.py", line 24, in
dash = re.findall(r'dash: {"src":"(.*?)"', resp)[0].strip()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^
IndexError: list index out of range

Help me please

@BaNoF
Copy link

BaNoF commented Jan 6, 2026

still working?

@BaNoF
Copy link

BaNoF commented Jan 6, 2026

о ты русский, оно чета не качается, у меня получилось скачать только видос и то не через твой скрипт, а через https://github.com/yt-dlp/yt-dlp

@r3code
Copy link
Author

r3code commented Jan 12, 2026

2026-01-12 Parsing new Kinescope response format for a correct m3u8 link. Fixed IndexError: list index out of range at dash = re.findall(r'dash: {"src":"(.*?)"', dash)[0].strip()

Successfully downloaded a video

@r3code
Copy link
Author

r3code commented Jan 13, 2026

@BaNoF Thanks for pointing an alternative https://github.com/yt-dlp/yt-dlp - it works too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment