Hanime plugin
I dont know much about making plugin for yt-dlp, can anyone make this into a yt-dlp plugin please 🥺 🥺 🥺
import subprocess
import sys
import time
import re
from requests import get
from bs4 import BeautifulSoup
from selenium import webdriver # NOTE: selenium==4.9.0, also need brotli to decompress the data
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.firefox.options import Options
DEBUG = False
def get_signature_and_stime(url):
options = Options()
options.add_argument("--headless")
options.set_preference("general.useragent.override",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
try:
with webdriver.Firefox(service=Service(), options=options) as driver:
driver.set_page_load_timeout(30)
driver.get(url)
time.sleep(3)
signature = driver.execute_script("return window.ssignature || null;")
stime = driver.execute_script("return window.stime || null;")
if DEBUG:
print(f"Signature: {signature}\nStime: {stime}")
return signature, stime
except Exception as e:
print(f"Error: {e}")
return None, None
def get_json_download(referer_url, url_id, signature, stime):
api_url = f"https://cached.freeanimehentai.net/rapi/v7/downloads?id={url_id}&kind=requestlinks"
headers = {
"Accept": "application/json, text/plain, */*",
"Referer": referer_url,
"Origin": "https://hanime.tv",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"x-signature": signature or "",
"x-time": str(stime) or "",
"x-signature-version": "web2"
}
try:
response = get(api_url, headers=headers, timeout=30)
return response.json() if response.status_code == 200 else None
except Exception as e:
print(f"API Error: {e}")
return None
def download_video(json_data):
videos = []
for server in json_data.get("videos_manifest", {}).get("servers", []):
videos.extend([{
"id": s["id"],
"url": s["extra2"],
"filename": s["filename"],
"extension": s["extension"],
"height": s["height"]
} for s in server.get("streams", []) if "extra2" in s and s["extra2"]])
if not videos:
print("No videos found!")
return
for i, v in enumerate(videos, 1):
print(f"{i:2d}. {v['height']}p - {v['extension']}")
try:
selections = [int(idx) for idx in input("Select videos (comma-separated): ").split(",") if idx.strip()]
selected = [videos[i-1] for i in selections if 1 <= i <= len(videos)]
for v in selected:
print(f"\nDownloading {v['height']}p video...")
subprocess.run(["yt-dlp", "-o", v["filename"], v["url"]], check=True)
print("✓ Done!")
except (ValueError, KeyboardInterrupt):
print("\nDownload cancelled.")
def main():
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <URL>")
sys.exit(1)
BASE_URL = "https://hanime.tv"
try:
soup = BeautifulSoup(get(sys.argv[1]).text, 'html.parser')
href = next((a['href'] for a in soup.find_all("a", href=re.compile(r'/downloads/')) if a.get('href')), None)
if not href:
print("No download link found!")
return
download_url = BASE_URL + href
url_id = re.search(r'/downloads/(.+)', href).group(1)
signature, stime = get_signature_and_stime(download_url)
if not (signature and stime):
print("Failed to get signature/stime")
return
data = get_json_download(download_url, url_id, signature, stime)
if data:
download_video(data)
else:
print("Failed to get video data")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
main()
Posted Dec 3, 2025, 1:34 AM UTC
05